diff options
author | Mike Lockwood <lockwood@google.com> | 2013-08-28 09:44:17 -0700 |
---|---|---|
committer | Mike Lockwood <lockwood@google.com> | 2013-08-28 09:44:17 -0700 |
commit | 9f6a119c8aa276432ece4fe2118bd8a3c9b1067e (patch) | |
tree | 1391656f9ad624aa99d4c7d2880d38121801a424 | |
parent | 647b6f5ed276bf93d95e5801e5e8af2802ef5fbb (diff) | |
download | frameworks_base-9f6a119c8aa276432ece4fe2118bd8a3c9b1067e.zip frameworks_base-9f6a119c8aa276432ece4fe2118bd8a3c9b1067e.tar.gz frameworks_base-9f6a119c8aa276432ece4fe2118bd8a3c9b1067e.tar.bz2 |
Move frameworks/base/tools/ to frameworks/tools/
Change-Id: I3ffafdab27cc4aca256c3a5806b630795b75d5c8
291 files changed, 0 insertions, 67426 deletions
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp deleted file mode 100644 index 3797b49..0000000 --- a/tools/aapt/AaptAssets.cpp +++ /dev/null @@ -1,2689 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// - -#include "AaptAssets.h" -#include "ResourceFilter.h" -#include "Main.h" - -#include <utils/misc.h> -#include <utils/SortedVector.h> - -#include <ctype.h> -#include <dirent.h> -#include <errno.h> - -static const char* kDefaultLocale = "default"; -static const char* kWildcardName = "any"; -static const char* kAssetDir = "assets"; -static const char* kResourceDir = "res"; -static const char* kValuesDir = "values"; -static const char* kMipmapDir = "mipmap"; -static const char* kInvalidChars = "/\\:"; -static const size_t kMaxAssetFileName = 100; - -static const String8 kResString(kResourceDir); - -/* - * Names of asset files must meet the following criteria: - * - * - the filename length must be less than kMaxAssetFileName bytes long - * (and can't be empty) - * - all characters must be 7-bit printable ASCII - * - none of { '/' '\\' ':' } - * - * Pass in just the filename, not the full path. - */ -static bool validateFileName(const char* fileName) -{ - const char* cp = fileName; - size_t len = 0; - - while (*cp != '\0') { - if ((*cp & 0x80) != 0) - return false; // reject high ASCII - if (*cp < 0x20 || *cp >= 0x7f) - return false; // reject control chars and 0x7f - if (strchr(kInvalidChars, *cp) != NULL) - return false; // reject path sep chars - cp++; - len++; - } - - if (len < 1 || len > kMaxAssetFileName) - return false; // reject empty or too long - - return true; -} - -// The default to use if no other ignore pattern is defined. -const char * const gDefaultIgnoreAssets = - "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"; -// The ignore pattern that can be passed via --ignore-assets in Main.cpp -const char * gUserIgnoreAssets = NULL; - -static bool isHidden(const char *root, const char *path) -{ - // Patterns syntax: - // - Delimiter is : - // - Entry can start with the flag ! to avoid printing a warning - // about the file being ignored. - // - Entry can have the flag "<dir>" to match only directories - // or <file> to match only files. Default is to match both. - // - Entry can be a simplified glob "<prefix>*" or "*<suffix>" - // where prefix/suffix must have at least 1 character (so that - // we don't match a '*' catch-all pattern.) - // - The special filenames "." and ".." are always ignored. - // - Otherwise the full string is matched. - // - match is not case-sensitive. - - if (strcmp(path, ".") == 0 || strcmp(path, "..") == 0) { - return true; - } - - const char *delim = ":"; - const char *p = gUserIgnoreAssets; - if (!p || !p[0]) { - p = getenv("ANDROID_AAPT_IGNORE"); - } - if (!p || !p[0]) { - p = gDefaultIgnoreAssets; - } - char *patterns = strdup(p); - - bool ignore = false; - bool chatty = true; - char *matchedPattern = NULL; - - String8 fullPath(root); - fullPath.appendPath(path); - FileType type = getFileType(fullPath); - - int plen = strlen(path); - - // Note: we don't have strtok_r under mingw. - for(char *token = strtok(patterns, delim); - !ignore && token != NULL; - token = strtok(NULL, delim)) { - chatty = token[0] != '!'; - if (!chatty) token++; // skip ! - if (strncasecmp(token, "<dir>" , 5) == 0) { - if (type != kFileTypeDirectory) continue; - token += 5; - } - if (strncasecmp(token, "<file>", 6) == 0) { - if (type != kFileTypeRegular) continue; - token += 6; - } - - matchedPattern = token; - int n = strlen(token); - - if (token[0] == '*') { - // Match *suffix - token++; - n--; - if (n <= plen) { - ignore = strncasecmp(token, path + plen - n, n) == 0; - } - } else if (n > 1 && token[n - 1] == '*') { - // Match prefix* - ignore = strncasecmp(token, path, n - 1) == 0; - } else { - ignore = strcasecmp(token, path) == 0; - } - } - - if (ignore && chatty) { - fprintf(stderr, " (skipping %s '%s' due to ANDROID_AAPT_IGNORE pattern '%s')\n", - type == kFileTypeDirectory ? "dir" : "file", - path, - matchedPattern ? matchedPattern : ""); - } - - free(patterns); - return ignore; -} - -// ========================================================================= -// ========================================================================= -// ========================================================================= - -status_t -AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value) -{ - ResTable_config config; - - // IMSI - MCC - if (getMccName(part.string(), &config)) { - *axis = AXIS_MCC; - *value = config.mcc; - return 0; - } - - // IMSI - MNC - if (getMncName(part.string(), &config)) { - *axis = AXIS_MNC; - *value = config.mnc; - return 0; - } - - // locale - language - if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) { - *axis = AXIS_LANGUAGE; - *value = part[1] << 8 | part[0]; - return 0; - } - - // locale - language_REGION - if (part.length() == 5 && isalpha(part[0]) && isalpha(part[1]) - && part[2] == '_' && isalpha(part[3]) && isalpha(part[4])) { - *axis = AXIS_LANGUAGE; - *value = (part[4] << 24) | (part[3] << 16) | (part[1] << 8) | (part[0]); - return 0; - } - - // layout direction - if (getLayoutDirectionName(part.string(), &config)) { - *axis = AXIS_LAYOUTDIR; - *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR); - return 0; - } - - // smallest screen dp width - if (getSmallestScreenWidthDpName(part.string(), &config)) { - *axis = AXIS_SMALLESTSCREENWIDTHDP; - *value = config.smallestScreenWidthDp; - return 0; - } - - // screen dp width - if (getScreenWidthDpName(part.string(), &config)) { - *axis = AXIS_SCREENWIDTHDP; - *value = config.screenWidthDp; - return 0; - } - - // screen dp height - if (getScreenHeightDpName(part.string(), &config)) { - *axis = AXIS_SCREENHEIGHTDP; - *value = config.screenHeightDp; - return 0; - } - - // screen layout size - if (getScreenLayoutSizeName(part.string(), &config)) { - *axis = AXIS_SCREENLAYOUTSIZE; - *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE); - return 0; - } - - // screen layout long - if (getScreenLayoutLongName(part.string(), &config)) { - *axis = AXIS_SCREENLAYOUTLONG; - *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG); - return 0; - } - - // orientation - if (getOrientationName(part.string(), &config)) { - *axis = AXIS_ORIENTATION; - *value = config.orientation; - return 0; - } - - // ui mode type - if (getUiModeTypeName(part.string(), &config)) { - *axis = AXIS_UIMODETYPE; - *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE); - return 0; - } - - // ui mode night - if (getUiModeNightName(part.string(), &config)) { - *axis = AXIS_UIMODENIGHT; - *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT); - return 0; - } - - // density - if (getDensityName(part.string(), &config)) { - *axis = AXIS_DENSITY; - *value = config.density; - return 0; - } - - // touchscreen - if (getTouchscreenName(part.string(), &config)) { - *axis = AXIS_TOUCHSCREEN; - *value = config.touchscreen; - return 0; - } - - // keyboard hidden - if (getKeysHiddenName(part.string(), &config)) { - *axis = AXIS_KEYSHIDDEN; - *value = config.inputFlags; - return 0; - } - - // keyboard - if (getKeyboardName(part.string(), &config)) { - *axis = AXIS_KEYBOARD; - *value = config.keyboard; - return 0; - } - - // navigation hidden - if (getNavHiddenName(part.string(), &config)) { - *axis = AXIS_NAVHIDDEN; - *value = config.inputFlags; - return 0; - } - - // navigation - if (getNavigationName(part.string(), &config)) { - *axis = AXIS_NAVIGATION; - *value = config.navigation; - return 0; - } - - // screen size - if (getScreenSizeName(part.string(), &config)) { - *axis = AXIS_SCREENSIZE; - *value = config.screenSize; - return 0; - } - - // version - if (getVersionName(part.string(), &config)) { - *axis = AXIS_VERSION; - *value = config.version; - return 0; - } - - return 1; -} - -uint32_t -AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis) -{ - switch (axis) { - case AXIS_MCC: - return config.mcc; - case AXIS_MNC: - return config.mnc; - case AXIS_LANGUAGE: - return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16) - | (((uint32_t)config.language[1]) << 8) | (config.language[0]); - case AXIS_LAYOUTDIR: - return config.screenLayout&ResTable_config::MASK_LAYOUTDIR; - case AXIS_SCREENLAYOUTSIZE: - return config.screenLayout&ResTable_config::MASK_SCREENSIZE; - case AXIS_ORIENTATION: - return config.orientation; - case AXIS_UIMODETYPE: - return (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE); - case AXIS_UIMODENIGHT: - return (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT); - case AXIS_DENSITY: - return config.density; - case AXIS_TOUCHSCREEN: - return config.touchscreen; - case AXIS_KEYSHIDDEN: - return config.inputFlags; - case AXIS_KEYBOARD: - return config.keyboard; - case AXIS_NAVIGATION: - return config.navigation; - case AXIS_SCREENSIZE: - return config.screenSize; - case AXIS_SMALLESTSCREENWIDTHDP: - return config.smallestScreenWidthDp; - case AXIS_SCREENWIDTHDP: - return config.screenWidthDp; - case AXIS_SCREENHEIGHTDP: - return config.screenHeightDp; - case AXIS_VERSION: - return config.version; - } - return 0; -} - -bool -AaptGroupEntry::configSameExcept(const ResTable_config& config, - const ResTable_config& otherConfig, int axis) -{ - for (int i=AXIS_START; i<=AXIS_END; i++) { - if (i == axis) { - continue; - } - if (getConfigValueForAxis(config, i) != getConfigValueForAxis(otherConfig, i)) { - return false; - } - } - return true; -} - -bool -AaptGroupEntry::initFromDirName(const char* dir, String8* resType) -{ - mParamsChanged = true; - - Vector<String8> parts; - - String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den; - String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers; - String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp; - - const char *p = dir; - const char *q; - while (NULL != (q = strchr(p, '-'))) { - String8 val(p, q-p); - val.toLower(); - parts.add(val); - //printf("part: %s\n", parts[parts.size()-1].string()); - p = q+1; - } - String8 val(p); - val.toLower(); - parts.add(val); - //printf("part: %s\n", parts[parts.size()-1].string()); - - const int N = parts.size(); - int index = 0; - String8 part = parts[index]; - - // resource type - if (!isValidResourceType(part)) { - return false; - } - *resType = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - - // imsi - mcc - if (getMccName(part.string())) { - mcc = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not mcc: %s\n", part.string()); - } - - // imsi - mnc - if (getMncName(part.string())) { - mnc = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not mcc: %s\n", part.string()); - } - - // locale - language - if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) { - loc = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not language: %s\n", part.string()); - } - - // locale - region - if (loc.length() > 0 - && part.length() == 3 && part[0] == 'r' && part[0] && part[1]) { - loc += "-"; - part.toUpper(); - loc += part.string() + 1; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not region: %s\n", part.string()); - } - - if (getLayoutDirectionName(part.string())) { - layoutDir = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not layout direction: %s\n", part.string()); - } - - if (getSmallestScreenWidthDpName(part.string())) { - smallestwidthdp = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not smallest screen width dp: %s\n", part.string()); - } - - if (getScreenWidthDpName(part.string())) { - widthdp = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not screen width dp: %s\n", part.string()); - } - - if (getScreenHeightDpName(part.string())) { - heightdp = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not screen height dp: %s\n", part.string()); - } - - if (getScreenLayoutSizeName(part.string())) { - layoutsize = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not screen layout size: %s\n", part.string()); - } - - if (getScreenLayoutLongName(part.string())) { - layoutlong = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not screen layout long: %s\n", part.string()); - } - - // orientation - if (getOrientationName(part.string())) { - orient = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not orientation: %s\n", part.string()); - } - - // ui mode type - if (getUiModeTypeName(part.string())) { - uiModeType = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not ui mode type: %s\n", part.string()); - } - - // ui mode night - if (getUiModeNightName(part.string())) { - uiModeNight = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not ui mode night: %s\n", part.string()); - } - - // density - if (getDensityName(part.string())) { - den = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not density: %s\n", part.string()); - } - - // touchscreen - if (getTouchscreenName(part.string())) { - touch = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not touchscreen: %s\n", part.string()); - } - - // keyboard hidden - if (getKeysHiddenName(part.string())) { - keysHidden = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not keysHidden: %s\n", part.string()); - } - - // keyboard - if (getKeyboardName(part.string())) { - key = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not keyboard: %s\n", part.string()); - } - - // navigation hidden - if (getNavHiddenName(part.string())) { - navHidden = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not navHidden: %s\n", part.string()); - } - - if (getNavigationName(part.string())) { - nav = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not navigation: %s\n", part.string()); - } - - if (getScreenSizeName(part.string())) { - size = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not screen size: %s\n", part.string()); - } - - if (getVersionName(part.string())) { - vers = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not version: %s\n", part.string()); - } - - // if there are extra parts, it doesn't match - return false; - -success: - this->mcc = mcc; - this->mnc = mnc; - this->locale = loc; - this->screenLayoutSize = layoutsize; - this->screenLayoutLong = layoutlong; - this->smallestScreenWidthDp = smallestwidthdp; - this->screenWidthDp = widthdp; - this->screenHeightDp = heightdp; - this->orientation = orient; - this->uiModeType = uiModeType; - this->uiModeNight = uiModeNight; - this->density = den; - this->touchscreen = touch; - this->keysHidden = keysHidden; - this->keyboard = key; - this->navHidden = navHidden; - this->navigation = nav; - this->screenSize = size; - this->layoutDirection = layoutDir; - this->version = vers; - - // what is this anyway? - this->vendor = ""; - - return true; -} - -String8 -AaptGroupEntry::toString() const -{ - String8 s = this->mcc; - s += ","; - s += this->mnc; - s += ","; - s += this->locale; - s += ","; - s += layoutDirection; - s += ","; - s += smallestScreenWidthDp; - s += ","; - s += screenWidthDp; - s += ","; - s += screenHeightDp; - s += ","; - s += screenLayoutSize; - s += ","; - s += screenLayoutLong; - s += ","; - s += this->orientation; - s += ","; - s += uiModeType; - s += ","; - s += uiModeNight; - s += ","; - s += density; - s += ","; - s += touchscreen; - s += ","; - s += keysHidden; - s += ","; - s += keyboard; - s += ","; - s += navHidden; - s += ","; - s += navigation; - s += ","; - s += screenSize; - s += ","; - s += version; - return s; -} - -String8 -AaptGroupEntry::toDirName(const String8& resType) const -{ - String8 s = resType; - if (this->mcc != "") { - if (s.length() > 0) { - s += "-"; - } - s += mcc; - } - if (this->mnc != "") { - if (s.length() > 0) { - s += "-"; - } - s += mnc; - } - if (this->locale != "") { - if (s.length() > 0) { - s += "-"; - } - s += locale; - } - if (this->layoutDirection != "") { - if (s.length() > 0) { - s += "-"; - } - s += layoutDirection; - } - if (this->smallestScreenWidthDp != "") { - if (s.length() > 0) { - s += "-"; - } - s += smallestScreenWidthDp; - } - if (this->screenWidthDp != "") { - if (s.length() > 0) { - s += "-"; - } - s += screenWidthDp; - } - if (this->screenHeightDp != "") { - if (s.length() > 0) { - s += "-"; - } - s += screenHeightDp; - } - if (this->screenLayoutSize != "") { - if (s.length() > 0) { - s += "-"; - } - s += screenLayoutSize; - } - if (this->screenLayoutLong != "") { - if (s.length() > 0) { - s += "-"; - } - s += screenLayoutLong; - } - if (this->orientation != "") { - if (s.length() > 0) { - s += "-"; - } - s += orientation; - } - if (this->uiModeType != "") { - if (s.length() > 0) { - s += "-"; - } - s += uiModeType; - } - if (this->uiModeNight != "") { - if (s.length() > 0) { - s += "-"; - } - s += uiModeNight; - } - if (this->density != "") { - if (s.length() > 0) { - s += "-"; - } - s += density; - } - if (this->touchscreen != "") { - if (s.length() > 0) { - s += "-"; - } - s += touchscreen; - } - if (this->keysHidden != "") { - if (s.length() > 0) { - s += "-"; - } - s += keysHidden; - } - if (this->keyboard != "") { - if (s.length() > 0) { - s += "-"; - } - s += keyboard; - } - if (this->navHidden != "") { - if (s.length() > 0) { - s += "-"; - } - s += navHidden; - } - if (this->navigation != "") { - if (s.length() > 0) { - s += "-"; - } - s += navigation; - } - if (this->screenSize != "") { - if (s.length() > 0) { - s += "-"; - } - s += screenSize; - } - if (this->version != "") { - if (s.length() > 0) { - s += "-"; - } - s += version; - } - - return s; -} - -bool AaptGroupEntry::getMccName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->mcc = 0; - return true; - } - const char* c = name; - if (tolower(*c) != 'm') return false; - c++; - if (tolower(*c) != 'c') return false; - c++; - if (tolower(*c) != 'c') return false; - c++; - - const char* val = c; - - while (*c >= '0' && *c <= '9') { - c++; - } - if (*c != 0) return false; - if (c-val != 3) return false; - - int d = atoi(val); - if (d != 0) { - if (out) out->mcc = d; - return true; - } - - return false; -} - -bool AaptGroupEntry::getMncName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->mcc = 0; - return true; - } - const char* c = name; - if (tolower(*c) != 'm') return false; - c++; - if (tolower(*c) != 'n') return false; - c++; - if (tolower(*c) != 'c') return false; - c++; - - const char* val = c; - - while (*c >= '0' && *c <= '9') { - c++; - } - if (*c != 0) return false; - if (c-val == 0 || c-val > 3) return false; - - if (out) { - out->mnc = atoi(val); - if (out->mnc == 0) { - out->mnc = ACONFIGURATION_MNC_ZERO; - } - } - - return true; -} - -/* - * Does this directory name fit the pattern of a locale dir ("en-rUS" or - * "default")? - * - * TODO: Should insist that the first two letters are lower case, and the - * second two are upper. - */ -bool AaptGroupEntry::getLocaleName(const char* fileName, - ResTable_config* out) -{ - if (strcmp(fileName, kWildcardName) == 0 - || strcmp(fileName, kDefaultLocale) == 0) { - if (out) { - out->language[0] = 0; - out->language[1] = 0; - out->country[0] = 0; - out->country[1] = 0; - } - return true; - } - - if (strlen(fileName) == 2 && isalpha(fileName[0]) && isalpha(fileName[1])) { - if (out) { - out->language[0] = fileName[0]; - out->language[1] = fileName[1]; - out->country[0] = 0; - out->country[1] = 0; - } - return true; - } - - if (strlen(fileName) == 5 && - isalpha(fileName[0]) && - isalpha(fileName[1]) && - fileName[2] == '-' && - isalpha(fileName[3]) && - isalpha(fileName[4])) { - if (out) { - out->language[0] = fileName[0]; - out->language[1] = fileName[1]; - out->country[0] = fileName[3]; - out->country[1] = fileName[4]; - } - return true; - } - - return false; -} - -bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR) - | ResTable_config::LAYOUTDIR_ANY; - return true; - } else if (strcmp(name, "ldltr") == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR) - | ResTable_config::LAYOUTDIR_LTR; - return true; - } else if (strcmp(name, "ldrtl") == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR) - | ResTable_config::LAYOUTDIR_RTL; - return true; - } - - return false; -} - -bool AaptGroupEntry::getScreenLayoutSizeName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) - | ResTable_config::SCREENSIZE_ANY; - return true; - } else if (strcmp(name, "small") == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) - | ResTable_config::SCREENSIZE_SMALL; - return true; - } else if (strcmp(name, "normal") == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) - | ResTable_config::SCREENSIZE_NORMAL; - return true; - } else if (strcmp(name, "large") == 0) { - if (out) out->screenLayout = - (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; -} - -bool AaptGroupEntry::getScreenLayoutLongName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_SCREENLONG) - | ResTable_config::SCREENLONG_ANY; - return true; - } else if (strcmp(name, "long") == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_SCREENLONG) - | ResTable_config::SCREENLONG_YES; - return true; - } else if (strcmp(name, "notlong") == 0) { - if (out) out->screenLayout = - (out->screenLayout&~ResTable_config::MASK_SCREENLONG) - | ResTable_config::SCREENLONG_NO; - return true; - } - - return false; -} - -bool AaptGroupEntry::getOrientationName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->orientation = out->ORIENTATION_ANY; - return true; - } else if (strcmp(name, "port") == 0) { - if (out) out->orientation = out->ORIENTATION_PORT; - return true; - } else if (strcmp(name, "land") == 0) { - if (out) out->orientation = out->ORIENTATION_LAND; - return true; - } else if (strcmp(name, "square") == 0) { - if (out) out->orientation = out->ORIENTATION_SQUARE; - return true; - } - - return false; -} - -bool AaptGroupEntry::getUiModeTypeName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE) - | ResTable_config::UI_MODE_TYPE_ANY; - return true; - } else if (strcmp(name, "desk") == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE) - | ResTable_config::UI_MODE_TYPE_DESK; - return true; - } else if (strcmp(name, "car") == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE) - | ResTable_config::UI_MODE_TYPE_CAR; - return true; - } else if (strcmp(name, "television") == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE) - | ResTable_config::UI_MODE_TYPE_TELEVISION; - return true; - } else if (strcmp(name, "appliance") == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE) - | ResTable_config::UI_MODE_TYPE_APPLIANCE; - return true; - } - - return false; -} - -bool AaptGroupEntry::getUiModeNightName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT) - | ResTable_config::UI_MODE_NIGHT_ANY; - return true; - } else if (strcmp(name, "night") == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT) - | ResTable_config::UI_MODE_NIGHT_YES; - return true; - } else if (strcmp(name, "notnight") == 0) { - if (out) out->uiMode = - (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT) - | ResTable_config::UI_MODE_NIGHT_NO; - return true; - } - - return false; -} - -bool AaptGroupEntry::getDensityName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->density = ResTable_config::DENSITY_DEFAULT; - return true; - } - - if (strcmp(name, "nodpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_NONE; - return true; - } - - if (strcmp(name, "ldpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_LOW; - return true; - } - - if (strcmp(name, "mdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_MEDIUM; - return true; - } - - if (strcmp(name, "tvdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_TV; - return true; - } - - if (strcmp(name, "hdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_HIGH; - return true; - } - - if (strcmp(name, "xhdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_XHIGH; - return true; - } - - if (strcmp(name, "xxhdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_XXHIGH; - return true; - } - - if (strcmp(name, "xxxhdpi") == 0) { - if (out) out->density = ResTable_config::DENSITY_XXXHIGH; - return true; - } - - char* c = (char*)name; - while (*c >= '0' && *c <= '9') { - c++; - } - - // check that we have 'dpi' after the last digit. - if (toupper(c[0]) != 'D' || - toupper(c[1]) != 'P' || - toupper(c[2]) != 'I' || - c[3] != 0) { - return false; - } - - // temporarily replace the first letter with \0 to - // use atoi. - char tmp = c[0]; - c[0] = '\0'; - - int d = atoi(name); - c[0] = tmp; - - if (d != 0) { - if (out) out->density = d; - return true; - } - - return false; -} - -bool AaptGroupEntry::getTouchscreenName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_ANY; - return true; - } else if (strcmp(name, "notouch") == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH; - return true; - } else if (strcmp(name, "stylus") == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS; - return true; - } else if (strcmp(name, "finger") == 0) { - if (out) out->touchscreen = out->TOUCHSCREEN_FINGER; - return true; - } - - return false; -} - -bool AaptGroupEntry::getKeysHiddenName(const char* name, - ResTable_config* out) -{ - uint8_t mask = 0; - uint8_t value = 0; - if (strcmp(name, kWildcardName) == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_ANY; - } else if (strcmp(name, "keysexposed") == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_NO; - } else if (strcmp(name, "keyshidden") == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_YES; - } else if (strcmp(name, "keyssoft") == 0) { - mask = ResTable_config::MASK_KEYSHIDDEN; - value = ResTable_config::KEYSHIDDEN_SOFT; - } - - if (mask != 0) { - if (out) out->inputFlags = (out->inputFlags&~mask) | value; - return true; - } - - return false; -} - -bool AaptGroupEntry::getKeyboardName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->keyboard = out->KEYBOARD_ANY; - return true; - } else if (strcmp(name, "nokeys") == 0) { - if (out) out->keyboard = out->KEYBOARD_NOKEYS; - return true; - } else if (strcmp(name, "qwerty") == 0) { - if (out) out->keyboard = out->KEYBOARD_QWERTY; - return true; - } else if (strcmp(name, "12key") == 0) { - if (out) out->keyboard = out->KEYBOARD_12KEY; - return true; - } - - return false; -} - -bool AaptGroupEntry::getNavHiddenName(const char* name, - ResTable_config* out) -{ - uint8_t mask = 0; - uint8_t value = 0; - if (strcmp(name, kWildcardName) == 0) { - mask = ResTable_config::MASK_NAVHIDDEN; - value = ResTable_config::NAVHIDDEN_ANY; - } else if (strcmp(name, "navexposed") == 0) { - mask = ResTable_config::MASK_NAVHIDDEN; - value = ResTable_config::NAVHIDDEN_NO; - } else if (strcmp(name, "navhidden") == 0) { - mask = ResTable_config::MASK_NAVHIDDEN; - value = ResTable_config::NAVHIDDEN_YES; - } - - if (mask != 0) { - if (out) out->inputFlags = (out->inputFlags&~mask) | value; - return true; - } - - return false; -} - -bool AaptGroupEntry::getNavigationName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->navigation = out->NAVIGATION_ANY; - return true; - } else if (strcmp(name, "nonav") == 0) { - if (out) out->navigation = out->NAVIGATION_NONAV; - return true; - } else if (strcmp(name, "dpad") == 0) { - if (out) out->navigation = out->NAVIGATION_DPAD; - return true; - } else if (strcmp(name, "trackball") == 0) { - if (out) out->navigation = out->NAVIGATION_TRACKBALL; - return true; - } else if (strcmp(name, "wheel") == 0) { - if (out) out->navigation = out->NAVIGATION_WHEEL; - return true; - } - - return false; -} - -bool AaptGroupEntry::getScreenSizeName(const char* name, ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->screenWidth = out->SCREENWIDTH_ANY; - out->screenHeight = out->SCREENHEIGHT_ANY; - } - return true; - } - - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || *x != 'x') return false; - String8 xName(name, x-name); - x++; - - const char* y = x; - while (*y >= '0' && *y <= '9') y++; - if (y == name || *y != 0) return false; - String8 yName(x, y-x); - - uint16_t w = (uint16_t)atoi(xName.string()); - uint16_t h = (uint16_t)atoi(yName.string()); - if (w < h) { - return false; - } - - if (out) { - out->screenWidth = w; - out->screenHeight = h; - } - - return true; -} - -bool AaptGroupEntry::getSmallestScreenWidthDpName(const char* name, ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->smallestScreenWidthDp = out->SCREENWIDTH_ANY; - } - return true; - } - - if (*name != 's') return false; - name++; - if (*name != 'w') return false; - name++; - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; - String8 xName(name, x-name); - - if (out) { - out->smallestScreenWidthDp = (uint16_t)atoi(xName.string()); - } - - return true; -} - -bool AaptGroupEntry::getScreenWidthDpName(const char* name, ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->screenWidthDp = out->SCREENWIDTH_ANY; - } - return true; - } - - if (*name != 'w') return false; - name++; - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; - String8 xName(name, x-name); - - if (out) { - out->screenWidthDp = (uint16_t)atoi(xName.string()); - } - - return true; -} - -bool AaptGroupEntry::getScreenHeightDpName(const char* name, ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->screenHeightDp = out->SCREENWIDTH_ANY; - } - return true; - } - - if (*name != 'h') return false; - name++; - const char* x = name; - while (*x >= '0' && *x <= '9') x++; - if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false; - String8 xName(name, x-name); - - if (out) { - out->screenHeightDp = (uint16_t)atoi(xName.string()); - } - - return true; -} - -bool AaptGroupEntry::getVersionName(const char* name, ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) { - out->sdkVersion = out->SDKVERSION_ANY; - out->minorVersion = out->MINORVERSION_ANY; - } - return true; - } - - if (*name != 'v') { - return false; - } - - name++; - const char* s = name; - while (*s >= '0' && *s <= '9') s++; - if (s == name || *s != 0) return false; - String8 sdkName(name, s-name); - - if (out) { - out->sdkVersion = (uint16_t)atoi(sdkName.string()); - out->minorVersion = 0; - } - - return true; -} - -int AaptGroupEntry::compare(const AaptGroupEntry& o) const -{ - int v = mcc.compare(o.mcc); - if (v == 0) v = mnc.compare(o.mnc); - if (v == 0) v = locale.compare(o.locale); - if (v == 0) v = layoutDirection.compare(o.layoutDirection); - if (v == 0) v = vendor.compare(o.vendor); - if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp); - if (v == 0) v = screenWidthDp.compare(o.screenWidthDp); - if (v == 0) v = screenHeightDp.compare(o.screenHeightDp); - if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize); - if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong); - if (v == 0) v = orientation.compare(o.orientation); - if (v == 0) v = uiModeType.compare(o.uiModeType); - if (v == 0) v = uiModeNight.compare(o.uiModeNight); - if (v == 0) v = density.compare(o.density); - if (v == 0) v = touchscreen.compare(o.touchscreen); - if (v == 0) v = keysHidden.compare(o.keysHidden); - if (v == 0) v = keyboard.compare(o.keyboard); - if (v == 0) v = navHidden.compare(o.navHidden); - if (v == 0) v = navigation.compare(o.navigation); - if (v == 0) v = screenSize.compare(o.screenSize); - if (v == 0) v = version.compare(o.version); - return v; -} - -const ResTable_config& AaptGroupEntry::toParams() const -{ - if (!mParamsChanged) { - return mParams; - } - - mParamsChanged = false; - ResTable_config& params(mParams); - memset(¶ms, 0, sizeof(params)); - getMccName(mcc.string(), ¶ms); - getMncName(mnc.string(), ¶ms); - getLocaleName(locale.string(), ¶ms); - getLayoutDirectionName(layoutDirection.string(), ¶ms); - getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), ¶ms); - getScreenWidthDpName(screenWidthDp.string(), ¶ms); - getScreenHeightDpName(screenHeightDp.string(), ¶ms); - getScreenLayoutSizeName(screenLayoutSize.string(), ¶ms); - getScreenLayoutLongName(screenLayoutLong.string(), ¶ms); - getOrientationName(orientation.string(), ¶ms); - getUiModeTypeName(uiModeType.string(), ¶ms); - getUiModeNightName(uiModeNight.string(), ¶ms); - getDensityName(density.string(), ¶ms); - getTouchscreenName(touchscreen.string(), ¶ms); - getKeysHiddenName(keysHidden.string(), ¶ms); - getKeyboardName(keyboard.string(), ¶ms); - getNavHiddenName(navHidden.string(), ¶ms); - getNavigationName(navigation.string(), ¶ms); - getScreenSizeName(screenSize.string(), ¶ms); - getVersionName(version.string(), ¶ms); - - // Fix up version number based on specified parameters. - int minSdk = 0; - if (params.smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY - || params.screenWidthDp != ResTable_config::SCREENWIDTH_ANY - || params.screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) { - minSdk = SDK_HONEYCOMB_MR2; - } else if ((params.uiMode&ResTable_config::MASK_UI_MODE_TYPE) - != ResTable_config::UI_MODE_TYPE_ANY - || (params.uiMode&ResTable_config::MASK_UI_MODE_NIGHT) - != ResTable_config::UI_MODE_NIGHT_ANY) { - minSdk = SDK_FROYO; - } else if ((params.screenLayout&ResTable_config::MASK_SCREENSIZE) - != ResTable_config::SCREENSIZE_ANY - || (params.screenLayout&ResTable_config::MASK_SCREENLONG) - != ResTable_config::SCREENLONG_ANY - || params.density != ResTable_config::DENSITY_DEFAULT) { - minSdk = SDK_DONUT; - } - - if (minSdk > params.sdkVersion) { - params.sdkVersion = minSdk; - } - - return params; -} - -// ========================================================================= -// ========================================================================= -// ========================================================================= - -void* AaptFile::editData(size_t size) -{ - if (size <= mBufferSize) { - mDataSize = size; - return mData; - } - size_t allocSize = (size*3)/2; - void* buf = realloc(mData, allocSize); - if (buf == NULL) { - return NULL; - } - mData = buf; - mDataSize = size; - mBufferSize = allocSize; - return buf; -} - -void* AaptFile::editData(size_t* outSize) -{ - if (outSize) { - *outSize = mDataSize; - } - return mData; -} - -void* AaptFile::padData(size_t wordSize) -{ - const size_t extra = mDataSize%wordSize; - if (extra == 0) { - return mData; - } - - size_t initial = mDataSize; - void* data = editData(initial+(wordSize-extra)); - if (data != NULL) { - memset(((uint8_t*)data) + initial, 0, wordSize-extra); - } - return data; -} - -status_t AaptFile::writeData(const void* data, size_t size) -{ - size_t end = mDataSize; - size_t total = size + end; - void* buf = editData(total); - if (buf == NULL) { - return UNKNOWN_ERROR; - } - memcpy(((char*)buf)+end, data, size); - return NO_ERROR; -} - -void AaptFile::clearData() -{ - if (mData != NULL) free(mData); - mData = NULL; - mDataSize = 0; - mBufferSize = 0; -} - -String8 AaptFile::getPrintableSource() const -{ - if (hasData()) { - String8 name(mGroupEntry.toDirName(String8())); - name.appendPath(mPath); - name.append(" #generated"); - return name; - } - return mSourceFile; -} - -// ========================================================================= -// ========================================================================= -// ========================================================================= - -status_t AaptGroup::addFile(const sp<AaptFile>& file) -{ - if (mFiles.indexOfKey(file->getGroupEntry()) < 0) { - file->mPath = mPath; - mFiles.add(file->getGroupEntry(), file); - return NO_ERROR; - } - -#if 0 - printf("Error adding file %s: group %s already exists in leaf=%s path=%s\n", - file->getSourceFile().string(), - file->getGroupEntry().toDirName(String8()).string(), - mLeaf.string(), mPath.string()); -#endif - - SourcePos(file->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.", - getPrintableSource().string()); - return UNKNOWN_ERROR; -} - -void AaptGroup::removeFile(size_t index) -{ - mFiles.removeItemsAt(index); -} - -void AaptGroup::print(const String8& prefix) const -{ - printf("%s%s\n", prefix.string(), getPath().string()); - const size_t N=mFiles.size(); - size_t i; - for (i=0; i<N; i++) { - sp<AaptFile> file = mFiles.valueAt(i); - const AaptGroupEntry& e = file->getGroupEntry(); - if (file->hasData()) { - printf("%s Gen: (%s) %d bytes\n", prefix.string(), e.toDirName(String8()).string(), - (int)file->getSize()); - } else { - printf("%s Src: (%s) %s\n", prefix.string(), e.toDirName(String8()).string(), - file->getPrintableSource().string()); - } - //printf("%s File Group Entry: %s\n", prefix.string(), - // file->getGroupEntry().toDirName(String8()).string()); - } -} - -String8 AaptGroup::getPrintableSource() const -{ - if (mFiles.size() > 0) { - // Arbitrarily pull the first source file out of the list. - return mFiles.valueAt(0)->getPrintableSource(); - } - - // Should never hit this case, but to be safe... - return getPath(); - -} - -// ========================================================================= -// ========================================================================= -// ========================================================================= - -status_t AaptDir::addFile(const String8& name, const sp<AaptGroup>& file) -{ - if (mFiles.indexOfKey(name) >= 0) { - return ALREADY_EXISTS; - } - mFiles.add(name, file); - return NO_ERROR; -} - -status_t AaptDir::addDir(const String8& name, const sp<AaptDir>& dir) -{ - if (mDirs.indexOfKey(name) >= 0) { - return ALREADY_EXISTS; - } - mDirs.add(name, dir); - return NO_ERROR; -} - -sp<AaptDir> AaptDir::makeDir(const String8& path) -{ - String8 name; - String8 remain = path; - - sp<AaptDir> subdir = this; - while (name = remain.walkPath(&remain), remain != "") { - subdir = subdir->makeDir(name); - } - - ssize_t i = subdir->mDirs.indexOfKey(name); - if (i >= 0) { - return subdir->mDirs.valueAt(i); - } - sp<AaptDir> dir = new AaptDir(name, subdir->mPath.appendPathCopy(name)); - subdir->mDirs.add(name, dir); - return dir; -} - -void AaptDir::removeFile(const String8& name) -{ - mFiles.removeItem(name); -} - -void AaptDir::removeDir(const String8& name) -{ - mDirs.removeItem(name); -} - -status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file) -{ - sp<AaptGroup> group; - if (mFiles.indexOfKey(leafName) >= 0) { - group = mFiles.valueFor(leafName); - } else { - group = new AaptGroup(leafName, mPath.appendPathCopy(leafName)); - mFiles.add(leafName, group); - } - - return group->addFile(file); -} - -ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, - const AaptGroupEntry& kind, const String8& resType, - sp<FilePathStore>& fullResPaths) -{ - Vector<String8> fileNames; - { - DIR* dir = NULL; - - dir = opendir(srcDir.string()); - if (dir == NULL) { - fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno)); - return UNKNOWN_ERROR; - } - - /* - * Slurp the filenames out of the directory. - */ - while (1) { - struct dirent* entry; - - entry = readdir(dir); - if (entry == NULL) - break; - - if (isHidden(srcDir.string(), entry->d_name)) - continue; - - String8 name(entry->d_name); - fileNames.add(name); - // Add fully qualified path for dependency purposes - // if we're collecting them - if (fullResPaths != NULL) { - fullResPaths->add(srcDir.appendPathCopy(name)); - } - } - closedir(dir); - } - - ssize_t count = 0; - - /* - * Stash away the files and recursively descend into subdirectories. - */ - const size_t N = fileNames.size(); - size_t i; - for (i = 0; i < N; i++) { - String8 pathName(srcDir); - FileType type; - - pathName.appendPath(fileNames[i].string()); - type = getFileType(pathName.string()); - if (type == kFileTypeDirectory) { - sp<AaptDir> subdir; - bool notAdded = false; - if (mDirs.indexOfKey(fileNames[i]) >= 0) { - subdir = mDirs.valueFor(fileNames[i]); - } else { - subdir = new AaptDir(fileNames[i], mPath.appendPathCopy(fileNames[i])); - notAdded = true; - } - ssize_t res = subdir->slurpFullTree(bundle, pathName, kind, - resType, fullResPaths); - if (res < NO_ERROR) { - return res; - } - if (res > 0 && notAdded) { - mDirs.add(fileNames[i], subdir); - } - count += res; - } else if (type == kFileTypeRegular) { - sp<AaptFile> file = new AaptFile(pathName, kind, resType); - status_t err = addLeafFile(fileNames[i], file); - if (err != NO_ERROR) { - return err; - } - - count++; - - } else { - if (bundle->getVerbose()) - printf(" (ignoring non-file/dir '%s')\n", pathName.string()); - } - } - - return count; -} - -status_t AaptDir::validate() const -{ - const size_t NF = mFiles.size(); - const size_t ND = mDirs.size(); - size_t i; - for (i = 0; i < NF; i++) { - if (!validateFileName(mFiles.valueAt(i)->getLeaf().string())) { - SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error( - "Invalid filename. Unable to add."); - return UNKNOWN_ERROR; - } - - size_t j; - for (j = i+1; j < NF; j++) { - if (strcasecmp(mFiles.valueAt(i)->getLeaf().string(), - mFiles.valueAt(j)->getLeaf().string()) == 0) { - SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error( - "File is case-insensitive equivalent to: %s", - mFiles.valueAt(j)->getPrintableSource().string()); - return UNKNOWN_ERROR; - } - - // TODO: if ".gz", check for non-.gz; if non-, check for ".gz" - // (this is mostly caught by the "marked" stuff, below) - } - - for (j = 0; j < ND; j++) { - if (strcasecmp(mFiles.valueAt(i)->getLeaf().string(), - mDirs.valueAt(j)->getLeaf().string()) == 0) { - SourcePos(mFiles.valueAt(i)->getPrintableSource(), -1).error( - "File conflicts with dir from: %s", - mDirs.valueAt(j)->getPrintableSource().string()); - return UNKNOWN_ERROR; - } - } - } - - for (i = 0; i < ND; i++) { - if (!validateFileName(mDirs.valueAt(i)->getLeaf().string())) { - SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error( - "Invalid directory name, unable to add."); - return UNKNOWN_ERROR; - } - - size_t j; - for (j = i+1; j < ND; j++) { - if (strcasecmp(mDirs.valueAt(i)->getLeaf().string(), - mDirs.valueAt(j)->getLeaf().string()) == 0) { - SourcePos(mDirs.valueAt(i)->getPrintableSource(), -1).error( - "Directory is case-insensitive equivalent to: %s", - mDirs.valueAt(j)->getPrintableSource().string()); - return UNKNOWN_ERROR; - } - } - - status_t err = mDirs.valueAt(i)->validate(); - if (err != NO_ERROR) { - return err; - } - } - - return NO_ERROR; -} - -void AaptDir::print(const String8& prefix) const -{ - const size_t ND=getDirs().size(); - size_t i; - for (i=0; i<ND; i++) { - getDirs().valueAt(i)->print(prefix); - } - - const size_t NF=getFiles().size(); - for (i=0; i<NF; i++) { - getFiles().valueAt(i)->print(prefix); - } -} - -String8 AaptDir::getPrintableSource() const -{ - if (mFiles.size() > 0) { - // Arbitrarily pull the first file out of the list as the source dir. - return mFiles.valueAt(0)->getPrintableSource().getPathDir(); - } - if (mDirs.size() > 0) { - // Or arbitrarily pull the first dir out of the list as the source dir. - return mDirs.valueAt(0)->getPrintableSource().getPathDir(); - } - - // Should never hit this case, but to be safe... - return mPath; - -} - -// ========================================================================= -// ========================================================================= -// ========================================================================= - -status_t AaptSymbols::applyJavaSymbols(const sp<AaptSymbols>& javaSymbols) -{ - status_t err = NO_ERROR; - size_t N = javaSymbols->mSymbols.size(); - for (size_t i=0; i<N; i++) { - const String8& name = javaSymbols->mSymbols.keyAt(i); - const AaptSymbolEntry& entry = javaSymbols->mSymbols.valueAt(i); - ssize_t pos = mSymbols.indexOfKey(name); - if (pos < 0) { - entry.sourcePos.error("Symbol '%s' declared with <java-symbol> not defined\n", name.string()); - err = UNKNOWN_ERROR; - continue; - } - //printf("**** setting symbol #%d/%d %s to isJavaSymbol=%d\n", - // i, N, name.string(), entry.isJavaSymbol ? 1 : 0); - mSymbols.editValueAt(pos).isJavaSymbol = entry.isJavaSymbol; - } - - N = javaSymbols->mNestedSymbols.size(); - for (size_t i=0; i<N; i++) { - const String8& name = javaSymbols->mNestedSymbols.keyAt(i); - const sp<AaptSymbols>& symbols = javaSymbols->mNestedSymbols.valueAt(i); - ssize_t pos = mNestedSymbols.indexOfKey(name); - if (pos < 0) { - SourcePos pos; - pos.error("Java symbol dir %s not defined\n", name.string()); - err = UNKNOWN_ERROR; - continue; - } - //printf("**** applying java symbols in dir %s\n", name.string()); - status_t myerr = mNestedSymbols.valueAt(pos)->applyJavaSymbols(symbols); - if (myerr != NO_ERROR) { - err = myerr; - } - } - - return err; -} - -// ========================================================================= -// ========================================================================= -// ========================================================================= - -AaptAssets::AaptAssets() - : AaptDir(String8(), String8()), - mChanged(false), mHaveIncludedAssets(false), mRes(NULL) -{ -} - -const SortedVector<AaptGroupEntry>& AaptAssets::getGroupEntries() const { - if (mChanged) { - } - return mGroupEntries; -} - -status_t AaptAssets::addFile(const String8& name, const sp<AaptGroup>& file) -{ - mChanged = true; - return AaptDir::addFile(name, file); -} - -sp<AaptFile> AaptAssets::addFile( - const String8& filePath, const AaptGroupEntry& entry, - const String8& srcDir, sp<AaptGroup>* outGroup, - const String8& resType) -{ - sp<AaptDir> dir = this; - sp<AaptGroup> group; - sp<AaptFile> file; - String8 root, remain(filePath), partialPath; - while (remain.length() > 0) { - root = remain.walkPath(&remain); - partialPath.appendPath(root); - - const String8 rootStr(root); - - if (remain.length() == 0) { - ssize_t i = dir->getFiles().indexOfKey(rootStr); - if (i >= 0) { - group = dir->getFiles().valueAt(i); - } else { - group = new AaptGroup(rootStr, filePath); - status_t res = dir->addFile(rootStr, group); - if (res != NO_ERROR) { - return NULL; - } - } - file = new AaptFile(srcDir.appendPathCopy(filePath), entry, resType); - status_t res = group->addFile(file); - if (res != NO_ERROR) { - return NULL; - } - break; - - } else { - ssize_t i = dir->getDirs().indexOfKey(rootStr); - if (i >= 0) { - dir = dir->getDirs().valueAt(i); - } else { - sp<AaptDir> subdir = new AaptDir(rootStr, partialPath); - status_t res = dir->addDir(rootStr, subdir); - if (res != NO_ERROR) { - return NULL; - } - dir = subdir; - } - } - } - - mGroupEntries.add(entry); - if (outGroup) *outGroup = group; - return file; -} - -void AaptAssets::addResource(const String8& leafName, const String8& path, - const sp<AaptFile>& file, const String8& resType) -{ - sp<AaptDir> res = AaptDir::makeDir(kResString); - String8 dirname = file->getGroupEntry().toDirName(resType); - sp<AaptDir> subdir = res->makeDir(dirname); - sp<AaptGroup> grr = new AaptGroup(leafName, path); - grr->addFile(file); - - subdir->addFile(leafName, grr); -} - - -ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) -{ - int count; - int totalCount = 0; - FileType type; - const Vector<const char *>& resDirs = bundle->getResourceSourceDirs(); - const size_t dirCount =resDirs.size(); - sp<AaptAssets> current = this; - - const int N = bundle->getFileSpecCount(); - - /* - * If a package manifest was specified, include that first. - */ - if (bundle->getAndroidManifestFile() != NULL) { - // place at root of zip. - String8 srcFile(bundle->getAndroidManifestFile()); - addFile(srcFile.getPathLeaf(), AaptGroupEntry(), srcFile.getPathDir(), - NULL, String8()); - totalCount++; - } - - /* - * If a directory of custom assets was supplied, slurp 'em up. - */ - if (bundle->getAssetSourceDir()) { - const char* assetDir = bundle->getAssetSourceDir(); - - FileType type = getFileType(assetDir); - if (type == kFileTypeNonexistent) { - fprintf(stderr, "ERROR: asset directory '%s' does not exist\n", assetDir); - return UNKNOWN_ERROR; - } - if (type != kFileTypeDirectory) { - fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDir); - return UNKNOWN_ERROR; - } - - String8 assetRoot(assetDir); - sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir)); - AaptGroupEntry group; - count = assetAaptDir->slurpFullTree(bundle, assetRoot, group, - String8(), mFullAssetPaths); - if (count < 0) { - totalCount = count; - goto bail; - } - if (count > 0) { - mGroupEntries.add(group); - } - totalCount += count; - - if (bundle->getVerbose()) - printf("Found %d custom asset file%s in %s\n", - count, (count==1) ? "" : "s", assetDir); - } - - /* - * If a directory of resource-specific assets was supplied, slurp 'em up. - */ - for (size_t i=0; i<dirCount; i++) { - const char *res = resDirs[i]; - if (res) { - type = getFileType(res); - if (type == kFileTypeNonexistent) { - fprintf(stderr, "ERROR: resource directory '%s' does not exist\n", res); - return UNKNOWN_ERROR; - } - if (type == kFileTypeDirectory) { - if (i>0) { - sp<AaptAssets> nextOverlay = new AaptAssets(); - current->setOverlay(nextOverlay); - current = nextOverlay; - current->setFullResPaths(mFullResPaths); - } - count = current->slurpResourceTree(bundle, String8(res)); - - if (count < 0) { - totalCount = count; - goto bail; - } - totalCount += count; - } - else { - fprintf(stderr, "ERROR: '%s' is not a directory\n", res); - return UNKNOWN_ERROR; - } - } - - } - /* - * Now do any additional raw files. - */ - for (int arg=0; arg<N; arg++) { - const char* assetDir = bundle->getFileSpecEntry(arg); - - FileType type = getFileType(assetDir); - if (type == kFileTypeNonexistent) { - fprintf(stderr, "ERROR: input directory '%s' does not exist\n", assetDir); - return UNKNOWN_ERROR; - } - if (type != kFileTypeDirectory) { - fprintf(stderr, "ERROR: '%s' is not a directory\n", assetDir); - return UNKNOWN_ERROR; - } - - String8 assetRoot(assetDir); - - if (bundle->getVerbose()) - printf("Processing raw dir '%s'\n", (const char*) assetDir); - - /* - * Do a recursive traversal of subdir tree. We don't make any - * guarantees about ordering, so we're okay with an inorder search - * using whatever order the OS happens to hand back to us. - */ - count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths); - if (count < 0) { - /* failure; report error and remove archive */ - totalCount = count; - goto bail; - } - totalCount += count; - - if (bundle->getVerbose()) - printf("Found %d asset file%s in %s\n", - count, (count==1) ? "" : "s", assetDir); - } - - count = validate(); - if (count != NO_ERROR) { - totalCount = count; - goto bail; - } - - count = filter(bundle); - if (count != NO_ERROR) { - totalCount = count; - goto bail; - } - -bail: - return totalCount; -} - -ssize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir, - const AaptGroupEntry& kind, - const String8& resType, - sp<FilePathStore>& fullResPaths) -{ - ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths); - if (res > 0) { - mGroupEntries.add(kind); - } - - return res; -} - -ssize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir) -{ - ssize_t err = 0; - - DIR* dir = opendir(srcDir.string()); - if (dir == NULL) { - fprintf(stderr, "ERROR: opendir(%s): %s\n", srcDir.string(), strerror(errno)); - return UNKNOWN_ERROR; - } - - status_t count = 0; - - /* - * Run through the directory, looking for dirs that match the - * expected pattern. - */ - while (1) { - struct dirent* entry = readdir(dir); - if (entry == NULL) { - break; - } - - if (isHidden(srcDir.string(), entry->d_name)) { - continue; - } - - String8 subdirName(srcDir); - subdirName.appendPath(entry->d_name); - - AaptGroupEntry group; - String8 resType; - bool b = group.initFromDirName(entry->d_name, &resType); - if (!b) { - fprintf(stderr, "invalid resource directory name: %s/%s\n", srcDir.string(), - entry->d_name); - err = -1; - continue; - } - - if (bundle->getMaxResVersion() != NULL && group.getVersionString().length() != 0) { - int maxResInt = atoi(bundle->getMaxResVersion()); - const char *verString = group.getVersionString().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) { - sp<AaptDir> dir = makeDir(resType); - ssize_t res = dir->slurpFullTree(bundle, subdirName, group, - resType, mFullResPaths); - if (res < 0) { - count = res; - goto bail; - } - if (res > 0) { - mGroupEntries.add(group); - count += res; - } - - // Only add this directory if we don't already have a resource dir - // for the current type. This ensures that we only add the dir once - // for all configs. - sp<AaptDir> rdir = resDir(resType); - if (rdir == NULL) { - mResDirs.add(dir); - } - } else { - if (bundle->getVerbose()) { - fprintf(stderr, " (ignoring file '%s')\n", subdirName.string()); - } - } - } - -bail: - closedir(dir); - dir = NULL; - - if (err != 0) { - return err; - } - return count; -} - -ssize_t -AaptAssets::slurpResourceZip(Bundle* bundle, const char* filename) -{ - int count = 0; - SortedVector<AaptGroupEntry> entries; - - ZipFile* zip = new ZipFile; - status_t err = zip->open(filename, ZipFile::kOpenReadOnly); - if (err != NO_ERROR) { - fprintf(stderr, "error opening zip file %s\n", filename); - count = err; - delete zip; - return -1; - } - - const int N = zip->getNumEntries(); - for (int i=0; i<N; i++) { - ZipEntry* entry = zip->getEntryByIndex(i); - if (entry->getDeleted()) { - continue; - } - - String8 entryName(entry->getFileName()); - - String8 dirName = entryName.getPathDir(); - sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName); - - String8 resType; - AaptGroupEntry kind; - - String8 remain; - if (entryName.walkPath(&remain) == kResourceDir) { - // these are the resources, pull their type out of the directory name - kind.initFromDirName(remain.walkPath().string(), &resType); - } else { - // these are untyped and don't have an AaptGroupEntry - } - if (entries.indexOf(kind) < 0) { - entries.add(kind); - mGroupEntries.add(kind); - } - - // use the one from the zip file if they both exist. - dir->removeFile(entryName.getPathLeaf()); - - sp<AaptFile> file = new AaptFile(entryName, kind, resType); - status_t err = dir->addLeafFile(entryName.getPathLeaf(), file); - if (err != NO_ERROR) { - fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.string()); - count = err; - goto bail; - } - file->setCompressionMethod(entry->getCompressionMethod()); - -#if 0 - if (entryName == "AndroidManifest.xml") { - printf("AndroidManifest.xml\n"); - } - printf("\n\nfile: %s\n", entryName.string()); -#endif - - size_t len = entry->getUncompressedLen(); - void* data = zip->uncompress(entry); - void* buf = file->editData(len); - memcpy(buf, data, len); - -#if 0 - const int OFF = 0; - const unsigned char* p = (unsigned char*)data; - const unsigned char* end = p+len; - p += OFF; - for (int i=0; i<32 && p < end; i++) { - printf("0x%03x ", i*0x10 + OFF); - for (int j=0; j<0x10 && p < end; j++) { - printf(" %02x", *p); - p++; - } - printf("\n"); - } -#endif - - free(data); - - count++; - } - -bail: - delete zip; - return count; -} - -status_t AaptAssets::filter(Bundle* bundle) -{ - ResourceFilter reqFilter; - status_t err = reqFilter.parse(bundle->getConfigurations()); - if (err != NO_ERROR) { - return err; - } - - ResourceFilter prefFilter; - err = prefFilter.parse(bundle->getPreferredConfigurations()); - if (err != NO_ERROR) { - return err; - } - - if (reqFilter.isEmpty() && prefFilter.isEmpty()) { - return NO_ERROR; - } - - if (bundle->getVerbose()) { - if (!reqFilter.isEmpty()) { - printf("Applying required filter: %s\n", - bundle->getConfigurations()); - } - if (!prefFilter.isEmpty()) { - printf("Applying preferred filter: %s\n", - bundle->getPreferredConfigurations()); - } - } - - const Vector<sp<AaptDir> >& resdirs = mResDirs; - const size_t ND = resdirs.size(); - for (size_t i=0; i<ND; i++) { - const sp<AaptDir>& dir = resdirs.itemAt(i); - if (dir->getLeaf() == kValuesDir) { - // The "value" dir is special since a single file defines - // multiple resources, so we can not do filtering on the - // files themselves. - continue; - } - if (dir->getLeaf() == kMipmapDir) { - // We also skip the "mipmap" directory, since the point of this - // is to include all densities without stripping. If you put - // other configurations in here as well they won't be stripped - // either... So don't do that. Seriously. What is wrong with you? - continue; - } - - const size_t NG = dir->getFiles().size(); - for (size_t j=0; j<NG; j++) { - sp<AaptGroup> grp = dir->getFiles().valueAt(j); - - // First remove any configurations we know we don't need. - for (size_t k=0; k<grp->getFiles().size(); k++) { - sp<AaptFile> file = grp->getFiles().valueAt(k); - if (k == 0 && grp->getFiles().size() == 1) { - // If this is the only file left, we need to keep it. - // Otherwise the resource IDs we are using will be inconsistent - // with what we get when not stripping. Sucky, but at least - // for now we can rely on the back-end doing another filtering - // pass to take this out and leave us with this resource name - // containing no entries. - continue; - } - if (file->getPath().getPathExtension() == ".xml") { - // We can't remove .xml files at this point, because when - // we parse them they may add identifier resources, so - // removing them can cause our resource identifiers to - // become inconsistent. - continue; - } - const ResTable_config& config(file->getGroupEntry().toParams()); - if (!reqFilter.match(config)) { - if (bundle->getVerbose()) { - printf("Pruning unneeded resource: %s\n", - file->getPrintableSource().string()); - } - grp->removeFile(k); - k--; - } - } - - // Quick check: no preferred filters, nothing more to do. - if (prefFilter.isEmpty()) { - continue; - } - - // Now deal with preferred configurations. - for (int axis=AXIS_START; axis<=AXIS_END; axis++) { - for (size_t k=0; k<grp->getFiles().size(); k++) { - sp<AaptFile> file = grp->getFiles().valueAt(k); - if (k == 0 && grp->getFiles().size() == 1) { - // If this is the only file left, we need to keep it. - // Otherwise the resource IDs we are using will be inconsistent - // with what we get when not stripping. Sucky, but at least - // for now we can rely on the back-end doing another filtering - // pass to take this out and leave us with this resource name - // containing no entries. - continue; - } - if (file->getPath().getPathExtension() == ".xml") { - // We can't remove .xml files at this point, because when - // we parse them they may add identifier resources, so - // removing them can cause our resource identifiers to - // become inconsistent. - continue; - } - const ResTable_config& config(file->getGroupEntry().toParams()); - if (!prefFilter.match(axis, config)) { - // This is a resource we would prefer not to have. Check - // to see if have a similar variation that we would like - // to have and, if so, we can drop it. - for (size_t m=0; m<grp->getFiles().size(); m++) { - if (m == k) continue; - sp<AaptFile> mfile = grp->getFiles().valueAt(m); - const ResTable_config& mconfig(mfile->getGroupEntry().toParams()); - if (AaptGroupEntry::configSameExcept(config, mconfig, axis)) { - if (prefFilter.match(axis, mconfig)) { - if (bundle->getVerbose()) { - printf("Pruning unneeded resource: %s\n", - file->getPrintableSource().string()); - } - grp->removeFile(k); - k--; - break; - } - } - } - } - } - } - } - } - - return NO_ERROR; -} - -sp<AaptSymbols> AaptAssets::getSymbolsFor(const String8& name) -{ - sp<AaptSymbols> sym = mSymbols.valueFor(name); - if (sym == NULL) { - sym = new AaptSymbols(); - mSymbols.add(name, sym); - } - return sym; -} - -sp<AaptSymbols> AaptAssets::getJavaSymbolsFor(const String8& name) -{ - sp<AaptSymbols> sym = mJavaSymbols.valueFor(name); - if (sym == NULL) { - sym = new AaptSymbols(); - mJavaSymbols.add(name, sym); - } - return sym; -} - -status_t AaptAssets::applyJavaSymbols() -{ - size_t N = mJavaSymbols.size(); - for (size_t i=0; i<N; i++) { - const String8& name = mJavaSymbols.keyAt(i); - const sp<AaptSymbols>& symbols = mJavaSymbols.valueAt(i); - ssize_t pos = mSymbols.indexOfKey(name); - if (pos < 0) { - SourcePos pos; - pos.error("Java symbol dir %s not defined\n", name.string()); - return UNKNOWN_ERROR; - } - //printf("**** applying java symbols in dir %s\n", name.string()); - status_t err = mSymbols.valueAt(pos)->applyJavaSymbols(symbols); - if (err != NO_ERROR) { - return err; - } - } - - return NO_ERROR; -} - -bool AaptAssets::isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const { - //printf("isJavaSymbol %s: public=%d, includePrivate=%d, isJavaSymbol=%d\n", - // sym.name.string(), sym.isPublic ? 1 : 0, includePrivate ? 1 : 0, - // sym.isJavaSymbol ? 1 : 0); - if (!mHavePrivateSymbols) return true; - if (sym.isPublic) return true; - if (includePrivate && sym.isJavaSymbol) return true; - return false; -} - -status_t AaptAssets::buildIncludedResources(Bundle* bundle) -{ - if (!mHaveIncludedAssets) { - // Add in all includes. - const Vector<const char*>& incl = bundle->getPackageIncludes(); - const size_t N=incl.size(); - for (size_t i=0; i<N; i++) { - if (bundle->getVerbose()) - printf("Including resources from package: %s\n", incl[i]); - if (!mIncludedAssets.addAssetPath(String8(incl[i]), NULL)) { - fprintf(stderr, "ERROR: Asset package include '%s' not found.\n", - incl[i]); - return UNKNOWN_ERROR; - } - } - mHaveIncludedAssets = true; - } - - return NO_ERROR; -} - -status_t AaptAssets::addIncludedResources(const sp<AaptFile>& file) -{ - const ResTable& res = getIncludedResources(); - // XXX dirty! - return const_cast<ResTable&>(res).add(file->getData(), file->getSize(), NULL); -} - -const ResTable& AaptAssets::getIncludedResources() const -{ - return mIncludedAssets.getResources(false); -} - -void AaptAssets::print(const String8& prefix) const -{ - String8 innerPrefix(prefix); - innerPrefix.append(" "); - String8 innerInnerPrefix(innerPrefix); - innerInnerPrefix.append(" "); - printf("%sConfigurations:\n", prefix.string()); - const size_t N=mGroupEntries.size(); - for (size_t i=0; i<N; i++) { - String8 cname = mGroupEntries.itemAt(i).toDirName(String8()); - printf("%s %s\n", prefix.string(), - cname != "" ? cname.string() : "(default)"); - } - - printf("\n%sFiles:\n", prefix.string()); - AaptDir::print(innerPrefix); - - printf("\n%sResource Dirs:\n", prefix.string()); - const Vector<sp<AaptDir> >& resdirs = mResDirs; - const size_t NR = resdirs.size(); - for (size_t i=0; i<NR; i++) { - const sp<AaptDir>& d = resdirs.itemAt(i); - printf("%s Type %s\n", prefix.string(), d->getLeaf().string()); - d->print(innerInnerPrefix); - } -} - -sp<AaptDir> AaptAssets::resDir(const String8& name) const -{ - const Vector<sp<AaptDir> >& resdirs = mResDirs; - const size_t N = resdirs.size(); - for (size_t i=0; i<N; i++) { - const sp<AaptDir>& d = resdirs.itemAt(i); - if (d->getLeaf() == name) { - return d; - } - } - return NULL; -} - -bool -valid_symbol_name(const String8& symbol) -{ - static char const * const KEYWORDS[] = { - "abstract", "assert", "boolean", "break", - "byte", "case", "catch", "char", "class", "const", "continue", - "default", "do", "double", "else", "enum", "extends", "final", - "finally", "float", "for", "goto", "if", "implements", "import", - "instanceof", "int", "interface", "long", "native", "new", "package", - "private", "protected", "public", "return", "short", "static", - "strictfp", "super", "switch", "synchronized", "this", "throw", - "throws", "transient", "try", "void", "volatile", "while", - "true", "false", "null", - NULL - }; - const char*const* k = KEYWORDS; - const char*const s = symbol.string(); - while (*k) { - if (0 == strcmp(s, *k)) { - return false; - } - k++; - } - return true; -} diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h deleted file mode 100644 index 5cfa913..0000000 --- a/tools/aapt/AaptAssets.h +++ /dev/null @@ -1,633 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Information about assets being operated on. -// -#ifndef __AAPT_ASSETS_H -#define __AAPT_ASSETS_H - -#include <stdlib.h> -#include <androidfw/AssetManager.h> -#include <androidfw/ResourceTypes.h> -#include <utils/KeyedVector.h> -#include <utils/RefBase.h> -#include <utils/SortedVector.h> -#include <utils/String8.h> -#include <utils/String8.h> -#include <utils/Vector.h> -#include "ZipFile.h" - -#include "Bundle.h" -#include "SourcePos.h" - -using namespace android; - - -extern const char * const gDefaultIgnoreAssets; -extern const char * gUserIgnoreAssets; - -bool valid_symbol_name(const String8& str); - -class AaptAssets; - -enum { - AXIS_NONE = 0, - AXIS_MCC = 1, - AXIS_MNC, - AXIS_LANGUAGE, - AXIS_REGION, - AXIS_SCREENLAYOUTSIZE, - AXIS_SCREENLAYOUTLONG, - AXIS_ORIENTATION, - AXIS_UIMODETYPE, - AXIS_UIMODENIGHT, - AXIS_DENSITY, - AXIS_TOUCHSCREEN, - AXIS_KEYSHIDDEN, - AXIS_KEYBOARD, - AXIS_NAVHIDDEN, - AXIS_NAVIGATION, - AXIS_SCREENSIZE, - AXIS_SMALLESTSCREENWIDTHDP, - AXIS_SCREENWIDTHDP, - AXIS_SCREENHEIGHTDP, - AXIS_LAYOUTDIR, - AXIS_VERSION, - - AXIS_START = AXIS_MCC, - AXIS_END = AXIS_VERSION, -}; - -/** - * This structure contains a specific variation of a single file out - * of all the variations it can have that we can have. - */ -struct AaptGroupEntry -{ -public: - AaptGroupEntry() : mParamsChanged(true) { } - AaptGroupEntry(const String8& _locale, const String8& _vendor) - : locale(_locale), vendor(_vendor), mParamsChanged(true) { } - - bool initFromDirName(const char* dir, String8* resType); - - static status_t parseNamePart(const String8& part, int* axis, uint32_t* value); - - static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis); - - static bool configSameExcept(const ResTable_config& config, - const ResTable_config& otherConfig, int axis); - - static bool getMccName(const char* name, ResTable_config* out = NULL); - static bool getMncName(const char* name, ResTable_config* out = NULL); - static bool getLocaleName(const char* name, ResTable_config* out = NULL); - static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL); - static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL); - static bool getOrientationName(const char* name, ResTable_config* out = NULL); - static bool getUiModeTypeName(const char* name, ResTable_config* out = NULL); - static bool getUiModeNightName(const char* name, ResTable_config* out = NULL); - static bool getDensityName(const char* name, ResTable_config* out = NULL); - static bool getTouchscreenName(const char* name, ResTable_config* out = NULL); - static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL); - static bool getKeyboardName(const char* name, ResTable_config* out = NULL); - static bool getNavigationName(const char* name, ResTable_config* out = NULL); - static bool getNavHiddenName(const char* name, ResTable_config* out = NULL); - static bool getScreenSizeName(const char* name, ResTable_config* out = NULL); - static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL); - static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL); - static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL); - static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL); - static bool getVersionName(const char* name, ResTable_config* out = NULL); - - int compare(const AaptGroupEntry& o) const; - - const ResTable_config& toParams() const; - - inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; } - inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; } - inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; } - inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; } - inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; } - inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; } - - String8 toString() const; - String8 toDirName(const String8& resType) const; - - const String8& getVersionString() const { return version; } - -private: - String8 mcc; - String8 mnc; - String8 locale; - String8 vendor; - String8 smallestScreenWidthDp; - String8 screenWidthDp; - String8 screenHeightDp; - String8 screenLayoutSize; - String8 screenLayoutLong; - String8 orientation; - String8 uiModeType; - String8 uiModeNight; - String8 density; - String8 touchscreen; - String8 keysHidden; - String8 keyboard; - String8 navHidden; - String8 navigation; - String8 screenSize; - String8 layoutDirection; - String8 version; - - mutable bool mParamsChanged; - mutable ResTable_config mParams; -}; - -inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs) -{ - return lhs.compare(rhs); -} - -inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs) -{ - return compare_type(lhs, rhs) < 0; -} - -class AaptGroup; -class FilePathStore; - -/** - * A single asset file we know about. - */ -class AaptFile : public RefBase -{ -public: - AaptFile(const String8& sourceFile, const AaptGroupEntry& groupEntry, - const String8& resType) - : mGroupEntry(groupEntry) - , mResourceType(resType) - , mSourceFile(sourceFile) - , mData(NULL) - , mDataSize(0) - , mBufferSize(0) - , mCompression(ZipEntry::kCompressStored) - { - //printf("new AaptFile created %s\n", (const char*)sourceFile); - } - virtual ~AaptFile() { - free(mData); - } - - const String8& getPath() const { return mPath; } - const AaptGroupEntry& getGroupEntry() const { return mGroupEntry; } - - // Data API. If there is data attached to the file, - // getSourceFile() is not used. - bool hasData() const { return mData != NULL; } - const void* getData() const { return mData; } - size_t getSize() const { return mDataSize; } - void* editData(size_t size); - void* editData(size_t* outSize = NULL); - void* padData(size_t wordSize); - status_t writeData(const void* data, size_t size); - void clearData(); - - const String8& getResourceType() const { return mResourceType; } - - // File API. If the file does not hold raw data, this is - // a full path to a file on the filesystem that holds its data. - const String8& getSourceFile() const { return mSourceFile; } - - String8 getPrintableSource() const; - - // Desired compression method, as per utils/ZipEntry.h. For example, - // no compression is ZipEntry::kCompressStored. - int getCompressionMethod() const { return mCompression; } - void setCompressionMethod(int c) { mCompression = c; } -private: - friend class AaptGroup; - - String8 mPath; - AaptGroupEntry mGroupEntry; - String8 mResourceType; - String8 mSourceFile; - void* mData; - size_t mDataSize; - size_t mBufferSize; - int mCompression; -}; - -/** - * A group of related files (the same file, with different - * vendor/locale variations). - */ -class AaptGroup : public RefBase -{ -public: - AaptGroup(const String8& leaf, const String8& path) - : mLeaf(leaf), mPath(path) { } - virtual ~AaptGroup() { } - - const String8& getLeaf() const { return mLeaf; } - - // Returns the relative path after the AaptGroupEntry dirs. - const String8& getPath() const { return mPath; } - - const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& getFiles() const - { return mFiles; } - - status_t addFile(const sp<AaptFile>& file); - void removeFile(size_t index); - - void print(const String8& prefix) const; - - String8 getPrintableSource() const; - -private: - String8 mLeaf; - String8 mPath; - - DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > mFiles; -}; - -/** - * A single directory of assets, which can contain files and other - * sub-directories. - */ -class AaptDir : public RefBase -{ -public: - AaptDir(const String8& leaf, const String8& path) - : mLeaf(leaf), mPath(path) { } - virtual ~AaptDir() { } - - const String8& getLeaf() const { return mLeaf; } - - const String8& getPath() const { return mPath; } - - const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; } - const DefaultKeyedVector<String8, sp<AaptDir> >& getDirs() const { return mDirs; } - - virtual status_t addFile(const String8& name, const sp<AaptGroup>& file); - - void removeFile(const String8& name); - void removeDir(const String8& name); - - /* - * Perform some sanity checks on the names of files and directories here. - * In particular: - * - Check for illegal chars in filenames. - * - Check filename length. - * - Check for presence of ".gz" and non-".gz" copies of same file. - * - Check for multiple files whose names match in a case-insensitive - * fashion (problematic for some systems). - * - * Comparing names against all other names is O(n^2). We could speed - * it up some by sorting the entries and being smarter about what we - * compare against, but I'm not expecting to have enough files in a - * single directory to make a noticeable difference in speed. - * - * Note that sorting here is not enough to guarantee that the package - * contents are sorted -- subsequent updates can rearrange things. - */ - status_t validate() const; - - void print(const String8& prefix) const; - - String8 getPrintableSource() const; - -private: - friend class AaptAssets; - - status_t addDir(const String8& name, const sp<AaptDir>& dir); - sp<AaptDir> makeDir(const String8& name); - status_t addLeafFile(const String8& leafName, - const sp<AaptFile>& file); - virtual ssize_t slurpFullTree(Bundle* bundle, - const String8& srcDir, - const AaptGroupEntry& kind, - const String8& resType, - sp<FilePathStore>& fullResPaths); - - String8 mLeaf; - String8 mPath; - - DefaultKeyedVector<String8, sp<AaptGroup> > mFiles; - DefaultKeyedVector<String8, sp<AaptDir> > mDirs; -}; - -/** - * All information we know about a particular symbol. - */ -class AaptSymbolEntry -{ -public: - AaptSymbolEntry() - : isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN) - { - } - AaptSymbolEntry(const String8& _name) - : name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN) - { - } - AaptSymbolEntry(const AaptSymbolEntry& o) - : name(o.name), sourcePos(o.sourcePos), isPublic(o.isPublic) - , isJavaSymbol(o.isJavaSymbol), comment(o.comment), typeComment(o.typeComment) - , typeCode(o.typeCode), int32Val(o.int32Val), stringVal(o.stringVal) - { - } - AaptSymbolEntry operator=(const AaptSymbolEntry& o) - { - sourcePos = o.sourcePos; - isPublic = o.isPublic; - isJavaSymbol = o.isJavaSymbol; - comment = o.comment; - typeComment = o.typeComment; - typeCode = o.typeCode; - int32Val = o.int32Val; - stringVal = o.stringVal; - return *this; - } - - const String8 name; - - SourcePos sourcePos; - bool isPublic; - bool isJavaSymbol; - - String16 comment; - String16 typeComment; - - enum { - TYPE_UNKNOWN = 0, - TYPE_INT32, - TYPE_STRING - }; - - int typeCode; - - // Value. May be one of these. - int32_t int32Val; - String8 stringVal; -}; - -/** - * A group of related symbols (such as indices into a string block) - * that have been generated from the assets. - */ -class AaptSymbols : public RefBase -{ -public: - AaptSymbols() { } - virtual ~AaptSymbols() { } - - status_t addSymbol(const String8& name, int32_t value, const SourcePos& pos) { - if (!check_valid_symbol_name(name, pos, "symbol")) { - return BAD_VALUE; - } - AaptSymbolEntry& sym = edit_symbol(name, &pos); - sym.typeCode = AaptSymbolEntry::TYPE_INT32; - sym.int32Val = value; - return NO_ERROR; - } - - status_t addStringSymbol(const String8& name, const String8& value, - const SourcePos& pos) { - if (!check_valid_symbol_name(name, pos, "symbol")) { - return BAD_VALUE; - } - AaptSymbolEntry& sym = edit_symbol(name, &pos); - sym.typeCode = AaptSymbolEntry::TYPE_STRING; - sym.stringVal = value; - return NO_ERROR; - } - - status_t makeSymbolPublic(const String8& name, const SourcePos& pos) { - if (!check_valid_symbol_name(name, pos, "symbol")) { - return BAD_VALUE; - } - AaptSymbolEntry& sym = edit_symbol(name, &pos); - sym.isPublic = true; - return NO_ERROR; - } - - status_t makeSymbolJavaSymbol(const String8& name, const SourcePos& pos) { - if (!check_valid_symbol_name(name, pos, "symbol")) { - return BAD_VALUE; - } - AaptSymbolEntry& sym = edit_symbol(name, &pos); - sym.isJavaSymbol = true; - return NO_ERROR; - } - - void appendComment(const String8& name, const String16& comment, const SourcePos& pos) { - if (comment.size() <= 0) { - return; - } - AaptSymbolEntry& sym = edit_symbol(name, &pos); - if (sym.comment.size() == 0) { - sym.comment = comment; - } else { - sym.comment.append(String16("\n")); - sym.comment.append(comment); - } - } - - void appendTypeComment(const String8& name, const String16& comment) { - if (comment.size() <= 0) { - return; - } - AaptSymbolEntry& sym = edit_symbol(name, NULL); - if (sym.typeComment.size() == 0) { - sym.typeComment = comment; - } else { - sym.typeComment.append(String16("\n")); - sym.typeComment.append(comment); - } - } - - sp<AaptSymbols> addNestedSymbol(const String8& name, const SourcePos& pos) { - if (!check_valid_symbol_name(name, pos, "nested symbol")) { - return NULL; - } - - sp<AaptSymbols> sym = mNestedSymbols.valueFor(name); - if (sym == NULL) { - sym = new AaptSymbols(); - mNestedSymbols.add(name, sym); - } - - return sym; - } - - status_t applyJavaSymbols(const sp<AaptSymbols>& javaSymbols); - - const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const - { return mSymbols; } - const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const - { return mNestedSymbols; } - - const String16& getComment(const String8& name) const - { return get_symbol(name).comment; } - const String16& getTypeComment(const String8& name) const - { return get_symbol(name).typeComment; } - -private: - bool check_valid_symbol_name(const String8& symbol, const SourcePos& pos, const char* label) { - if (valid_symbol_name(symbol)) { - return true; - } - pos.error("invalid %s: '%s'\n", label, symbol.string()); - return false; - } - AaptSymbolEntry& edit_symbol(const String8& symbol, const SourcePos* pos) { - ssize_t i = mSymbols.indexOfKey(symbol); - if (i < 0) { - i = mSymbols.add(symbol, AaptSymbolEntry(symbol)); - } - AaptSymbolEntry& sym = mSymbols.editValueAt(i); - if (pos != NULL && sym.sourcePos.line < 0) { - sym.sourcePos = *pos; - } - return sym; - } - const AaptSymbolEntry& get_symbol(const String8& symbol) const { - ssize_t i = mSymbols.indexOfKey(symbol); - if (i >= 0) { - return mSymbols.valueAt(i); - } - return mDefSymbol; - } - - KeyedVector<String8, AaptSymbolEntry> mSymbols; - DefaultKeyedVector<String8, sp<AaptSymbols> > mNestedSymbols; - AaptSymbolEntry mDefSymbol; -}; - -class ResourceTypeSet : public RefBase, - public KeyedVector<String8,sp<AaptGroup> > -{ -public: - ResourceTypeSet(); -}; - -// Storage for lists of fully qualified paths for -// resources encountered during slurping. -class FilePathStore : public RefBase, - public Vector<String8> -{ -public: - FilePathStore(); -}; - -/** - * Asset hierarchy being operated on. - */ -class AaptAssets : public AaptDir -{ -public: - AaptAssets(); - virtual ~AaptAssets() { delete mRes; } - - const String8& getPackage() const { return mPackage; } - void setPackage(const String8& package) { - mPackage = package; - mSymbolsPrivatePackage = package; - mHavePrivateSymbols = false; - } - - const SortedVector<AaptGroupEntry>& getGroupEntries() const; - - virtual status_t addFile(const String8& name, const sp<AaptGroup>& file); - - sp<AaptFile> addFile(const String8& filePath, - const AaptGroupEntry& entry, - const String8& srcDir, - sp<AaptGroup>* outGroup, - const String8& resType); - - void addResource(const String8& leafName, - const String8& path, - const sp<AaptFile>& file, - const String8& resType); - - void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); } - - ssize_t slurpFromArgs(Bundle* bundle); - - sp<AaptSymbols> getSymbolsFor(const String8& name); - - sp<AaptSymbols> getJavaSymbolsFor(const String8& name); - - status_t applyJavaSymbols(); - - const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; } - - String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; } - void setSymbolsPrivatePackage(const String8& pkg) { - mSymbolsPrivatePackage = pkg; - mHavePrivateSymbols = mSymbolsPrivatePackage != mPackage; - } - - bool havePrivateSymbols() const { return mHavePrivateSymbols; } - - bool isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const; - - status_t buildIncludedResources(Bundle* bundle); - status_t addIncludedResources(const sp<AaptFile>& file); - const ResTable& getIncludedResources() const; - - void print(const String8& prefix) const; - - inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; } - sp<AaptDir> resDir(const String8& name) const; - - inline sp<AaptAssets> getOverlay() { return mOverlay; } - inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; } - - inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; } - inline void - setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; } - - inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; } - inline void - setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; } - - inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; } - inline void - setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; } - -private: - virtual ssize_t slurpFullTree(Bundle* bundle, - const String8& srcDir, - const AaptGroupEntry& kind, - const String8& resType, - sp<FilePathStore>& fullResPaths); - - ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir); - ssize_t slurpResourceZip(Bundle* bundle, const char* filename); - - status_t filter(Bundle* bundle); - - String8 mPackage; - SortedVector<AaptGroupEntry> mGroupEntries; - DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols; - DefaultKeyedVector<String8, sp<AaptSymbols> > mJavaSymbols; - String8 mSymbolsPrivatePackage; - bool mHavePrivateSymbols; - - Vector<sp<AaptDir> > mResDirs; - - bool mChanged; - - bool mHaveIncludedAssets; - AssetManager mIncludedAssets; - - sp<AaptAssets> mOverlay; - KeyedVector<String8, sp<ResourceTypeSet> >* mRes; - - sp<FilePathStore> mFullResPaths; - sp<FilePathStore> mFullAssetPaths; -}; - -#endif // __AAPT_ASSETS_H - diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk deleted file mode 100644 index 452c60a..0000000 --- a/tools/aapt/Android.mk +++ /dev/null @@ -1,103 +0,0 @@ -# -# Copyright 2006 The Android Open Source Project -# -# Android Asset Packaging Tool -# - -# This tool is prebuilt if we're doing an app-only build. -ifeq ($(TARGET_BUILD_APPS),) - - -aapt_src_files := \ - AaptAssets.cpp \ - Command.cpp \ - CrunchCache.cpp \ - FileFinder.cpp \ - Main.cpp \ - Package.cpp \ - StringPool.cpp \ - XMLNode.cpp \ - ResourceFilter.cpp \ - ResourceIdCache.cpp \ - ResourceTable.cpp \ - Images.cpp \ - Resource.cpp \ - pseudolocalize.cpp \ - SourcePos.cpp \ - WorkQueue.cpp \ - ZipEntry.cpp \ - ZipFile.cpp \ - qsort_r_compat.c - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(aapt_src_files) - -LOCAL_CFLAGS += -Wno-format-y2k -ifeq (darwin,$(HOST_OS)) -LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS -endif - -LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS - -LOCAL_C_INCLUDES += external/libpng -LOCAL_C_INCLUDES += external/zlib - -LOCAL_STATIC_LIBRARIES := \ - libandroidfw \ - libutils \ - libcutils \ - libexpat \ - libpng \ - liblog - -ifeq ($(HOST_OS),linux) -LOCAL_LDLIBS += -lrt -ldl -lpthread -endif - -# Statically link libz for MinGW (Win SDK under Linux), -# and dynamically link for all others. -ifneq ($(strip $(USE_MINGW)),) - LOCAL_STATIC_LIBRARIES += libz -else - LOCAL_LDLIBS += -lz -endif - -LOCAL_MODULE := aapt - -include $(BUILD_HOST_EXECUTABLE) - -# aapt for running on the device -# ========================================================= -ifneq ($(SDK_ONLY),true) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(aapt_src_files) - -LOCAL_MODULE := aapt - -LOCAL_C_INCLUDES += bionic -LOCAL_C_INCLUDES += bionic/libstdc++/include -LOCAL_C_INCLUDES += external/stlport/stlport -LOCAL_C_INCLUDES += external/libpng -LOCAL_C_INCLUDES += external/zlib - -LOCAL_CFLAGS += -Wno-non-virtual-dtor - -LOCAL_SHARED_LIBRARIES := \ - libandroidfw \ - libutils \ - libcutils \ - libpng \ - liblog \ - libz - -LOCAL_STATIC_LIBRARIES := \ - libstlport_static \ - libexpat_static - -include $(BUILD_EXECUTABLE) -endif - -endif # TARGET_BUILD_APPS diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h deleted file mode 100644 index b67ca09..0000000 --- a/tools/aapt/Bundle.h +++ /dev/null @@ -1,309 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// State bundle. Used to pass around stuff like command-line args. -// -#ifndef __BUNDLE_H -#define __BUNDLE_H - -#include <stdlib.h> -#include <utils/Log.h> -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> -#include <utils/String8.h> -#include <utils/Vector.h> - -enum { - SDK_CUPCAKE = 3, - SDK_DONUT = 4, - SDK_ECLAIR = 5, - SDK_ECLAIR_0_1 = 6, - SDK_MR1 = 7, - SDK_FROYO = 8, - SDK_HONEYCOMB_MR2 = 13, - SDK_ICE_CREAM_SANDWICH = 14, - SDK_ICE_CREAM_SANDWICH_MR1 = 15, -}; - -/* - * Things we can do. - */ -typedef enum Command { - kCommandUnknown = 0, - kCommandVersion, - kCommandList, - kCommandDump, - kCommandAdd, - kCommandRemove, - kCommandPackage, - kCommandCrunch, - kCommandSingleCrunch, -} Command; - -/* - * Bundle of goodies, including everything specified on the command line. - */ -class Bundle { -public: - Bundle(void) - : mCmd(kCommandUnknown), mVerbose(false), mAndroidList(false), - mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false), - mUpdate(false), mExtending(false), - mRequireLocalization(false), mPseudolocalize(false), - mWantUTF16(false), mValues(false), mIncludeMetaData(false), - mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL), - mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL), - mAutoAddOverlay(false), mGenDependencies(false), - mAssetSourceDir(NULL), - mCrunchedOutputDir(NULL), mProguardFile(NULL), - mAndroidManifestFile(NULL), mPublicOutputFile(NULL), - mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL), - mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), - mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), mExtraPackages(NULL), - mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL), - mUseCrunchCache(false), mErrorOnFailedInsert(false), mOutputTextSymbols(NULL), - mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL), - mArgc(0), mArgv(NULL) - {} - ~Bundle(void) {} - - /* - * Set the command value. Returns "false" if it was previously set. - */ - Command getCommand(void) const { return mCmd; } - void setCommand(Command cmd) { mCmd = cmd; } - - /* - * Command modifiers. Not all modifiers are appropriate for all - * commands. - */ - bool getVerbose(void) const { return mVerbose; } - void setVerbose(bool val) { mVerbose = val; } - bool getAndroidList(void) const { return mAndroidList; } - void setAndroidList(bool val) { mAndroidList = val; } - bool getForce(void) const { return mForce; } - void setForce(bool val) { mForce = val; } - void setGrayscaleTolerance(int val) { mGrayscaleTolerance = val; } - int getGrayscaleTolerance() const { return mGrayscaleTolerance; } - bool getMakePackageDirs(void) const { return mMakePackageDirs; } - void setMakePackageDirs(bool val) { mMakePackageDirs = val; } - bool getUpdate(void) const { return mUpdate; } - void setUpdate(bool val) { mUpdate = val; } - bool getExtending(void) const { return mExtending; } - void setExtending(bool val) { mExtending = val; } - bool getRequireLocalization(void) const { return mRequireLocalization; } - void setRequireLocalization(bool val) { mRequireLocalization = val; } - bool getPseudolocalize(void) const { return mPseudolocalize; } - void setPseudolocalize(bool val) { mPseudolocalize = val; } - void setWantUTF16(bool val) { mWantUTF16 = val; } - bool getValues(void) const { return mValues; } - void setValues(bool val) { mValues = val; } - bool getIncludeMetaData(void) const { return mIncludeMetaData; } - void setIncludeMetaData(bool val) { mIncludeMetaData = val; } - int getCompressionMethod(void) const { return mCompressionMethod; } - void setCompressionMethod(int val) { mCompressionMethod = val; } - bool getJunkPath(void) const { return mJunkPath; } - void setJunkPath(bool val) { mJunkPath = val; } - const char* getOutputAPKFile() const { return mOutputAPKFile; } - void setOutputAPKFile(const char* val) { mOutputAPKFile = val; } - const char* getManifestPackageNameOverride() const { return mManifestPackageNameOverride; } - void setManifestPackageNameOverride(const char * val) { mManifestPackageNameOverride = val; } - const char* getInstrumentationPackageNameOverride() const { return mInstrumentationPackageNameOverride; } - void setInstrumentationPackageNameOverride(const char * val) { mInstrumentationPackageNameOverride = val; } - bool getAutoAddOverlay() { return mAutoAddOverlay; } - void setAutoAddOverlay(bool val) { mAutoAddOverlay = val; } - bool getGenDependencies() { return mGenDependencies; } - void setGenDependencies(bool val) { mGenDependencies = val; } - bool getErrorOnFailedInsert() { return mErrorOnFailedInsert; } - void setErrorOnFailedInsert(bool val) { mErrorOnFailedInsert = val; } - - bool getUTF16StringsOption() { - return mWantUTF16 || !isMinSdkAtLeast(SDK_FROYO); - } - - /* - * Input options. - */ - const char* getAssetSourceDir() const { return mAssetSourceDir; } - void setAssetSourceDir(const char* dir) { mAssetSourceDir = dir; } - const char* getCrunchedOutputDir() const { return mCrunchedOutputDir; } - void setCrunchedOutputDir(const char* dir) { mCrunchedOutputDir = dir; } - const char* getProguardFile() const { return mProguardFile; } - void setProguardFile(const char* file) { mProguardFile = file; } - const android::Vector<const char*>& getResourceSourceDirs() const { return mResourceSourceDirs; } - void addResourceSourceDir(const char* dir) { mResourceSourceDirs.insertAt(dir,0); } - const char* getAndroidManifestFile() const { return mAndroidManifestFile; } - void setAndroidManifestFile(const char* file) { mAndroidManifestFile = file; } - const char* getPublicOutputFile() const { return mPublicOutputFile; } - void setPublicOutputFile(const char* file) { mPublicOutputFile = file; } - const char* getRClassDir() const { return mRClassDir; } - void setRClassDir(const char* dir) { mRClassDir = dir; } - const char* getConfigurations() const { return mConfigurations.size() > 0 ? mConfigurations.string() : NULL; } - void addConfigurations(const char* val) { if (mConfigurations.size() > 0) { mConfigurations.append(","); mConfigurations.append(val); } else { mConfigurations = val; } } - const char* getPreferredConfigurations() const { return mPreferredConfigurations.size() > 0 ? mPreferredConfigurations.string() : NULL; } - void addPreferredConfigurations(const char* val) { if (mPreferredConfigurations.size() > 0) { mPreferredConfigurations.append(","); mPreferredConfigurations.append(val); } else { mPreferredConfigurations = val; } } - const char* getResourceIntermediatesDir() const { return mResourceIntermediatesDir; } - void setResourceIntermediatesDir(const char* dir) { mResourceIntermediatesDir = dir; } - const android::Vector<const char*>& getPackageIncludes() const { return mPackageIncludes; } - void addPackageInclude(const char* file) { mPackageIncludes.add(file); } - const android::Vector<const char*>& getJarFiles() const { return mJarFiles; } - void addJarFile(const char* file) { mJarFiles.add(file); } - const android::Vector<const char*>& getNoCompressExtensions() const { return mNoCompressExtensions; } - void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); } - - const char* getManifestMinSdkVersion() const { return mManifestMinSdkVersion; } - void setManifestMinSdkVersion(const char* val) { mManifestMinSdkVersion = val; } - 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; } - const char* getCustomPackage() const { return mCustomPackage; } - void setCustomPackage(const char* val) { mCustomPackage = val; } - const char* getExtraPackages() const { return mExtraPackages; } - void setExtraPackages(const char* val) { mExtraPackages = val; } - const char* getMaxResVersion() const { return mMaxResVersion; } - void setMaxResVersion(const char * val) { mMaxResVersion = val; } - bool getDebugMode() const { return mDebugMode; } - void setDebugMode(bool val) { mDebugMode = val; } - bool getNonConstantId() const { return mNonConstantId; } - void setNonConstantId(bool val) { mNonConstantId = val; } - const char* getProduct() const { return mProduct; } - void setProduct(const char * val) { mProduct = val; } - void setUseCrunchCache(bool val) { mUseCrunchCache = val; } - bool getUseCrunchCache() const { return mUseCrunchCache; } - const char* getOutputTextSymbols() const { return mOutputTextSymbols; } - void setOutputTextSymbols(const char* val) { mOutputTextSymbols = val; } - const char* getSingleCrunchInputFile() const { return mSingleCrunchInputFile; } - void setSingleCrunchInputFile(const char* val) { mSingleCrunchInputFile = val; } - const char* getSingleCrunchOutputFile() const { return mSingleCrunchOutputFile; } - void setSingleCrunchOutputFile(const char* val) { mSingleCrunchOutputFile = val; } - - /* - * Set and get the file specification. - * - * Note this does NOT make a copy of argv. - */ - void setFileSpec(char* const argv[], int argc) { - mArgc = argc; - mArgv = argv; - } - int getFileSpecCount(void) const { return mArgc; } - const char* getFileSpecEntry(int idx) const { return mArgv[idx]; } - void eatArgs(int n) { - if (n > mArgc) n = mArgc; - mArgv += n; - mArgc -= n; - } - -#if 0 - /* - * Package count. Nothing to do with anything else here; this is - * just a convenient place to stuff it so we don't have to pass it - * around everywhere. - */ - int getPackageCount(void) const { return mPackageCount; } - void setPackageCount(int val) { mPackageCount = val; } -#endif - - /* Certain features may only be available on a specific SDK level or - * above. SDK levels that have a non-numeric identifier are assumed - * to be newer than any SDK level that has a number designated. - */ - bool isMinSdkAtLeast(int desired) { - /* If the application specifies a minSdkVersion in the manifest - * then use that. Otherwise, check what the user specified on - * the command line. If neither, it's not available since - * the minimum SDK version is assumed to be 1. - */ - const char *minVer; - if (mManifestMinSdkVersion != NULL) { - minVer = mManifestMinSdkVersion; - } else if (mMinSdkVersion != NULL) { - minVer = mMinSdkVersion; - } else { - return false; - } - - char *end; - int minSdkNum = (int)strtol(minVer, &end, 0); - if (*end == '\0') { - if (minSdkNum < desired) { - return false; - } - } - return true; - } - -private: - /* commands & modifiers */ - Command mCmd; - bool mVerbose; - bool mAndroidList; - bool mForce; - int mGrayscaleTolerance; - bool mMakePackageDirs; - bool mUpdate; - bool mExtending; - bool mRequireLocalization; - bool mPseudolocalize; - bool mWantUTF16; - bool mValues; - bool mIncludeMetaData; - int mCompressionMethod; - bool mJunkPath; - const char* mOutputAPKFile; - const char* mManifestPackageNameOverride; - const char* mInstrumentationPackageNameOverride; - bool mAutoAddOverlay; - bool mGenDependencies; - const char* mAssetSourceDir; - const char* mCrunchedOutputDir; - const char* mProguardFile; - const char* mAndroidManifestFile; - const char* mPublicOutputFile; - const char* mRClassDir; - const char* mResourceIntermediatesDir; - android::String8 mConfigurations; - android::String8 mPreferredConfigurations; - android::Vector<const char*> mPackageIncludes; - android::Vector<const char*> mJarFiles; - android::Vector<const char*> mNoCompressExtensions; - android::Vector<const char*> mResourceSourceDirs; - - const char* mManifestMinSdkVersion; - const char* mMinSdkVersion; - const char* mTargetSdkVersion; - const char* mMaxSdkVersion; - const char* mVersionCode; - const char* mVersionName; - const char* mCustomPackage; - const char* mExtraPackages; - const char* mMaxResVersion; - bool mDebugMode; - bool mNonConstantId; - const char* mProduct; - bool mUseCrunchCache; - bool mErrorOnFailedInsert; - const char* mOutputTextSymbols; - const char* mSingleCrunchInputFile; - const char* mSingleCrunchOutputFile; - - /* file specification */ - int mArgc; - char* const* mArgv; - -#if 0 - /* misc stuff */ - int mPackageCount; -#endif - -}; - -#endif // __BUNDLE_H diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h deleted file mode 100644 index 0e65589..0000000 --- a/tools/aapt/CacheUpdater.h +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -// Abstraction of calls to system to make directories and delete files and -// wrapper to image processing. - -#ifndef CACHE_UPDATER_H -#define CACHE_UPDATER_H - -#include <utils/String8.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <stdio.h> -#include "Images.h" - -using namespace android; - -/** CacheUpdater - * This is a pure virtual class that declares abstractions of functions useful - * for managing a cache files. This manager is set up to be used in a - * mirror cache where the source tree is duplicated and filled with processed - * images. This class is abstracted to allow for dependency injection during - * unit testing. - * Usage: - * To update/add a file to the cache, call processImage - * To remove a file from the cache, call deleteFile - */ -class CacheUpdater { -public: - // Make sure all the directories along this path exist - virtual void ensureDirectoriesExist(String8 path) = 0; - - // Delete a file - virtual void deleteFile(String8 path) = 0; - - // Process an image from source out to dest - virtual void processImage(String8 source, String8 dest) = 0; -private: -}; - -/** SystemCacheUpdater - * This is an implementation of the above virtual cache updater specification. - * This implementations hits the filesystem to manage a cache and calls out to - * the PNG crunching in images.h to process images out to its cache components. - */ -class SystemCacheUpdater : public CacheUpdater { -public: - // Constructor to set bundle to pass to preProcessImage - SystemCacheUpdater (Bundle* b) - : bundle(b) { }; - - // Make sure all the directories along this path exist - virtual void ensureDirectoriesExist(String8 path) - { - // Check to see if we're dealing with a fully qualified path - String8 existsPath; - String8 toCreate; - String8 remains; - struct stat s; - - // Check optomistically to see if all directories exist. - // If something in the path doesn't exist, then walk the path backwards - // and find the place to start creating directories forward. - if (stat(path.string(),&s) == -1) { - // Walk backwards to find place to start creating directories - existsPath = path; - do { - // As we remove the end of existsPath add it to - // the string of paths to create. - toCreate = existsPath.getPathLeaf().appendPath(toCreate); - existsPath = existsPath.getPathDir(); - } while (stat(existsPath.string(),&s) == -1); - - // Walk forwards and build directories as we go - do { - // Advance to the next segment of the path - existsPath.appendPath(toCreate.walkPath(&remains)); - toCreate = remains; -#ifdef HAVE_MS_C_RUNTIME - _mkdir(existsPath.string()); -#else - mkdir(existsPath.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP); -#endif - } while (remains.length() > 0); - } //if - }; - - // Delete a file - virtual void deleteFile(String8 path) - { - if (remove(path.string()) != 0) - fprintf(stderr,"ERROR DELETING %s\n",path.string()); - }; - - // Process an image from source out to dest - virtual void processImage(String8 source, String8 dest) - { - // Make sure we're trying to write to a directory that is extant - ensureDirectoriesExist(dest.getPathDir()); - - preProcessImageToCache(bundle, source, dest); - }; -private: - Bundle* bundle; -}; - -#endif // CACHE_UPDATER_H
\ No newline at end of file diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp deleted file mode 100644 index 7fa8c9d..0000000 --- a/tools/aapt/Command.cpp +++ /dev/null @@ -1,2121 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Android Asset Packaging Tool main entry point. -// -#include "Main.h" -#include "Bundle.h" -#include "ResourceFilter.h" -#include "ResourceTable.h" -#include "Images.h" -#include "XMLNode.h" - -#include <utils/Log.h> -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> - -#include <fcntl.h> -#include <errno.h> - -using namespace android; - -/* - * Show version info. All the cool kids do it. - */ -int doVersion(Bundle* bundle) -{ - if (bundle->getFileSpecCount() != 0) { - printf("(ignoring extra arguments)\n"); - } - printf("Android Asset Packaging Tool, v0.2\n"); - - return 0; -} - - -/* - * Open the file read only. The call fails if the file doesn't exist. - * - * Returns NULL on failure. - */ -ZipFile* openReadOnly(const char* fileName) -{ - ZipFile* zip; - status_t result; - - zip = new ZipFile; - result = zip->open(fileName, ZipFile::kOpenReadOnly); - if (result != NO_ERROR) { - if (result == NAME_NOT_FOUND) { - fprintf(stderr, "ERROR: '%s' not found\n", fileName); - } else if (result == PERMISSION_DENIED) { - fprintf(stderr, "ERROR: '%s' access denied\n", fileName); - } else { - fprintf(stderr, "ERROR: failed opening '%s' as Zip file\n", - fileName); - } - delete zip; - return NULL; - } - - return zip; -} - -/* - * Open the file read-write. The file will be created if it doesn't - * already exist and "okayToCreate" is set. - * - * Returns NULL on failure. - */ -ZipFile* openReadWrite(const char* fileName, bool okayToCreate) -{ - ZipFile* zip = NULL; - status_t result; - int flags; - - flags = ZipFile::kOpenReadWrite; - if (okayToCreate) { - flags |= ZipFile::kOpenCreate; - } - - zip = new ZipFile; - result = zip->open(fileName, flags); - if (result != NO_ERROR) { - delete zip; - zip = NULL; - goto bail; - } - -bail: - return zip; -} - - -/* - * Return a short string describing the compression method. - */ -const char* compressionName(int method) -{ - if (method == ZipEntry::kCompressStored) { - return "Stored"; - } else if (method == ZipEntry::kCompressDeflated) { - return "Deflated"; - } else { - return "Unknown"; - } -} - -/* - * Return the percent reduction in size (0% == no compression). - */ -int calcPercent(long uncompressedLen, long compressedLen) -{ - if (!uncompressedLen) { - return 0; - } else { - return (int) (100.0 - (compressedLen * 100.0) / uncompressedLen + 0.5); - } -} - -/* - * Handle the "list" command, which can be a simple file dump or - * a verbose listing. - * - * The verbose listing closely matches the output of the Info-ZIP "unzip" - * command. - */ -int doList(Bundle* bundle) -{ - int result = 1; - ZipFile* zip = NULL; - const ZipEntry* entry; - long totalUncLen, totalCompLen; - const char* zipFileName; - - if (bundle->getFileSpecCount() != 1) { - fprintf(stderr, "ERROR: specify zip file name (only)\n"); - goto bail; - } - zipFileName = bundle->getFileSpecEntry(0); - - zip = openReadOnly(zipFileName); - if (zip == NULL) { - goto bail; - } - - int count, i; - - if (bundle->getVerbose()) { - printf("Archive: %s\n", zipFileName); - printf( - " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); - printf( - "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); - } - - totalUncLen = totalCompLen = 0; - - count = zip->getNumEntries(); - for (i = 0; i < count; i++) { - entry = zip->getEntryByIndex(i); - if (bundle->getVerbose()) { - char dateBuf[32]; - time_t when; - - when = entry->getModWhen(); - strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", - localtime(&when)); - - 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()); - } else { - printf("%s\n", entry->getFileName()); - } - - totalUncLen += entry->getUncompressedLen(); - totalCompLen += entry->getCompressedLen(); - } - - if (bundle->getVerbose()) { - printf( - "-------- ------- --- -------\n"); - printf("%8ld %7ld %2d%% %d files\n", - totalUncLen, - totalCompLen, - calcPercent(totalUncLen, totalCompLen), - zip->getNumEntries()); - } - - if (bundle->getAndroidList()) { - AssetManager assets; - if (!assets.addAssetPath(String8(zipFileName), NULL)) { - fprintf(stderr, "ERROR: list -a failed because assets could not be loaded\n"); - goto bail; - } - - const ResTable& res = assets.getResources(false); - if (&res == NULL) { - printf("\nNo resource table found.\n"); - } else { -#ifndef HAVE_ANDROID_OS - printf("\nResource table:\n"); - res.print(false); -#endif - } - - Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", - Asset::ACCESS_BUFFER); - if (manifestAsset == NULL) { - printf("\nNo AndroidManifest.xml found.\n"); - } else { - printf("\nAndroid manifest:\n"); - ResXMLTree tree; - tree.setTo(manifestAsset->getBuffer(true), - manifestAsset->getLength()); - printXMLBlock(&tree); - } - delete manifestAsset; - } - - result = 0; - -bail: - delete zip; - return result; -} - -static ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) -{ - size_t N = tree.getAttributeCount(); - for (size_t i=0; i<N; i++) { - if (tree.getAttributeNameResID(i) == attrRes) { - return (ssize_t)i; - } - } - return -1; -} - -String8 getAttribute(const ResXMLTree& tree, const char* ns, - const char* attr, String8* outError) -{ - ssize_t idx = tree.indexOfAttribute(ns, attr); - if (idx < 0) { - return String8(); - } - Res_value value; - if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - if (value.dataType != Res_value::TYPE_STRING) { - if (outError != NULL) { - *outError = "attribute is not a string value"; - } - return String8(); - } - } - size_t len; - const uint16_t* str = tree.getAttributeStringValue(idx, &len); - return str ? String8(str, len) : String8(); -} - -static String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) -{ - ssize_t idx = indexOfAttribute(tree, attrRes); - if (idx < 0) { - return String8(); - } - Res_value value; - if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - if (value.dataType != Res_value::TYPE_STRING) { - if (outError != NULL) { - *outError = "attribute is not a string value"; - } - return String8(); - } - } - size_t len; - const uint16_t* str = tree.getAttributeStringValue(idx, &len); - return str ? String8(str, len) : String8(); -} - -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 defValue; - } - Res_value value; - if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - 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 defValue; - } - } - return value.data; -} - -static int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree, - uint32_t attrRes, String8* outError, int32_t defValue = -1) -{ - ssize_t idx = indexOfAttribute(tree, attrRes); - if (idx < 0) { - return defValue; - } - Res_value value; - if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - if (value.dataType == Res_value::TYPE_REFERENCE) { - resTable->resolveReference(&value, 0); - } - 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 defValue; - } - } - return value.data; -} - -static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree, - uint32_t attrRes, String8* outError) -{ - ssize_t idx = indexOfAttribute(tree, attrRes); - if (idx < 0) { - return String8(); - } - Res_value value; - if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - if (value.dataType == Res_value::TYPE_STRING) { - size_t len; - const uint16_t* str = tree.getAttributeStringValue(idx, &len); - return str ? String8(str, len) : String8(); - } - resTable->resolveReference(&value, 0); - if (value.dataType != Res_value::TYPE_STRING) { - if (outError != NULL) { - *outError = "attribute is not a string value"; - } - return String8(); - } - } - size_t len; - const Res_value* value2 = &value; - const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len); - return str ? String8(str, len) : String8(); -} - -static void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable, - const ResXMLTree& tree, uint32_t attrRes, String8* outError) -{ - ssize_t idx = indexOfAttribute(tree, attrRes); - if (idx < 0) { - if (outError != NULL) { - *outError = "attribute could not be found"; - } - return; - } - if (tree.getAttributeValue(idx, value) != NO_ERROR) { - if (value->dataType == Res_value::TYPE_REFERENCE) { - resTable->resolveReference(value, 0); - } - // The attribute was found and was resolved if need be. - return; - } - if (outError != NULL) { - *outError = "error getting resolved resource attribute"; - } -} - -// These are attribute resource constants for the platform, as found -// in android.R.attr -enum { - LABEL_ATTR = 0x01010001, - ICON_ATTR = 0x01010002, - NAME_ATTR = 0x01010003, - DEBUGGABLE_ATTR = 0x0101000f, - VALUE_ATTR = 0x01010024, - VERSION_CODE_ATTR = 0x0101021b, - VERSION_NAME_ATTR = 0x0101021c, - SCREEN_ORIENTATION_ATTR = 0x0101001e, - MIN_SDK_VERSION_ATTR = 0x0101020c, - MAX_SDK_VERSION_ATTR = 0x01010271, - 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, - ANY_DENSITY_ATTR = 0x0101026c, - GL_ES_VERSION_ATTR = 0x01010281, - SMALL_SCREEN_ATTR = 0x01010284, - NORMAL_SCREEN_ATTR = 0x01010285, - LARGE_SCREEN_ATTR = 0x01010286, - XLARGE_SCREEN_ATTR = 0x010102bf, - REQUIRED_ATTR = 0x0101028e, - SCREEN_SIZE_ATTR = 0x010102ca, - SCREEN_DENSITY_ATTR = 0x010102cb, - REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364, - COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365, - LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366, - PUBLIC_KEY_ATTR = 0x010103a6, -}; - -const char *getComponentName(String8 &pkgName, String8 &componentName) { - ssize_t idx = componentName.find("."); - String8 retStr(pkgName); - if (idx == 0) { - retStr += componentName; - } else if (idx < 0) { - retStr += "."; - retStr += componentName; - } else { - return componentName.string(); - } - return retStr.string(); -} - -static void printCompatibleScreens(ResXMLTree& tree) { - size_t len; - ResXMLTree::event_code_t code; - int depth = 0; - bool first = true; - printf("compatible-screens:"); - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - depth--; - if (depth < 0) { - break; - } - continue; - } - if (code != ResXMLTree::START_TAG) { - continue; - } - depth++; - String8 tag(tree.getElementName(&len)); - if (tag == "screen") { - int32_t screenSize = getIntegerAttribute(tree, - SCREEN_SIZE_ATTR, NULL, -1); - int32_t screenDensity = getIntegerAttribute(tree, - SCREEN_DENSITY_ATTR, NULL, -1); - if (screenSize > 0 && screenDensity > 0) { - if (!first) { - printf(","); - } - first = false; - printf("'%d/%d'", screenSize, screenDensity); - } - } - } - printf("\n"); -} - -/* - * Handle the "dump" command, to extract select data from an archive. - */ -extern char CONSOLE_DATA[2925]; // see EOF -int doDump(Bundle* bundle) -{ - status_t result = UNKNOWN_ERROR; - Asset* asset = NULL; - - if (bundle->getFileSpecCount() < 1) { - fprintf(stderr, "ERROR: no dump option specified\n"); - return 1; - } - - if (bundle->getFileSpecCount() < 2) { - fprintf(stderr, "ERROR: no dump file specified\n"); - return 1; - } - - const char* option = bundle->getFileSpecEntry(0); - const char* filename = bundle->getFileSpecEntry(1); - - AssetManager assets; - void* assetsCookie; - if (!assets.addAssetPath(String8(filename), &assetsCookie)) { - fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); - return 1; - } - - // Make a dummy config for retrieving resources... we need to supply - // non-default values for some configs so that we can retrieve resources - // in the app that don't have a default. The most important of these is - // the API version because key resources like icons will have an implicit - // version if they are using newer config types like density. - ResTable_config config; - config.language[0] = 'e'; - config.language[1] = 'n'; - config.country[0] = 'U'; - config.country[1] = 'S'; - config.orientation = ResTable_config::ORIENTATION_PORT; - config.density = ResTable_config::DENSITY_MEDIUM; - config.sdkVersion = 10000; // Very high. - config.screenWidthDp = 320; - config.screenHeightDp = 480; - config.smallestScreenWidthDp = 320; - assets.setConfiguration(config); - - const ResTable& res = assets.getResources(false); - if (&res == NULL) { - fprintf(stderr, "ERROR: dump failed because no resource table was found\n"); - goto bail; - } - - if (strcmp("resources", option) == 0) { -#ifndef HAVE_ANDROID_OS - res.print(bundle->getValues()); -#endif - - } else if (strcmp("strings", option) == 0) { - const ResStringPool* pool = res.getTableStringBlock(0); - printStringPool(pool); - - } else if (strcmp("xmltree", option) == 0) { - if (bundle->getFileSpecCount() < 3) { - fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); - goto bail; - } - - for (int i=2; i<bundle->getFileSpecCount(); i++) { - const char* resname = bundle->getFileSpecEntry(i); - ResXMLTree tree; - asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER); - if (asset == NULL) { - fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); - goto bail; - } - - if (tree.setTo(asset->getBuffer(true), - asset->getLength()) != NO_ERROR) { - fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); - goto bail; - } - tree.restart(); - printXMLBlock(&tree); - tree.uninit(); - delete asset; - asset = NULL; - } - - } else if (strcmp("xmlstrings", option) == 0) { - if (bundle->getFileSpecCount() < 3) { - fprintf(stderr, "ERROR: no dump xmltree resource file specified\n"); - goto bail; - } - - for (int i=2; i<bundle->getFileSpecCount(); i++) { - const char* resname = bundle->getFileSpecEntry(i); - ResXMLTree tree; - asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER); - if (asset == NULL) { - fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname); - goto bail; - } - - if (tree.setTo(asset->getBuffer(true), - asset->getLength()) != NO_ERROR) { - fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname); - goto bail; - } - printStringPool(&tree.getStrings()); - delete asset; - asset = NULL; - } - - } else { - ResXMLTree tree; - asset = assets.openNonAsset("AndroidManifest.xml", - Asset::ACCESS_BUFFER); - if (asset == NULL) { - fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n"); - goto bail; - } - - if (tree.setTo(asset->getBuffer(true), - asset->getLength()) != NO_ERROR) { - fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n"); - goto bail; - } - tree.restart(); - - if (strcmp("permissions", option) == 0) { - size_t len; - ResXMLTree::event_code_t code; - int depth = 0; - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - depth--; - continue; - } - if (code != ResXMLTree::START_TAG) { - continue; - } - depth++; - String8 tag(tree.getElementName(&len)); - //printf("Depth %d tag %s\n", depth, tag.string()); - if (depth == 1) { - if (tag != "manifest") { - fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); - goto bail; - } - String8 pkg = getAttribute(tree, NULL, "package", NULL); - printf("package: %s\n", pkg.string()); - } else if (depth == 2 && tag == "permission") { - String8 error; - String8 name = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR: %s\n", error.string()); - goto bail; - } - printf("permission: %s\n", name.string()); - } else if (depth == 2 && tag == "uses-permission") { - String8 error; - String8 name = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR: %s\n", error.string()); - goto bail; - } - printf("uses-permission: %s\n", name.string()); - int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1); - if (!req) { - printf("optional-permission: %s\n", name.string()); - } - } - } - } else if (strcmp("badging", option) == 0) { - Vector<String8> locales; - res.getLocales(&locales); - - 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); - } - - size_t len; - ResXMLTree::event_code_t code; - int depth = 0; - String8 error; - bool withinActivity = false; - bool isMainActivity = false; - bool isLauncherActivity = false; - bool isSearchable = false; - bool withinApplication = false; - bool withinReceiver = false; - bool withinService = false; - bool withinIntentFilter = false; - bool hasMainActivity = false; - bool hasOtherActivities = false; - bool hasOtherReceivers = false; - bool hasOtherServices = false; - bool hasWallpaperService = false; - bool hasImeService = false; - bool hasWidgetReceivers = false; - bool hasIntentFilter = false; - bool actMainActivity = false; - bool actWidgetReceivers = false; - bool actImeService = false; - bool actWallpaperService = false; - - // These two implement the implicit permissions that are granted - // to pre-1.6 applications. - bool hasWriteExternalStoragePermission = false; - bool hasReadPhoneStatePermission = false; - - // If an app requests write storage, they will also get read storage. - bool hasReadExternalStoragePermission = false; - - // Implement transition to read and write call log. - bool hasReadContactsPermission = false; - bool hasWriteContactsPermission = false; - bool hasReadCallLogPermission = false; - bool hasWriteCallLogPermission = false; - - // This next group of variables is used to implement a group of - // backward-compatibility heuristics necessitated by the addition of - // some new uses-feature constants in 2.1 and 2.2. In most cases, the - // heuristic is "if an app requests a permission but doesn't explicitly - // request the corresponding <uses-feature>, presume it's there anyway". - bool specCameraFeature = false; // camera-related - bool specCameraAutofocusFeature = false; - bool reqCameraAutofocusFeature = false; - bool reqCameraFlashFeature = false; - bool hasCameraPermission = false; - bool specLocationFeature = false; // location-related - bool specNetworkLocFeature = false; - bool reqNetworkLocFeature = false; - bool specGpsFeature = false; - bool reqGpsFeature = false; - bool hasMockLocPermission = false; - bool hasCoarseLocPermission = false; - bool hasGpsPermission = false; - bool hasGeneralLocPermission = false; - bool specBluetoothFeature = false; // Bluetooth API-related - bool hasBluetoothPermission = false; - bool specMicrophoneFeature = false; // microphone-related - bool hasRecordAudioPermission = false; - bool specWiFiFeature = false; - bool hasWiFiPermission = false; - bool specTelephonyFeature = false; // telephony-related - bool reqTelephonySubFeature = false; - bool hasTelephonyPermission = false; - bool specTouchscreenFeature = false; // touchscreen-related - bool specMultitouchFeature = false; - bool reqDistinctMultitouchFeature = false; - bool specScreenPortraitFeature = false; - bool specScreenLandscapeFeature = false; - bool reqScreenPortraitFeature = false; - bool reqScreenLandscapeFeature = false; - // 2.2 also added some other features that apps can request, but that - // have no corresponding permission, so we cannot implement any - // back-compatibility heuristic for them. The below are thus unnecessary - // (but are retained here for documentary purposes.) - //bool specCompassFeature = false; - //bool specAccelerometerFeature = false; - //bool specProximityFeature = false; - //bool specAmbientLightFeature = false; - //bool specLiveWallpaperFeature = false; - - int targetSdk = 0; - int smallScreen = 1; - int normalScreen = 1; - int largeScreen = 1; - int xlargeScreen = 1; - int anyDensity = 1; - int requiresSmallestWidthDp = 0; - int compatibleWidthLimitDp = 0; - int largestWidthLimitDp = 0; - String8 pkg; - String8 activityName; - String8 activityLabel; - String8 activityIcon; - String8 receiverName; - String8 serviceName; - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - depth--; - if (depth < 2) { - withinApplication = false; - } else if (depth < 3) { - if (withinActivity && isMainActivity && isLauncherActivity) { - const char *aName = getComponentName(pkg, activityName); - printf("launchable-activity:"); - if (aName != NULL) { - printf(" name='%s' ", aName); - } - printf(" label='%s' icon='%s'\n", - activityLabel.string(), - activityIcon.string()); - } - if (!hasIntentFilter) { - hasOtherActivities |= withinActivity; - hasOtherReceivers |= withinReceiver; - hasOtherServices |= withinService; - } - withinActivity = false; - withinService = false; - withinReceiver = false; - hasIntentFilter = false; - isMainActivity = isLauncherActivity = false; - } else if (depth < 4) { - if (withinIntentFilter) { - if (withinActivity) { - hasMainActivity |= actMainActivity; - hasOtherActivities |= !actMainActivity; - } else if (withinReceiver) { - hasWidgetReceivers |= actWidgetReceivers; - hasOtherReceivers |= !actWidgetReceivers; - } else if (withinService) { - hasImeService |= actImeService; - hasWallpaperService |= actWallpaperService; - hasOtherServices |= (!actImeService && !actWallpaperService); - } - } - withinIntentFilter = false; - } - continue; - } - if (code != ResXMLTree::START_TAG) { - continue; - } - depth++; - String8 tag(tree.getElementName(&len)); - //printf("Depth %d, %s\n", depth, tag.string()); - if (depth == 1) { - if (tag != "manifest") { - fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); - goto bail; - } - pkg = getAttribute(tree, NULL, "package", NULL); - printf("package: name='%s' ", pkg.string()); - int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string()); - goto bail; - } - if (versionCode > 0) { - printf("versionCode='%d' ", versionCode); - } else { - printf("versionCode='' "); - } - String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); - goto bail; - } - printf("versionName='%s'\n", versionName.string()); - } else if (depth == 2) { - withinApplication = false; - if (tag == "application") { - withinApplication = true; - - String8 label; - const size_t NL = locales.size(); - for (size_t i=0; i<NL; i++) { - const char* localeStr = locales[i].string(); - assets.setLocale(localeStr != NULL ? localeStr : ""); - String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); - if (llabel != "") { - if (localeStr == NULL || strlen(localeStr) == 0) { - label = llabel; - printf("application-label:'%s'\n", llabel.string()); - } else { - if (label == "") { - label = llabel; - } - printf("application-label-%s:'%s'\n", localeStr, - llabel.string()); - } - } - } - - ResTable_config tmpConfig = config; - const size_t ND = densities.size(); - for (size_t i=0; i<ND; i++) { - tmpConfig.density = densities[i]; - assets.setConfiguration(tmpConfig); - String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); - if (icon != "") { - printf("application-icon-%d:'%s'\n", densities[i], icon.string()); - } - } - assets.setConfiguration(config); - - String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); - goto bail; - } - int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string()); - goto bail; - } - printf("application: label='%s' ", label.string()); - printf("icon='%s'\n", icon.string()); - if (testOnly != 0) { - printf("testOnly='%d'\n", testOnly); - } - - int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string()); - goto bail; - } - if (debuggable != 0) { - printf("application-debuggable\n"); - } - } 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, MAX_SDK_VERSION_ATTR, NULL, -1); - if (code != -1) { - printf("maxSdkVersion:'%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-configuration:"); - 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-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); - xlargeScreen = getIntegerAttribute(tree, - XLARGE_SCREEN_ATTR, NULL, 1); - anyDensity = getIntegerAttribute(tree, - ANY_DENSITY_ATTR, NULL, 1); - requiresSmallestWidthDp = getIntegerAttribute(tree, - REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0); - compatibleWidthLimitDp = getIntegerAttribute(tree, - COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0); - largestWidthLimitDp = getIntegerAttribute(tree, - LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0); - } else if (tag == "uses-feature") { - String8 name = getAttribute(tree, NAME_ATTR, &error); - - if (name != "" && error == "") { - int req = getIntegerAttribute(tree, - REQUIRED_ATTR, NULL, 1); - - if (name == "android.hardware.camera") { - specCameraFeature = true; - } else if (name == "android.hardware.camera.autofocus") { - // these have no corresponding permission to check for, - // but should imply the foundational camera permission - reqCameraAutofocusFeature = reqCameraAutofocusFeature || req; - specCameraAutofocusFeature = true; - } else if (req && (name == "android.hardware.camera.flash")) { - // these have no corresponding permission to check for, - // but should imply the foundational camera permission - reqCameraFlashFeature = true; - } else if (name == "android.hardware.location") { - specLocationFeature = true; - } else if (name == "android.hardware.location.network") { - specNetworkLocFeature = true; - reqNetworkLocFeature = reqNetworkLocFeature || req; - } else if (name == "android.hardware.location.gps") { - specGpsFeature = true; - reqGpsFeature = reqGpsFeature || req; - } else if (name == "android.hardware.bluetooth") { - specBluetoothFeature = true; - } else if (name == "android.hardware.touchscreen") { - specTouchscreenFeature = true; - } else if (name == "android.hardware.touchscreen.multitouch") { - specMultitouchFeature = true; - } else if (name == "android.hardware.touchscreen.multitouch.distinct") { - reqDistinctMultitouchFeature = reqDistinctMultitouchFeature || req; - } else if (name == "android.hardware.microphone") { - specMicrophoneFeature = true; - } else if (name == "android.hardware.wifi") { - specWiFiFeature = true; - } else if (name == "android.hardware.telephony") { - specTelephonyFeature = true; - } else if (req && (name == "android.hardware.telephony.gsm" || - name == "android.hardware.telephony.cdma")) { - // these have no corresponding permission to check for, - // but should imply the foundational telephony permission - reqTelephonySubFeature = true; - } else if (name == "android.hardware.screen.portrait") { - specScreenPortraitFeature = true; - } else if (name == "android.hardware.screen.landscape") { - specScreenLandscapeFeature = true; - } - printf("uses-feature%s:'%s'\n", - req ? "" : "-not-required", name.string()); - } else { - int vers = getIntegerAttribute(tree, - GL_ES_VERSION_ATTR, &error); - if (error == "") { - printf("uses-gl-es:'0x%x'\n", vers); - } - } - } else if (tag == "uses-permission") { - String8 name = getAttribute(tree, NAME_ATTR, &error); - if (name != "" && error == "") { - if (name == "android.permission.CAMERA") { - hasCameraPermission = true; - } else if (name == "android.permission.ACCESS_FINE_LOCATION") { - hasGpsPermission = true; - } else if (name == "android.permission.ACCESS_MOCK_LOCATION") { - hasMockLocPermission = true; - } else if (name == "android.permission.ACCESS_COARSE_LOCATION") { - hasCoarseLocPermission = true; - } else if (name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" || - name == "android.permission.INSTALL_LOCATION_PROVIDER") { - hasGeneralLocPermission = true; - } else if (name == "android.permission.BLUETOOTH" || - name == "android.permission.BLUETOOTH_ADMIN") { - hasBluetoothPermission = true; - } else if (name == "android.permission.RECORD_AUDIO") { - hasRecordAudioPermission = true; - } else if (name == "android.permission.ACCESS_WIFI_STATE" || - name == "android.permission.CHANGE_WIFI_STATE" || - name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") { - hasWiFiPermission = true; - } else if (name == "android.permission.CALL_PHONE" || - name == "android.permission.CALL_PRIVILEGED" || - name == "android.permission.MODIFY_PHONE_STATE" || - name == "android.permission.PROCESS_OUTGOING_CALLS" || - name == "android.permission.READ_SMS" || - name == "android.permission.RECEIVE_SMS" || - name == "android.permission.RECEIVE_MMS" || - name == "android.permission.RECEIVE_WAP_PUSH" || - name == "android.permission.SEND_SMS" || - name == "android.permission.WRITE_APN_SETTINGS" || - name == "android.permission.WRITE_SMS") { - hasTelephonyPermission = true; - } else if (name == "android.permission.WRITE_EXTERNAL_STORAGE") { - hasWriteExternalStoragePermission = true; - } else if (name == "android.permission.READ_EXTERNAL_STORAGE") { - hasReadExternalStoragePermission = true; - } else if (name == "android.permission.READ_PHONE_STATE") { - hasReadPhoneStatePermission = true; - } else if (name == "android.permission.READ_CONTACTS") { - hasReadContactsPermission = true; - } else if (name == "android.permission.WRITE_CONTACTS") { - hasWriteContactsPermission = true; - } else if (name == "android.permission.READ_CALL_LOG") { - hasReadCallLogPermission = true; - } else if (name == "android.permission.WRITE_CALL_LOG") { - hasWriteCallLogPermission = true; - } - printf("uses-permission:'%s'\n", name.string()); - int req = getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1); - if (!req) { - printf("optional-permission:'%s'\n", name.string()); - } - } else { - fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", - 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 == "") { - printf("original-package:'%s'\n", name.string()); - } else { - fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", - error.string()); - goto bail; - } - } else if (tag == "supports-gl-texture") { - String8 name = getAttribute(tree, NAME_ATTR, &error); - if (name != "" && error == "") { - printf("supports-gl-texture:'%s'\n", name.string()); - } else { - fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", - error.string()); - goto bail; - } - } else if (tag == "compatible-screens") { - printCompatibleScreens(tree); - depth--; - } else if (tag == "package-verifier") { - String8 name = getAttribute(tree, NAME_ATTR, &error); - if (name != "" && error == "") { - String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error); - if (publicKey != "" && error == "") { - printf("package-verifier: name='%s' publicKey='%s'\n", - name.string(), publicKey.string()); - } - } - } - } else if (depth == 3 && withinApplication) { - withinActivity = false; - withinReceiver = false; - withinService = false; - hasIntentFilter = false; - if(tag == "activity") { - withinActivity = true; - activityName = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string()); - goto bail; - } - - activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string()); - goto bail; - } - - activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); - goto bail; - } - - int32_t orien = getResolvedIntegerAttribute(&res, tree, - SCREEN_ORIENTATION_ATTR, &error); - if (error == "") { - if (orien == 0 || orien == 6 || orien == 8) { - // Requests landscape, sensorLandscape, or reverseLandscape. - reqScreenLandscapeFeature = true; - } else if (orien == 1 || orien == 7 || orien == 9) { - // Requests portrait, sensorPortrait, or reversePortrait. - reqScreenPortraitFeature = true; - } - } - } else if (tag == "uses-library") { - String8 libraryName = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute for uses-library: %s\n", error.string()); - goto bail; - } - int req = getIntegerAttribute(tree, - REQUIRED_ATTR, NULL, 1); - printf("uses-library%s:'%s'\n", - req ? "" : "-not-required", libraryName.string()); - } else if (tag == "receiver") { - withinReceiver = true; - receiverName = getAttribute(tree, NAME_ATTR, &error); - - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute for " - "receiver:%s\n", error.string()); - goto bail; - } - } else if (tag == "service") { - withinService = true; - serviceName = getAttribute(tree, NAME_ATTR, &error); - - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute for " - "service:%s\n", error.string()); - goto bail; - } - } else if (bundle->getIncludeMetaData() && tag == "meta-data") { - String8 metaDataName = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute for " - "meta-data:%s\n", error.string()); - goto bail; - } - printf("meta-data: name='%s' ", metaDataName.string()); - Res_value value; - getResolvedResourceAttribute(&value, &res, tree, VALUE_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:value' attribute for " - "meta-data:%s\n", error.string()); - goto bail; - } - if (value.dataType == Res_value::TYPE_STRING) { - String8 metaDataValue = getAttribute(tree, value.data, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:value' attribute for " - "meta-data: %s\n", error.string()); - goto bail; - } - printf("value='%s'\n", metaDataValue.string()); - } else if (Res_value::TYPE_FIRST_INT <= value.dataType && - value.dataType <= Res_value::TYPE_LAST_INT) { - printf("value='%d'\n", value.data); - } else { - printf("value=(type 0x%x)0x%x", (int)value.dataType, (int)value.data); - } - } - } else if ((depth == 4) && (tag == "intent-filter")) { - hasIntentFilter = true; - withinIntentFilter = true; - actMainActivity = actWidgetReceivers = actImeService = actWallpaperService = - false; - } else if ((depth == 5) && withinIntentFilter) { - String8 action; - if (tag == "action") { - action = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", - error.string()); - goto bail; - } - if (withinActivity) { - if (action == "android.intent.action.MAIN") { - isMainActivity = true; - actMainActivity = true; - } - } else if (withinReceiver) { - if (action == "android.appwidget.action.APPWIDGET_UPDATE") { - actWidgetReceivers = true; - } - } else if (withinService) { - if (action == "android.view.InputMethod") { - actImeService = true; - } else if (action == "android.service.wallpaper.WallpaperService") { - actWallpaperService = true; - } - } - if (action == "android.intent.action.SEARCH") { - isSearchable = true; - } - } - - if (tag == "category") { - String8 category = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'name' attribute: %s\n", error.string()); - goto bail; - } - if (withinActivity) { - if (category == "android.intent.category.LAUNCHER") { - isLauncherActivity = true; - } - } - } - } - } - - // Pre-1.6 implicitly granted permission compatibility logic - if (targetSdk < 4) { - if (!hasWriteExternalStoragePermission) { - printf("uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE'\n"); - printf("uses-implied-permission:'android.permission.WRITE_EXTERNAL_STORAGE'," \ - "'targetSdkVersion < 4'\n"); - hasWriteExternalStoragePermission = true; - } - if (!hasReadPhoneStatePermission) { - printf("uses-permission:'android.permission.READ_PHONE_STATE'\n"); - printf("uses-implied-permission:'android.permission.READ_PHONE_STATE'," \ - "'targetSdkVersion < 4'\n"); - } - } - - // If the application has requested WRITE_EXTERNAL_STORAGE, we will - // force them to always take READ_EXTERNAL_STORAGE as well. We always - // do this (regardless of target API version) because we can't have - // an app with write permission but not read permission. - if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) { - printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n"); - printf("uses-implied-permission:'android.permission.READ_EXTERNAL_STORAGE'," \ - "'requested WRITE_EXTERNAL_STORAGE'\n"); - } - - // Pre-JellyBean call log permission compatibility. - if (targetSdk < 16) { - if (!hasReadCallLogPermission && hasReadContactsPermission) { - printf("uses-permission:'android.permission.READ_CALL_LOG'\n"); - printf("uses-implied-permission:'android.permission.READ_CALL_LOG'," \ - "'targetSdkVersion < 16 and requested READ_CONTACTS'\n"); - } - if (!hasWriteCallLogPermission && hasWriteContactsPermission) { - printf("uses-permission:'android.permission.WRITE_CALL_LOG'\n"); - printf("uses-implied-permission:'android.permission.WRITE_CALL_LOG'," \ - "'targetSdkVersion < 16 and requested WRITE_CONTACTS'\n"); - } - } - - /* The following blocks handle printing "inferred" uses-features, based - * on whether related features or permissions are used by the app. - * Note that the various spec*Feature variables denote whether the - * relevant tag was *present* in the AndroidManfest, not that it was - * present and set to true. - */ - // Camera-related back-compatibility logic - if (!specCameraFeature) { - if (reqCameraFlashFeature) { - // if app requested a sub-feature (autofocus or flash) and didn't - // request the base camera feature, we infer that it meant to - printf("uses-feature:'android.hardware.camera'\n"); - printf("uses-implied-feature:'android.hardware.camera'," \ - "'requested android.hardware.camera.flash feature'\n"); - } else if (reqCameraAutofocusFeature) { - // if app requested a sub-feature (autofocus or flash) and didn't - // request the base camera feature, we infer that it meant to - printf("uses-feature:'android.hardware.camera'\n"); - printf("uses-implied-feature:'android.hardware.camera'," \ - "'requested android.hardware.camera.autofocus feature'\n"); - } else if (hasCameraPermission) { - // if app wants to use camera but didn't request the feature, we infer - // that it meant to, and further that it wants autofocus - // (which was the 1.0 - 1.5 behavior) - printf("uses-feature:'android.hardware.camera'\n"); - if (!specCameraAutofocusFeature) { - printf("uses-feature:'android.hardware.camera.autofocus'\n"); - printf("uses-implied-feature:'android.hardware.camera.autofocus'," \ - "'requested android.permission.CAMERA permission'\n"); - } - } - } - - // Location-related back-compatibility logic - if (!specLocationFeature && - (hasMockLocPermission || hasCoarseLocPermission || hasGpsPermission || - hasGeneralLocPermission || reqNetworkLocFeature || reqGpsFeature)) { - // if app either takes a location-related permission or requests one of the - // sub-features, we infer that it also meant to request the base location feature - printf("uses-feature:'android.hardware.location'\n"); - printf("uses-implied-feature:'android.hardware.location'," \ - "'requested a location access permission'\n"); - } - if (!specGpsFeature && hasGpsPermission) { - // if app takes GPS (FINE location) perm but does not request the GPS - // feature, we infer that it meant to - printf("uses-feature:'android.hardware.location.gps'\n"); - printf("uses-implied-feature:'android.hardware.location.gps'," \ - "'requested android.permission.ACCESS_FINE_LOCATION permission'\n"); - } - if (!specNetworkLocFeature && hasCoarseLocPermission) { - // if app takes Network location (COARSE location) perm but does not request the - // network location feature, we infer that it meant to - printf("uses-feature:'android.hardware.location.network'\n"); - printf("uses-implied-feature:'android.hardware.location.network'," \ - "'requested android.permission.ACCESS_COARSE_LOCATION permission'\n"); - } - - // Bluetooth-related compatibility logic - if (!specBluetoothFeature && hasBluetoothPermission && (targetSdk > 4)) { - // if app takes a Bluetooth permission but does not request the Bluetooth - // feature, we infer that it meant to - printf("uses-feature:'android.hardware.bluetooth'\n"); - printf("uses-implied-feature:'android.hardware.bluetooth'," \ - "'requested android.permission.BLUETOOTH or android.permission.BLUETOOTH_ADMIN " \ - "permission and targetSdkVersion > 4'\n"); - } - - // Microphone-related compatibility logic - if (!specMicrophoneFeature && hasRecordAudioPermission) { - // if app takes the record-audio permission but does not request the microphone - // feature, we infer that it meant to - printf("uses-feature:'android.hardware.microphone'\n"); - printf("uses-implied-feature:'android.hardware.microphone'," \ - "'requested android.permission.RECORD_AUDIO permission'\n"); - } - - // WiFi-related compatibility logic - if (!specWiFiFeature && hasWiFiPermission) { - // if app takes one of the WiFi permissions but does not request the WiFi - // feature, we infer that it meant to - printf("uses-feature:'android.hardware.wifi'\n"); - printf("uses-implied-feature:'android.hardware.wifi'," \ - "'requested android.permission.ACCESS_WIFI_STATE, " \ - "android.permission.CHANGE_WIFI_STATE, or " \ - "android.permission.CHANGE_WIFI_MULTICAST_STATE permission'\n"); - } - - // Telephony-related compatibility logic - if (!specTelephonyFeature && (hasTelephonyPermission || reqTelephonySubFeature)) { - // if app takes one of the telephony permissions or requests a sub-feature but - // does not request the base telephony feature, we infer that it meant to - printf("uses-feature:'android.hardware.telephony'\n"); - printf("uses-implied-feature:'android.hardware.telephony'," \ - "'requested a telephony-related permission or feature'\n"); - } - - // Touchscreen-related back-compatibility logic - if (!specTouchscreenFeature) { // not a typo! - // all apps are presumed to require a touchscreen, unless they explicitly say - // <uses-feature android:name="android.hardware.touchscreen" android:required="false"/> - // Note that specTouchscreenFeature is true if the tag is present, regardless - // of whether its value is true or false, so this is safe - printf("uses-feature:'android.hardware.touchscreen'\n"); - printf("uses-implied-feature:'android.hardware.touchscreen'," \ - "'assumed you require a touch screen unless explicitly made optional'\n"); - } - if (!specMultitouchFeature && reqDistinctMultitouchFeature) { - // if app takes one of the telephony permissions or requests a sub-feature but - // does not request the base telephony feature, we infer that it meant to - printf("uses-feature:'android.hardware.touchscreen.multitouch'\n"); - printf("uses-implied-feature:'android.hardware.touchscreen.multitouch'," \ - "'requested android.hardware.touchscreen.multitouch.distinct feature'\n"); - } - - // Landscape/portrait-related compatibility logic - if (!specScreenLandscapeFeature && !specScreenPortraitFeature) { - // If the app has specified any activities in its manifest - // that request a specific orientation, then assume that - // orientation is required. - if (reqScreenLandscapeFeature) { - printf("uses-feature:'android.hardware.screen.landscape'\n"); - printf("uses-implied-feature:'android.hardware.screen.landscape'," \ - "'one or more activities have specified a landscape orientation'\n"); - } - if (reqScreenPortraitFeature) { - printf("uses-feature:'android.hardware.screen.portrait'\n"); - printf("uses-implied-feature:'android.hardware.screen.portrait'," \ - "'one or more activities have specified a portrait orientation'\n"); - } - } - - if (hasMainActivity) { - printf("main\n"); - } - if (hasWidgetReceivers) { - printf("app-widget\n"); - } - if (hasImeService) { - printf("ime\n"); - } - if (hasWallpaperService) { - printf("wallpaper\n"); - } - if (hasOtherActivities) { - printf("other-activities\n"); - } - if (isSearchable) { - printf("search\n"); - } - if (hasOtherReceivers) { - printf("other-receivers\n"); - } - if (hasOtherServices) { - printf("other-services\n"); - } - - // For modern apps, if screen size buckets haven't been specified - // but the new width ranges have, then infer the buckets from them. - if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0 - && requiresSmallestWidthDp > 0) { - int compatWidth = compatibleWidthLimitDp; - if (compatWidth <= 0) { - compatWidth = requiresSmallestWidthDp; - } - if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) { - smallScreen = -1; - } else { - smallScreen = 0; - } - if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) { - normalScreen = -1; - } else { - normalScreen = 0; - } - if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) { - largeScreen = -1; - } else { - largeScreen = 0; - } - if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) { - xlargeScreen = -1; - } else { - xlargeScreen = 0; - } - } - - // 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; - } - if (xlargeScreen > 0) { - // Introduced in Gingerbread. - xlargeScreen = targetSdk >= 9 ? -1 : 0; - } - if (anyDensity > 0) { - anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0 - || compatibleWidthLimitDp > 0) ? -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("supports-any-density: '%s'\n", anyDensity ? "true" : "false"); - if (requiresSmallestWidthDp > 0) { - printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp); - } - if (compatibleWidthLimitDp > 0) { - printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp); - } - if (largestWidthLimitDp > 0) { - printf("largest-width-limit:'%d'\n", largestWidthLimitDp); - } - - printf("locales:"); - 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 = "--_--"; - } - printf(" '%s'", localeStr); - } - printf("\n"); - - 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("badger", option) == 0) { - printf("%s", CONSOLE_DATA); - } else if (strcmp("configurations", option) == 0) { - Vector<ResTable_config> configs; - res.getConfigurations(&configs); - const size_t N = configs.size(); - for (size_t i=0; i<N; i++) { - printf("%s\n", configs[i].toString().string()); - } - } else { - fprintf(stderr, "ERROR: unknown dump option '%s'\n", option); - goto bail; - } - } - - result = NO_ERROR; - -bail: - if (asset) { - delete asset; - } - return (result != NO_ERROR); -} - - -/* - * Handle the "add" command, which wants to add files to a new or - * pre-existing archive. - */ -int doAdd(Bundle* bundle) -{ - ZipFile* zip = NULL; - status_t result = UNKNOWN_ERROR; - const char* zipFileName; - - if (bundle->getUpdate()) { - /* avoid confusion */ - fprintf(stderr, "ERROR: can't use '-u' with add\n"); - goto bail; - } - - if (bundle->getFileSpecCount() < 1) { - fprintf(stderr, "ERROR: must specify zip file name\n"); - goto bail; - } - zipFileName = bundle->getFileSpecEntry(0); - - if (bundle->getFileSpecCount() < 2) { - fprintf(stderr, "NOTE: nothing to do\n"); - goto bail; - } - - zip = openReadWrite(zipFileName, true); - if (zip == NULL) { - fprintf(stderr, "ERROR: failed opening/creating '%s' as Zip file\n", zipFileName); - goto bail; - } - - for (int i = 1; i < bundle->getFileSpecCount(); i++) { - const char* fileName = bundle->getFileSpecEntry(i); - - if (strcasecmp(String8(fileName).getPathExtension().string(), ".gz") == 0) { - printf(" '%s'... (from gzip)\n", fileName); - result = zip->addGzip(fileName, String8(fileName).getBasePath().string(), NULL); - } else { - if (bundle->getJunkPath()) { - String8 storageName = String8(fileName).getPathLeaf(); - printf(" '%s' as '%s'...\n", fileName, storageName.string()); - result = zip->add(fileName, storageName.string(), - bundle->getCompressionMethod(), NULL); - } else { - printf(" '%s'...\n", fileName); - result = zip->add(fileName, bundle->getCompressionMethod(), NULL); - } - } - if (result != NO_ERROR) { - fprintf(stderr, "Unable to add '%s' to '%s'", bundle->getFileSpecEntry(i), zipFileName); - if (result == NAME_NOT_FOUND) { - fprintf(stderr, ": file not found\n"); - } else if (result == ALREADY_EXISTS) { - fprintf(stderr, ": already exists in archive\n"); - } else { - fprintf(stderr, "\n"); - } - goto bail; - } - } - - result = NO_ERROR; - -bail: - delete zip; - return (result != NO_ERROR); -} - - -/* - * Delete files from an existing archive. - */ -int doRemove(Bundle* bundle) -{ - ZipFile* zip = NULL; - status_t result = UNKNOWN_ERROR; - const char* zipFileName; - - if (bundle->getFileSpecCount() < 1) { - fprintf(stderr, "ERROR: must specify zip file name\n"); - goto bail; - } - zipFileName = bundle->getFileSpecEntry(0); - - if (bundle->getFileSpecCount() < 2) { - fprintf(stderr, "NOTE: nothing to do\n"); - goto bail; - } - - zip = openReadWrite(zipFileName, false); - if (zip == NULL) { - fprintf(stderr, "ERROR: failed opening Zip archive '%s'\n", - zipFileName); - goto bail; - } - - for (int i = 1; i < bundle->getFileSpecCount(); i++) { - const char* fileName = bundle->getFileSpecEntry(i); - ZipEntry* entry; - - entry = zip->getEntryByName(fileName); - if (entry == NULL) { - printf(" '%s' NOT FOUND\n", fileName); - continue; - } - - result = zip->remove(entry); - - if (result != NO_ERROR) { - fprintf(stderr, "Unable to delete '%s' from '%s'\n", - bundle->getFileSpecEntry(i), zipFileName); - goto bail; - } - } - - /* update the archive */ - zip->flush(); - -bail: - delete zip; - return (result != NO_ERROR); -} - - -/* - * Package up an asset directory and associated application files. - */ -int doPackage(Bundle* bundle) -{ - const char* outputAPKFile; - int retVal = 1; - status_t err; - sp<AaptAssets> assets; - int N; - FILE* fp; - String8 dependencyFile; - - // -c zz_ZZ means do pseudolocalization - ResourceFilter filter; - err = filter.parse(bundle->getConfigurations()); - if (err != NO_ERROR) { - goto bail; - } - if (filter.containsPseudo()) { - bundle->setPseudolocalize(true); - } - - N = bundle->getFileSpecCount(); - if (N < 1 && bundle->getResourceSourceDirs().size() == 0 && bundle->getJarFiles().size() == 0 - && bundle->getAndroidManifestFile() == NULL && bundle->getAssetSourceDir() == NULL) { - fprintf(stderr, "ERROR: no input files\n"); - goto bail; - } - - outputAPKFile = bundle->getOutputAPKFile(); - - // Make sure the filenames provided exist and are of the appropriate type. - if (outputAPKFile) { - FileType type; - type = getFileType(outputAPKFile); - if (type != kFileTypeNonexistent && type != kFileTypeRegular) { - fprintf(stderr, - "ERROR: output file '%s' exists but is not regular file\n", - outputAPKFile); - goto bail; - } - } - - // Load the assets. - assets = new AaptAssets(); - - // Set up the resource gathering in assets if we're going to generate - // dependency files. Every time we encounter a resource while slurping - // the tree, we'll add it to these stores so we have full resource paths - // to write to a dependency file. - if (bundle->getGenDependencies()) { - sp<FilePathStore> resPathStore = new FilePathStore; - assets->setFullResPaths(resPathStore); - sp<FilePathStore> assetPathStore = new FilePathStore; - assets->setFullAssetPaths(assetPathStore); - } - - err = assets->slurpFromArgs(bundle); - if (err < 0) { - goto bail; - } - - if (bundle->getVerbose()) { - assets->print(String8()); - } - - // If they asked for any fileAs that need to be compiled, do so. - if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) { - err = buildResources(bundle, assets); - if (err != 0) { - goto bail; - } - } - - // At this point we've read everything and processed everything. From here - // on out it's just writing output files. - if (SourcePos::hasErrors()) { - goto bail; - } - - // Update symbols with information about which ones are needed as Java symbols. - assets->applyJavaSymbols(); - if (SourcePos::hasErrors()) { - goto bail; - } - - // If we've been asked to generate a dependency file, do that here - if (bundle->getGenDependencies()) { - // If this is the packaging step, generate the dependency file next to - // the output apk (e.g. bin/resources.ap_.d) - if (outputAPKFile) { - dependencyFile = String8(outputAPKFile); - // Add the .d extension to the dependency file. - dependencyFile.append(".d"); - } else { - // Else if this is the R.java dependency generation step, - // generate the dependency file in the R.java package subdirectory - // e.g. gen/com/foo/app/R.java.d - dependencyFile = String8(bundle->getRClassDir()); - dependencyFile.appendPath("R.java.d"); - } - // Make sure we have a clean dependency file to start with - fp = fopen(dependencyFile, "w"); - fclose(fp); - } - - // Write out R.java constants - if (!assets->havePrivateSymbols()) { - if (bundle->getCustomPackage() == NULL) { - // Write the R.java file into the appropriate class directory - // e.g. gen/com/foo/app/R.java - err = writeResourceSymbols(bundle, assets, assets->getPackage(), true); - } else { - const String8 customPkg(bundle->getCustomPackage()); - err = writeResourceSymbols(bundle, assets, customPkg, true); - } - if (err < 0) { - goto bail; - } - // If we have library files, we're going to write our R.java file into - // the appropriate class directory for those libraries as well. - // e.g. gen/com/foo/app/lib/R.java - if (bundle->getExtraPackages() != NULL) { - // Split on colon - String8 libs(bundle->getExtraPackages()); - char* packageString = strtok(libs.lockBuffer(libs.length()), ":"); - while (packageString != NULL) { - // Write the R.java file out with the correct package name - err = writeResourceSymbols(bundle, assets, String8(packageString), true); - if (err < 0) { - goto bail; - } - packageString = strtok(NULL, ":"); - } - libs.unlockBuffer(); - } - } else { - err = writeResourceSymbols(bundle, assets, assets->getPackage(), false); - if (err < 0) { - goto bail; - } - err = writeResourceSymbols(bundle, assets, assets->getSymbolsPrivatePackage(), true); - if (err < 0) { - goto bail; - } - } - - // Write out the ProGuard file - err = writeProguardFile(bundle, assets); - if (err < 0) { - goto bail; - } - - // Write the apk - if (outputAPKFile) { - err = writeAPK(bundle, assets, String8(outputAPKFile)); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: packaging of '%s' failed\n", outputAPKFile); - goto bail; - } - } - - // If we've been asked to generate a dependency file, we need to finish up here. - // the writeResourceSymbols and writeAPK functions have already written the target - // half of the dependency file, now we need to write the prerequisites. (files that - // the R.java file or .ap_ file depend on) - if (bundle->getGenDependencies()) { - // Now that writeResourceSymbols or writeAPK has taken care of writing - // the targets to our dependency file, we'll write the prereqs - fp = fopen(dependencyFile, "a+"); - fprintf(fp, " : "); - bool includeRaw = (outputAPKFile != NULL); - err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); - // Also manually add the AndroidManifeset since it's not under res/ or assets/ - // and therefore was not added to our pathstores during slurping - fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); - fclose(fp); - } - - retVal = 0; -bail: - if (SourcePos::hasErrors()) { - SourcePos::printErrors(stderr); - } - return retVal; -} - -/* - * Do PNG Crunching - * PRECONDITIONS - * -S flag points to a source directory containing drawable* folders - * -C flag points to destination directory. The folder structure in the - * source directory will be mirrored to the destination (cache) directory - * - * POSTCONDITIONS - * Destination directory will be updated to match the PNG files in - * the source directory. - */ -int doCrunch(Bundle* bundle) -{ - fprintf(stdout, "Crunching PNG Files in "); - fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); - fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); - - updatePreProcessedCache(bundle); - - return NO_ERROR; -} - -/* - * Do PNG Crunching on a single flag - * -i points to a single png file - * -o points to a single png output file - */ -int doSingleCrunch(Bundle* bundle) -{ - fprintf(stdout, "Crunching single PNG file: %s\n", bundle->getSingleCrunchInputFile()); - fprintf(stdout, "\tOutput file: %s\n", bundle->getSingleCrunchOutputFile()); - - String8 input(bundle->getSingleCrunchInputFile()); - String8 output(bundle->getSingleCrunchOutputFile()); - - if (preProcessImageToCache(bundle, input, output) != NO_ERROR) { - // we can't return the status_t as it gets truncate to the lower 8 bits. - return 42; - } - - return NO_ERROR; -} - -char CONSOLE_DATA[2925] = { - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, - 86, 35, 40, 46, 46, 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, - 62, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, - 81, 81, 81, 66, 96, 61, 61, 58, 46, 46, 46, 58, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 81, 81, 102, 59, 61, 59, - 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, - 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 46, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, - 58, 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, - 47, 61, 59, 59, 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, - 121, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, - 81, 81, 81, 109, 58, 59, 59, 59, 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 81, 81, 81, 81, 59, 61, 59, - 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 60, 81, 91, 59, - 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 81, 76, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, - 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 93, 40, 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, - 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 46, 46, 46, 32, 46, 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, - 81, 81, 81, 87, 46, 58, 61, 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, - 32, 32, 32, 32, 32, 32, 32, 46, 46, 61, 59, 61, 61, 61, 59, 61, 61, 59, - 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 81, 81, 81, 81, 69, 58, 59, 59, - 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 58, 59, - 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 46, - 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 96, 32, 32, 32, - 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 81, - 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, - 67, 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, - 61, 59, 59, 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, - 73, 108, 108, 62, 52, 81, 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 61, 59, 61, 61, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, - 32, 46, 45, 57, 101, 43, 43, 61, 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 58, 97, 46, 61, 108, 62, 126, 58, 106, 80, 96, - 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, - 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 45, 46, 32, - 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 58, 59, 59, 59, 59, 61, - 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 58, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 99, 32, 32, - 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, - 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 61, 58, 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, - 81, 58, 59, 59, 59, 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, - 87, 66, 33, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, - 45, 32, 46, 32, 32, 32, 32, 32, 46, 32, 126, 96, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, - 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, - 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 40, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, - 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 59, - 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 102, 94, 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, - 59, 59, 43, 63, 36, 81, 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, - 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 43, 33, - 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, - 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 58, 95, - 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 59, - 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, - 59, 58, 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, - 59, 59, 59, 59, 59, 59, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 45, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 58, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 61, - 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, - 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 59, 59, - 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, - 32, 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, - 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, - 59, 59, 59, 58, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10 - }; diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp deleted file mode 100644 index c4cf6bc..0000000 --- a/tools/aapt/CrunchCache.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -// Implementation file for CrunchCache -// This file defines functions laid out and documented in -// CrunchCache.h - -#include <utils/Vector.h> -#include <utils/String8.h> - -#include "DirectoryWalker.h" -#include "FileFinder.h" -#include "CacheUpdater.h" -#include "CrunchCache.h" - -using namespace android; - -CrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff) - : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff) -{ - // We initialize the default value to return to 0 so if a file doesn't exist - // then all files are automatically "newer" than it. - - // Set file extensions to look for. Right now just pngs. - mExtensions.push(String8(".png")); - - // Load files into our data members - loadFiles(); -} - -size_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite) -{ - size_t numFilesUpdated = 0; - - // Iterate through the source files and compare to cache. - // After processing a file, remove it from the source files and - // from the dest files. - // We're done when we're out of files in source. - String8 relativePath; - while (mSourceFiles.size() > 0) { - // Get the full path to the source file, then convert to a c-string - // and offset our beginning pointer to the length of the sourcePath - // This efficiently strips the source directory prefix from our path. - // Also, String8 doesn't have a substring method so this is what we've - // got to work with. - const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length(); - // Strip leading slash if present - int offset = 0; - if (rPathPtr[0] == OS_PATH_SEPARATOR) - offset = 1; - relativePath = String8(rPathPtr + offset); - - if (forceOverwrite || needsUpdating(relativePath)) { - cu->processImage(mSourcePath.appendPathCopy(relativePath), - mDestPath.appendPathCopy(relativePath)); - numFilesUpdated++; - // crunchFile(relativePath); - } - // Delete this file from the source files and (if it exists) from the - // dest files. - mSourceFiles.removeItemsAt(0); - mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath)); - } - - // Iterate through what's left of destFiles and delete leftovers - while (mDestFiles.size() > 0) { - cu->deleteFile(mDestFiles.keyAt(0)); - mDestFiles.removeItemsAt(0); - } - - // Update our knowledge of the files cache - // both source and dest should be empty by now. - loadFiles(); - - return numFilesUpdated; -} - -void CrunchCache::loadFiles() -{ - // Clear out our data structures to avoid putting in duplicates - mSourceFiles.clear(); - mDestFiles.clear(); - - // Make a directory walker that points to the system. - DirectoryWalker* dw = new SystemDirectoryWalker(); - - // Load files in the source directory - mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw); - - // Load files in the destination directory - mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw); - - delete dw; -} - -bool CrunchCache::needsUpdating(String8 relativePath) const -{ - // Retrieve modification dates for this file entry under the source and - // cache directory trees. The vectors will return a modification date of 0 - // if the file doesn't exist. - time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath)); - time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath)); - return sourceDate > destDate; -}
\ No newline at end of file diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h deleted file mode 100644 index be3da5c..0000000 --- a/tools/aapt/CrunchCache.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -// Cache manager for pre-processed PNG files. -// Contains code for managing which PNG files get processed -// at build time. -// - -#ifndef CRUNCHCACHE_H -#define CRUNCHCACHE_H - -#include <utils/KeyedVector.h> -#include <utils/String8.h> -#include "FileFinder.h" -#include "CacheUpdater.h" - -using namespace android; - -/** CrunchCache - * This class is a cache manager which can pre-process PNG files and store - * them in a mirror-cache. It's capable of doing incremental updates to its - * cache. - * - * Usage: - * Create an instance initialized with the root of the source tree, the - * root location to store the cache files, and an instance of a file finder. - * Then update the cache by calling crunch. - */ -class CrunchCache { -public: - // Constructor - CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff); - - // Nobody should be calling the default constructor - // So this space is intentionally left blank - - // Default Copy Constructor and Destructor are fine - - /** crunch is the workhorse of this class. - * It goes through all the files found in the sourcePath and compares - * them to the cached versions in the destPath. If the optional - * argument forceOverwrite is set to true, then all source files are - * re-crunched even if they have not been modified recently. Otherwise, - * source files are only crunched when they needUpdating. Afterwards, - * we delete any leftover files in the cache that are no longer present - * in source. - * - * PRECONDITIONS: - * No setup besides construction is needed - * POSTCONDITIONS: - * The cache is updated to fully reflect all changes in source. - * The function then returns the number of files changed in cache - * (counting deletions). - */ - size_t crunch(CacheUpdater* cu, bool forceOverwrite=false); - -private: - /** loadFiles is a wrapper to the FileFinder that places matching - * files into mSourceFiles and mDestFiles. - * - * POSTCONDITIONS - * mDestFiles and mSourceFiles are refreshed to reflect the current - * state of the files in the source and dest directories. - * Any previous contents of mSourceFiles and mDestFiles are cleared. - */ - void loadFiles(); - - /** needsUpdating takes a file path - * and returns true if the file represented by this path is newer in the - * sourceFiles than in the cache (mDestFiles). - * - * PRECONDITIONS: - * mSourceFiles and mDestFiles must be initialized and filled. - * POSTCONDITIONS: - * returns true if and only if source file's modification time - * is greater than the cached file's mod-time. Otherwise returns false. - * - * USAGE: - * Should be used something like the following: - * if (needsUpdating(filePath)) - * // Recrunch sourceFile out to destFile. - * - */ - bool needsUpdating(String8 relativePath) const; - - // DATA MEMBERS ==================================================== - - String8 mSourcePath; - String8 mDestPath; - - Vector<String8> mExtensions; - - // Each vector of paths contains one entry per PNG file encountered. - // Each entry consists of a path pointing to that PNG. - DefaultKeyedVector<String8,time_t> mSourceFiles; - DefaultKeyedVector<String8,time_t> mDestFiles; - - // Pointer to a FileFinder to use - FileFinder* mFileFinder; -}; - -#endif // CRUNCHCACHE_H diff --git a/tools/aapt/DirectoryWalker.h b/tools/aapt/DirectoryWalker.h deleted file mode 100644 index 88031d0..0000000 --- a/tools/aapt/DirectoryWalker.h +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -// Defines an abstraction for opening a directory on the filesystem and -// iterating through it. - -#ifndef DIRECTORYWALKER_H -#define DIRECTORYWALKER_H - -#include <dirent.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <unistd.h> -#include <utils/String8.h> - -#include <stdio.h> - -using namespace android; - -// Directory Walker -// This is an abstraction for walking through a directory and getting files -// and descriptions. - -class DirectoryWalker { -public: - virtual ~DirectoryWalker() {}; - virtual bool openDir(String8 path) = 0; - virtual bool openDir(const char* path) = 0; - // Advance to next directory entry - virtual struct dirent* nextEntry() = 0; - // Get the stats for the current entry - virtual struct stat* entryStats() = 0; - // Clean Up - virtual void closeDir() = 0; - // This class is able to replicate itself on the heap - virtual DirectoryWalker* clone() = 0; - - // DATA MEMBERS - // Current directory entry - struct dirent mEntry; - // Stats for that directory entry - struct stat mStats; - // Base path - String8 mBasePath; -}; - -// System Directory Walker -// This is an implementation of the above abstraction that calls -// real system calls and is fully functional. -// functions are inlined since they're very short and simple - -class SystemDirectoryWalker : public DirectoryWalker { - - // Default constructor, copy constructor, and destructor are fine -public: - virtual bool openDir(String8 path) { - mBasePath = path; - dir = NULL; - dir = opendir(mBasePath.string() ); - - if (dir == NULL) - return false; - - return true; - }; - virtual bool openDir(const char* path) { - String8 p(path); - openDir(p); - return true; - }; - // Advance to next directory entry - virtual struct dirent* nextEntry() { - struct dirent* entryPtr = readdir(dir); - if (entryPtr == NULL) - return NULL; - - mEntry = *entryPtr; - // Get stats - String8 fullPath = mBasePath.appendPathCopy(mEntry.d_name); - stat(fullPath.string(),&mStats); - return &mEntry; - }; - // Get the stats for the current entry - virtual struct stat* entryStats() { - return &mStats; - }; - virtual void closeDir() { - closedir(dir); - }; - virtual DirectoryWalker* clone() { - return new SystemDirectoryWalker(*this); - }; -private: - DIR* dir; -}; - -#endif // DIRECTORYWALKER_H diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp deleted file mode 100644 index 18775c0..0000000 --- a/tools/aapt/FileFinder.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// - -// File Finder implementation. -// Implementation for the functions declared and documented in FileFinder.h - -#include <utils/Vector.h> -#include <utils/String8.h> -#include <utils/KeyedVector.h> - -#include <dirent.h> -#include <sys/stat.h> - -#include "DirectoryWalker.h" -#include "FileFinder.h" - -//#define DEBUG - -using android::String8; - -// Private function to check whether a file is a directory or not -bool isDirectory(const char* filename) { - struct stat fileStat; - if (stat(filename, &fileStat) == -1) { - return false; - } - return(S_ISDIR(fileStat.st_mode)); -} - - -// Private function to check whether a file is a regular file or not -bool isFile(const char* filename) { - struct stat fileStat; - if (stat(filename, &fileStat) == -1) { - return false; - } - return(S_ISREG(fileStat.st_mode)); -} - -bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions, - KeyedVector<String8,time_t>& fileStore, - DirectoryWalker* dw) -{ - // Scan the directory pointed to by basePath - // check files and recurse into subdirectories. - if (!dw->openDir(basePath)) { - return false; - } - /* - * Go through all directory entries. Check each file using checkAndAddFile - * and recurse into sub-directories. - */ - struct dirent* entry; - while ((entry = dw->nextEntry()) != NULL) { - String8 entryName(entry->d_name); - if (entry->d_name[0] == '.') // Skip hidden files and directories - continue; - - String8 fullPath = basePath.appendPathCopy(entryName); - // If this entry is a directory we'll recurse into it - if (isDirectory(fullPath.string()) ) { - DirectoryWalker* copy = dw->clone(); - findFiles(fullPath, extensions, fileStore,copy); - delete copy; - } - - // If this entry is a file, we'll pass it over to checkAndAddFile - if (isFile(fullPath.string()) ) { - checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore); - } - } - - // Clean up - dw->closeDir(); - - return true; -} - -void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats, - Vector<String8>& extensions, - KeyedVector<String8,time_t>& fileStore) -{ - // Loop over the extensions, checking for a match - bool done = false; - String8 ext(path.getPathExtension()); - ext.toLower(); - for (size_t i = 0; i < extensions.size() && !done; ++i) { - String8 ext2 = extensions[i].getPathExtension(); - ext2.toLower(); - // Compare the extensions. If a match is found, add to storage. - if (ext == ext2) { - done = true; - fileStore.add(path,stats->st_mtime); - } - } -} - diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h deleted file mode 100644 index 6974aee..0000000 --- a/tools/aapt/FileFinder.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// - -// File Finder. -// This is a collection of useful functions for finding paths and modification -// times of files that match an extension pattern in a directory tree. -// and finding files in it. - -#ifndef FILEFINDER_H -#define FILEFINDER_H - -#include <utils/Vector.h> -#include <utils/KeyedVector.h> -#include <utils/String8.h> - -#include "DirectoryWalker.h" - -using namespace android; - -// Abstraction to allow for dependency injection. See MockFileFinder.h -// for the testing implementation. -class FileFinder { -public: - virtual bool findFiles(String8 basePath, Vector<String8>& extensions, - KeyedVector<String8,time_t>& fileStore, - DirectoryWalker* dw) = 0; - - virtual ~FileFinder() {}; -}; - -class SystemFileFinder : public FileFinder { -public: - - /* findFiles takes a path, a Vector of extensions, and a destination KeyedVector - * and places path/modification date key/values pointing to - * all files with matching extensions found into the KeyedVector - * PRECONDITIONS - * path is a valid system path - * extensions should include leading "." - * This is not necessary, but the comparison directly - * compares the end of the path string so if the "." - * is excluded there is a small chance you could have - * a false positive match. (For example: extension "png" - * would match a file called "blahblahpng") - * - * POSTCONDITIONS - * fileStore contains (in no guaranteed order) paths to all - * matching files encountered in subdirectories of path - * as keys in the KeyedVector. Each key has the modification time - * of the file as its value. - * - * Calls checkAndAddFile on each file encountered in the directory tree - * Recursively descends into subdirectories. - */ - virtual bool findFiles(String8 basePath, Vector<String8>& extensions, - KeyedVector<String8,time_t>& fileStore, - DirectoryWalker* dw); - -private: - /** - * checkAndAddFile looks at a single file path and stat combo - * to determine whether it is a matching file (by looking at - * the extension) - * - * PRECONDITIONS - * no setup is needed - * - * POSTCONDITIONS - * If the given file has a matching extension then a new entry - * is added to the KeyedVector with the path as the key and the modification - * time as the value. - * - */ - static void checkAndAddFile(String8 path, const struct stat* stats, - Vector<String8>& extensions, - KeyedVector<String8,time_t>& fileStore); - -}; -#endif // FILEFINDER_H diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp deleted file mode 100644 index b2cbf49..0000000 --- a/tools/aapt/Images.cpp +++ /dev/null @@ -1,1387 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#define PNG_INTERNAL - -#include "Images.h" - -#include <androidfw/ResourceTypes.h> -#include <utils/ByteOrder.h> - -#include <png.h> -#include <zlib.h> - -#define NOISY(x) //x - -static void -png_write_aapt_file(png_structp png_ptr, png_bytep data, png_size_t length) -{ - AaptFile* aaptfile = (AaptFile*) png_get_io_ptr(png_ptr); - status_t err = aaptfile->writeData(data, length); - if (err != NO_ERROR) { - png_error(png_ptr, "Write Error"); - } -} - - -static void -png_flush_aapt_file(png_structp png_ptr) -{ -} - -// This holds an image as 8bpp RGBA. -struct image_info -{ - image_info() : rows(NULL), is9Patch(false), allocRows(NULL) { } - ~image_info() { - if (rows && rows != allocRows) { - free(rows); - } - if (allocRows) { - for (int i=0; i<(int)allocHeight; i++) { - free(allocRows[i]); - } - free(allocRows); - } - free(info9Patch.xDivs); - free(info9Patch.yDivs); - free(info9Patch.colors); - } - - png_uint_32 width; - png_uint_32 height; - png_bytepp rows; - - // 9-patch info. - bool is9Patch; - Res_png_9patch info9Patch; - - // Layout padding, if relevant - bool haveLayoutBounds; - int32_t layoutBoundsLeft; - int32_t layoutBoundsTop; - int32_t layoutBoundsRight; - int32_t layoutBoundsBottom; - - png_uint_32 allocHeight; - png_bytepp allocRows; -}; - -static void read_png(const char* imageName, - png_structp read_ptr, png_infop read_info, - image_info* outImageInfo) -{ - int color_type; - int bit_depth, interlace_type, compression_type; - int i; - - png_read_info(read_ptr, read_info); - - png_get_IHDR(read_ptr, read_info, &outImageInfo->width, - &outImageInfo->height, &bit_depth, &color_type, - &interlace_type, &compression_type, NULL); - - //printf("Image %s:\n", imageName); - //printf("color_type=%d, bit_depth=%d, interlace_type=%d, compression_type=%d\n", - // color_type, bit_depth, interlace_type, compression_type); - - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(read_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_expand_gray_1_2_4_to_8(read_ptr); - - if (png_get_valid(read_ptr, read_info, PNG_INFO_tRNS)) { - //printf("Has PNG_INFO_tRNS!\n"); - png_set_tRNS_to_alpha(read_ptr); - } - - if (bit_depth == 16) - png_set_strip_16(read_ptr); - - if ((color_type&PNG_COLOR_MASK_ALPHA) == 0) - png_set_add_alpha(read_ptr, 0xFF, PNG_FILLER_AFTER); - - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(read_ptr); - - png_read_update_info(read_ptr, read_info); - - outImageInfo->rows = (png_bytepp)malloc( - outImageInfo->height * sizeof(png_bytep)); - outImageInfo->allocHeight = outImageInfo->height; - outImageInfo->allocRows = outImageInfo->rows; - - png_set_rows(read_ptr, read_info, outImageInfo->rows); - - for (i = 0; i < (int)outImageInfo->height; i++) - { - outImageInfo->rows[i] = (png_bytep) - malloc(png_get_rowbytes(read_ptr, read_info)); - } - - png_read_image(read_ptr, outImageInfo->rows); - - png_read_end(read_ptr, read_info); - - NOISY(printf("Image %s: w=%d, h=%d, d=%d, colors=%d, inter=%d, comp=%d\n", - imageName, - (int)outImageInfo->width, (int)outImageInfo->height, - bit_depth, color_type, - interlace_type, compression_type)); - - png_get_IHDR(read_ptr, read_info, &outImageInfo->width, - &outImageInfo->height, &bit_depth, &color_type, - &interlace_type, &compression_type, NULL); -} - -#define COLOR_TRANSPARENT 0 -#define COLOR_WHITE 0xFFFFFFFF -#define COLOR_TICK 0xFF000000 -#define COLOR_LAYOUT_BOUNDS_TICK 0xFF0000FF - -enum { - TICK_TYPE_NONE, - TICK_TYPE_TICK, - TICK_TYPE_LAYOUT_BOUNDS, - TICK_TYPE_BOTH -}; - -static int tick_type(png_bytep p, bool transparent, const char** outError) -{ - png_uint_32 color = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - - if (transparent) { - if (p[3] == 0) { - return TICK_TYPE_NONE; - } - if (color == COLOR_LAYOUT_BOUNDS_TICK) { - return TICK_TYPE_LAYOUT_BOUNDS; - } - if (color == COLOR_TICK) { - return TICK_TYPE_TICK; - } - - // Error cases - if (p[3] != 0xff) { - *outError = "Frame pixels must be either solid or transparent (not intermediate alphas)"; - return TICK_TYPE_NONE; - } - if (p[0] != 0 || p[1] != 0 || p[2] != 0) { - *outError = "Ticks in transparent frame must be black or red"; - } - return TICK_TYPE_TICK; - } - - if (p[3] != 0xFF) { - *outError = "White frame must be a solid color (no alpha)"; - } - if (color == COLOR_WHITE) { - return TICK_TYPE_NONE; - } - if (color == COLOR_TICK) { - return TICK_TYPE_TICK; - } - if (color == COLOR_LAYOUT_BOUNDS_TICK) { - return TICK_TYPE_LAYOUT_BOUNDS; - } - - if (p[0] != 0 || p[1] != 0 || p[2] != 0) { - *outError = "Ticks in white frame must be black or red"; - return TICK_TYPE_NONE; - } - return TICK_TYPE_TICK; -} - -enum { - TICK_START, - TICK_INSIDE_1, - TICK_OUTSIDE_1 -}; - -static status_t get_horizontal_ticks( - png_bytep row, int width, bool transparent, bool required, - int32_t* outLeft, int32_t* outRight, const char** outError, - uint8_t* outDivs, bool multipleAllowed) -{ - int i; - *outLeft = *outRight = -1; - int state = TICK_START; - bool found = false; - - for (i=1; i<width-1; i++) { - if (TICK_TYPE_TICK == tick_type(row+i*4, transparent, outError)) { - if (state == TICK_START || - (state == TICK_OUTSIDE_1 && multipleAllowed)) { - *outLeft = i-1; - *outRight = width-2; - found = true; - if (outDivs != NULL) { - *outDivs += 2; - } - state = TICK_INSIDE_1; - } else if (state == TICK_OUTSIDE_1) { - *outError = "Can't have more than one marked region along edge"; - *outLeft = i; - return UNKNOWN_ERROR; - } - } else if (*outError == NULL) { - if (state == TICK_INSIDE_1) { - // We're done with this div. Move on to the next. - *outRight = i-1; - outRight += 2; - outLeft += 2; - state = TICK_OUTSIDE_1; - } - } else { - *outLeft = i; - return UNKNOWN_ERROR; - } - } - - if (required && !found) { - *outError = "No marked region found along edge"; - *outLeft = -1; - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -static status_t get_vertical_ticks( - png_bytepp rows, int offset, int height, bool transparent, bool required, - int32_t* outTop, int32_t* outBottom, const char** outError, - uint8_t* outDivs, bool multipleAllowed) -{ - int i; - *outTop = *outBottom = -1; - int state = TICK_START; - bool found = false; - - for (i=1; i<height-1; i++) { - if (TICK_TYPE_TICK == tick_type(rows[i]+offset, transparent, outError)) { - if (state == TICK_START || - (state == TICK_OUTSIDE_1 && multipleAllowed)) { - *outTop = i-1; - *outBottom = height-2; - found = true; - if (outDivs != NULL) { - *outDivs += 2; - } - state = TICK_INSIDE_1; - } else if (state == TICK_OUTSIDE_1) { - *outError = "Can't have more than one marked region along edge"; - *outTop = i; - return UNKNOWN_ERROR; - } - } else if (*outError == NULL) { - if (state == TICK_INSIDE_1) { - // We're done with this div. Move on to the next. - *outBottom = i-1; - outTop += 2; - outBottom += 2; - state = TICK_OUTSIDE_1; - } - } else { - *outTop = i; - return UNKNOWN_ERROR; - } - } - - if (required && !found) { - *outError = "No marked region found along edge"; - *outTop = -1; - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -static status_t get_horizontal_layout_bounds_ticks( - png_bytep row, int width, bool transparent, bool required, - int32_t* outLeft, int32_t* outRight, const char** outError) -{ - int i; - *outLeft = *outRight = 0; - - // Look for left tick - if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(row + 4, transparent, outError)) { - // Starting with a layout padding tick - i = 1; - while (i < width - 1) { - (*outLeft)++; - i++; - int tick = tick_type(row + i * 4, transparent, outError); - if (tick != TICK_TYPE_LAYOUT_BOUNDS) { - break; - } - } - } - - // Look for right tick - if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(row + (width - 2) * 4, transparent, outError)) { - // Ending with a layout padding tick - i = width - 2; - while (i > 1) { - (*outRight)++; - i--; - int tick = tick_type(row+i*4, transparent, outError); - if (tick != TICK_TYPE_LAYOUT_BOUNDS) { - break; - } - } - } - - return NO_ERROR; -} - -static status_t get_vertical_layout_bounds_ticks( - png_bytepp rows, int offset, int height, bool transparent, bool required, - int32_t* outTop, int32_t* outBottom, const char** outError) -{ - int i; - *outTop = *outBottom = 0; - - // Look for top tick - if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(rows[1] + offset, transparent, outError)) { - // Starting with a layout padding tick - i = 1; - while (i < height - 1) { - (*outTop)++; - i++; - int tick = tick_type(rows[i] + offset, transparent, outError); - if (tick != TICK_TYPE_LAYOUT_BOUNDS) { - break; - } - } - } - - // Look for bottom tick - if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(rows[height - 2] + offset, transparent, outError)) { - // Ending with a layout padding tick - i = height - 2; - while (i > 1) { - (*outBottom)++; - i--; - int tick = tick_type(rows[i] + offset, transparent, outError); - if (tick != TICK_TYPE_LAYOUT_BOUNDS) { - break; - } - } - } - - return NO_ERROR; -} - - -static uint32_t get_color( - png_bytepp rows, int left, int top, int right, int bottom) -{ - png_bytep color = rows[top] + left*4; - - if (left > right || top > bottom) { - return Res_png_9patch::TRANSPARENT_COLOR; - } - - while (top <= bottom) { - for (int i = left; i <= right; i++) { - png_bytep p = rows[top]+i*4; - if (color[3] == 0) { - if (p[3] != 0) { - return Res_png_9patch::NO_COLOR; - } - } else if (p[0] != color[0] || p[1] != color[1] - || p[2] != color[2] || p[3] != color[3]) { - return Res_png_9patch::NO_COLOR; - } - } - top++; - } - - if (color[3] == 0) { - return Res_png_9patch::TRANSPARENT_COLOR; - } - return (color[3]<<24) | (color[0]<<16) | (color[1]<<8) | color[2]; -} - -static void select_patch( - int which, int front, int back, int size, int* start, int* end) -{ - switch (which) { - case 0: - *start = 0; - *end = front-1; - break; - case 1: - *start = front; - *end = back-1; - break; - case 2: - *start = back; - *end = size-1; - break; - } -} - -static uint32_t get_color(image_info* image, int hpatch, int vpatch) -{ - int left, right, top, bottom; - select_patch( - hpatch, image->info9Patch.xDivs[0], image->info9Patch.xDivs[1], - image->width, &left, &right); - select_patch( - vpatch, image->info9Patch.yDivs[0], image->info9Patch.yDivs[1], - image->height, &top, &bottom); - //printf("Selecting h=%d v=%d: (%d,%d)-(%d,%d)\n", - // hpatch, vpatch, left, top, right, bottom); - const uint32_t c = get_color(image->rows, left, top, right, bottom); - NOISY(printf("Color in (%d,%d)-(%d,%d): #%08x\n", left, top, right, bottom, c)); - return c; -} - -static status_t do_9patch(const char* imageName, image_info* image) -{ - image->is9Patch = true; - - int W = image->width; - int H = image->height; - int i, j; - - int maxSizeXDivs = W * sizeof(int32_t); - int maxSizeYDivs = H * sizeof(int32_t); - int32_t* xDivs = (int32_t*) malloc(maxSizeXDivs); - int32_t* yDivs = (int32_t*) malloc(maxSizeYDivs); - uint8_t numXDivs = 0; - uint8_t numYDivs = 0; - int8_t numColors; - int numRows; - int numCols; - int top; - int left; - int right; - int bottom; - memset(xDivs, -1, maxSizeXDivs); - memset(yDivs, -1, maxSizeYDivs); - image->info9Patch.paddingLeft = image->info9Patch.paddingRight = - image->info9Patch.paddingTop = image->info9Patch.paddingBottom = -1; - - image->layoutBoundsLeft = image->layoutBoundsRight = - image->layoutBoundsTop = image->layoutBoundsBottom = 0; - - png_bytep p = image->rows[0]; - bool transparent = p[3] == 0; - bool hasColor = false; - - const char* errorMsg = NULL; - int errorPixel = -1; - const char* errorEdge = NULL; - - int colorIndex = 0; - - // Validate size... - if (W < 3 || H < 3) { - errorMsg = "Image must be at least 3x3 (1x1 without frame) pixels"; - goto getout; - } - - // Validate frame... - if (!transparent && - (p[0] != 0xFF || p[1] != 0xFF || p[2] != 0xFF || p[3] != 0xFF)) { - errorMsg = "Must have one-pixel frame that is either transparent or white"; - goto getout; - } - - // Find left and right of sizing areas... - if (get_horizontal_ticks(p, W, transparent, true, &xDivs[0], - &xDivs[1], &errorMsg, &numXDivs, true) != NO_ERROR) { - errorPixel = xDivs[0]; - errorEdge = "top"; - goto getout; - } - - // Find top and bottom of sizing areas... - if (get_vertical_ticks(image->rows, 0, H, transparent, true, &yDivs[0], - &yDivs[1], &errorMsg, &numYDivs, true) != NO_ERROR) { - errorPixel = yDivs[0]; - errorEdge = "left"; - goto getout; - } - - // Find left and right of padding area... - if (get_horizontal_ticks(image->rows[H-1], W, transparent, false, &image->info9Patch.paddingLeft, - &image->info9Patch.paddingRight, &errorMsg, NULL, false) != NO_ERROR) { - errorPixel = image->info9Patch.paddingLeft; - errorEdge = "bottom"; - goto getout; - } - - // Find top and bottom of padding area... - if (get_vertical_ticks(image->rows, (W-1)*4, H, transparent, false, &image->info9Patch.paddingTop, - &image->info9Patch.paddingBottom, &errorMsg, NULL, false) != NO_ERROR) { - errorPixel = image->info9Patch.paddingTop; - errorEdge = "right"; - goto getout; - } - - // Find left and right of layout padding... - get_horizontal_layout_bounds_ticks(image->rows[H-1], W, transparent, false, - &image->layoutBoundsLeft, - &image->layoutBoundsRight, &errorMsg); - - get_vertical_layout_bounds_ticks(image->rows, (W-1)*4, H, transparent, false, - &image->layoutBoundsTop, - &image->layoutBoundsBottom, &errorMsg); - - image->haveLayoutBounds = image->layoutBoundsLeft != 0 - || image->layoutBoundsRight != 0 - || image->layoutBoundsTop != 0 - || image->layoutBoundsBottom != 0; - - if (image->haveLayoutBounds) { - NOISY(printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, image->layoutBoundsTop, - image->layoutBoundsRight, image->layoutBoundsBottom)); - } - - // Copy patch data into image - image->info9Patch.numXDivs = numXDivs; - image->info9Patch.numYDivs = numYDivs; - image->info9Patch.xDivs = xDivs; - image->info9Patch.yDivs = yDivs; - - // If padding is not yet specified, take values from size. - if (image->info9Patch.paddingLeft < 0) { - image->info9Patch.paddingLeft = xDivs[0]; - image->info9Patch.paddingRight = W - 2 - xDivs[1]; - } else { - // Adjust value to be correct! - image->info9Patch.paddingRight = W - 2 - image->info9Patch.paddingRight; - } - if (image->info9Patch.paddingTop < 0) { - image->info9Patch.paddingTop = yDivs[0]; - image->info9Patch.paddingBottom = H - 2 - yDivs[1]; - } else { - // Adjust value to be correct! - image->info9Patch.paddingBottom = H - 2 - image->info9Patch.paddingBottom; - } - - NOISY(printf("Size ticks for %s: x0=%d, x1=%d, y0=%d, y1=%d\n", imageName, - image->info9Patch.xDivs[0], image->info9Patch.xDivs[1], - image->info9Patch.yDivs[0], image->info9Patch.yDivs[1])); - NOISY(printf("padding ticks for %s: l=%d, r=%d, t=%d, b=%d\n", imageName, - image->info9Patch.paddingLeft, image->info9Patch.paddingRight, - image->info9Patch.paddingTop, image->info9Patch.paddingBottom)); - - // Remove frame from image. - image->rows = (png_bytepp)malloc((H-2) * sizeof(png_bytep)); - for (i=0; i<(H-2); i++) { - image->rows[i] = image->allocRows[i+1]; - memmove(image->rows[i], image->rows[i]+4, (W-2)*4); - } - image->width -= 2; - W = image->width; - image->height -= 2; - H = image->height; - - // Figure out the number of rows and columns in the N-patch - numCols = numXDivs + 1; - if (xDivs[0] == 0) { // Column 1 is strechable - numCols--; - } - if (xDivs[numXDivs - 1] == W) { - numCols--; - } - numRows = numYDivs + 1; - if (yDivs[0] == 0) { // Row 1 is strechable - numRows--; - } - if (yDivs[numYDivs - 1] == H) { - numRows--; - } - - // Make sure the amount of rows and columns will fit in the number of - // colors we can use in the 9-patch format. - if (numRows * numCols > 0x7F) { - errorMsg = "Too many rows and columns in 9-patch perimeter"; - goto getout; - } - - numColors = numRows * numCols; - image->info9Patch.numColors = numColors; - image->info9Patch.colors = (uint32_t*)malloc(numColors * sizeof(uint32_t)); - - // Fill in color information for each patch. - - uint32_t c; - top = 0; - - // The first row always starts with the top being at y=0 and the bottom - // being either yDivs[1] (if yDivs[0]=0) of yDivs[0]. In the former case - // the first row is stretchable along the Y axis, otherwise it is fixed. - // The last row always ends with the bottom being bitmap.height and the top - // being either yDivs[numYDivs-2] (if yDivs[numYDivs-1]=bitmap.height) or - // yDivs[numYDivs-1]. In the former case the last row is stretchable along - // the Y axis, otherwise it is fixed. - // - // The first and last columns are similarly treated with respect to the X - // axis. - // - // The above is to help explain some of the special casing that goes on the - // code below. - - // The initial yDiv and whether the first row is considered stretchable or - // not depends on whether yDiv[0] was zero or not. - for (j = (yDivs[0] == 0 ? 1 : 0); - j <= numYDivs && top < H; - j++) { - if (j == numYDivs) { - bottom = H; - } else { - bottom = yDivs[j]; - } - left = 0; - // The initial xDiv and whether the first column is considered - // stretchable or not depends on whether xDiv[0] was zero or not. - for (i = xDivs[0] == 0 ? 1 : 0; - i <= numXDivs && left < W; - i++) { - if (i == numXDivs) { - right = W; - } else { - right = xDivs[i]; - } - c = get_color(image->rows, left, top, right - 1, bottom - 1); - image->info9Patch.colors[colorIndex++] = c; - NOISY(if (c != Res_png_9patch::NO_COLOR) hasColor = true); - left = right; - } - top = bottom; - } - - assert(colorIndex == numColors); - - for (i=0; i<numColors; i++) { - if (hasColor) { - if (i == 0) printf("Colors in %s:\n ", imageName); - printf(" #%08x", image->info9Patch.colors[i]); - if (i == numColors - 1) printf("\n"); - } - } - - image->is9Patch = true; - image->info9Patch.deviceToFile(); - -getout: - if (errorMsg) { - fprintf(stderr, - "ERROR: 9-patch image %s malformed.\n" - " %s.\n", imageName, errorMsg); - if (errorEdge != NULL) { - if (errorPixel >= 0) { - fprintf(stderr, - " Found at pixel #%d along %s edge.\n", errorPixel, errorEdge); - } else { - fprintf(stderr, - " Found along %s edge.\n", errorEdge); - } - } - return UNKNOWN_ERROR; - } - return NO_ERROR; -} - -static void checkNinePatchSerialization(Res_png_9patch* inPatch, void * data) -{ - if (sizeof(void*) != sizeof(int32_t)) { - // can't deserialize on a non-32 bit system - return; - } - size_t patchSize = inPatch->serializedSize(); - void * newData = malloc(patchSize); - memcpy(newData, data, patchSize); - Res_png_9patch* outPatch = inPatch->deserialize(newData); - // deserialization is done in place, so outPatch == newData - assert(outPatch == newData); - assert(outPatch->numXDivs == inPatch->numXDivs); - assert(outPatch->numYDivs == inPatch->numYDivs); - assert(outPatch->paddingLeft == inPatch->paddingLeft); - assert(outPatch->paddingRight == inPatch->paddingRight); - assert(outPatch->paddingTop == inPatch->paddingTop); - assert(outPatch->paddingBottom == inPatch->paddingBottom); - for (int i = 0; i < outPatch->numXDivs; i++) { - assert(outPatch->xDivs[i] == inPatch->xDivs[i]); - } - for (int i = 0; i < outPatch->numYDivs; i++) { - assert(outPatch->yDivs[i] == inPatch->yDivs[i]); - } - for (int i = 0; i < outPatch->numColors; i++) { - assert(outPatch->colors[i] == inPatch->colors[i]); - } - free(newData); -} - -static bool patch_equals(Res_png_9patch& patch1, Res_png_9patch& patch2) { - if (!(patch1.numXDivs == patch2.numXDivs && - patch1.numYDivs == patch2.numYDivs && - patch1.numColors == patch2.numColors && - patch1.paddingLeft == patch2.paddingLeft && - patch1.paddingRight == patch2.paddingRight && - patch1.paddingTop == patch2.paddingTop && - patch1.paddingBottom == patch2.paddingBottom)) { - return false; - } - for (int i = 0; i < patch1.numColors; i++) { - if (patch1.colors[i] != patch2.colors[i]) { - return false; - } - } - for (int i = 0; i < patch1.numXDivs; i++) { - if (patch1.xDivs[i] != patch2.xDivs[i]) { - return false; - } - } - for (int i = 0; i < patch1.numYDivs; i++) { - if (patch1.yDivs[i] != patch2.yDivs[i]) { - return false; - } - } - return true; -} - -static void dump_image(int w, int h, png_bytepp rows, int color_type) -{ - int i, j, rr, gg, bb, aa; - - int bpp; - if (color_type == PNG_COLOR_TYPE_PALETTE || color_type == PNG_COLOR_TYPE_GRAY) { - bpp = 1; - } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - bpp = 2; - } else if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - // We use a padding byte even when there is no alpha - bpp = 4; - } else { - printf("Unknown color type %d.\n", color_type); - } - - for (j = 0; j < h; j++) { - png_bytep row = rows[j]; - for (i = 0; i < w; i++) { - rr = row[0]; - gg = row[1]; - bb = row[2]; - aa = row[3]; - row += bpp; - - if (i == 0) { - printf("Row %d:", j); - } - switch (bpp) { - case 1: - printf(" (%d)", rr); - break; - case 2: - printf(" (%d %d", rr, gg); - break; - case 3: - printf(" (%d %d %d)", rr, gg, bb); - break; - case 4: - printf(" (%d %d %d %d)", rr, gg, bb, aa); - break; - } - if (i == (w - 1)) { - NOISY(printf("\n")); - } - } - } -} - -#define MAX(a,b) ((a)>(b)?(a):(b)) -#define ABS(a) ((a)<0?-(a):(a)) - -static void analyze_image(const char *imageName, image_info &imageInfo, int grayscaleTolerance, - png_colorp rgbPalette, png_bytep alphaPalette, - int *paletteEntries, bool *hasTransparency, int *colorType, - png_bytepp outRows) -{ - int w = imageInfo.width; - int h = imageInfo.height; - int i, j, rr, gg, bb, aa, idx; - uint32_t colors[256], col; - int num_colors = 0; - int maxGrayDeviation = 0; - - bool isOpaque = true; - bool isPalette = true; - bool isGrayscale = true; - - // Scan the entire image and determine if: - // 1. Every pixel has R == G == B (grayscale) - // 2. Every pixel has A == 255 (opaque) - // 3. There are no more than 256 distinct RGBA colors - - // NOISY(printf("Initial image data:\n")); - // dump_image(w, h, imageInfo.rows, PNG_COLOR_TYPE_RGB_ALPHA); - - for (j = 0; j < h; j++) { - png_bytep row = imageInfo.rows[j]; - png_bytep out = outRows[j]; - for (i = 0; i < w; i++) { - rr = *row++; - gg = *row++; - bb = *row++; - aa = *row++; - - int odev = maxGrayDeviation; - maxGrayDeviation = MAX(ABS(rr - gg), maxGrayDeviation); - maxGrayDeviation = MAX(ABS(gg - bb), maxGrayDeviation); - maxGrayDeviation = MAX(ABS(bb - rr), maxGrayDeviation); - if (maxGrayDeviation > odev) { - NOISY(printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n", - maxGrayDeviation, i, j, rr, gg, bb, aa)); - } - - // Check if image is really grayscale - if (isGrayscale) { - if (rr != gg || rr != bb) { - NOISY(printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", - i, j, rr, gg, bb, aa)); - isGrayscale = false; - } - } - - // Check if image is really opaque - if (isOpaque) { - if (aa != 0xff) { - NOISY(printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", - i, j, rr, gg, bb, aa)); - isOpaque = false; - } - } - - // Check if image is really <= 256 colors - if (isPalette) { - col = (uint32_t) ((rr << 24) | (gg << 16) | (bb << 8) | aa); - bool match = false; - for (idx = 0; idx < num_colors; idx++) { - if (colors[idx] == col) { - match = true; - break; - } - } - - // Write the palette index for the pixel to outRows optimistically - // We might overwrite it later if we decide to encode as gray or - // gray + alpha - *out++ = idx; - if (!match) { - if (num_colors == 256) { - NOISY(printf("Found 257th color at %d, %d\n", i, j)); - isPalette = false; - } else { - colors[num_colors++] = col; - } - } - } - } - } - - *paletteEntries = 0; - *hasTransparency = !isOpaque; - int bpp = isOpaque ? 3 : 4; - int paletteSize = w * h + bpp * num_colors; - - NOISY(printf("isGrayscale = %s\n", isGrayscale ? "true" : "false")); - NOISY(printf("isOpaque = %s\n", isOpaque ? "true" : "false")); - NOISY(printf("isPalette = %s\n", isPalette ? "true" : "false")); - NOISY(printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", - paletteSize, 2 * w * h, bpp * w * h)); - NOISY(printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation, grayscaleTolerance)); - - // Choose the best color type for the image. - // 1. Opaque gray - use COLOR_TYPE_GRAY at 1 byte/pixel - // 2. Gray + alpha - use COLOR_TYPE_PALETTE if the number of distinct combinations - // is sufficiently small, otherwise use COLOR_TYPE_GRAY_ALPHA - // 3. RGB(A) - use COLOR_TYPE_PALETTE if the number of distinct colors is sufficiently - // small, otherwise use COLOR_TYPE_RGB{_ALPHA} - if (isGrayscale) { - if (isOpaque) { - *colorType = PNG_COLOR_TYPE_GRAY; // 1 byte/pixel - } else { - // Use a simple heuristic to determine whether using a palette will - // save space versus using gray + alpha for each pixel. - // This doesn't take into account chunk overhead, filtering, LZ - // compression, etc. - if (isPalette && (paletteSize < 2 * w * h)) { - *colorType = PNG_COLOR_TYPE_PALETTE; // 1 byte/pixel + 4 bytes/color - } else { - *colorType = PNG_COLOR_TYPE_GRAY_ALPHA; // 2 bytes per pixel - } - } - } else if (isPalette && (paletteSize < bpp * w * h)) { - *colorType = PNG_COLOR_TYPE_PALETTE; - } else { - if (maxGrayDeviation <= grayscaleTolerance) { - printf("%s: forcing image to gray (max deviation = %d)\n", imageName, maxGrayDeviation); - *colorType = isOpaque ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_GRAY_ALPHA; - } else { - *colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; - } - } - - // Perform postprocessing of the image or palette data based on the final - // color type chosen - - if (*colorType == PNG_COLOR_TYPE_PALETTE) { - // Create separate RGB and Alpha palettes and set the number of colors - *paletteEntries = num_colors; - - // Create the RGB and alpha palettes - for (int idx = 0; idx < num_colors; idx++) { - col = colors[idx]; - rgbPalette[idx].red = (png_byte) ((col >> 24) & 0xff); - rgbPalette[idx].green = (png_byte) ((col >> 16) & 0xff); - rgbPalette[idx].blue = (png_byte) ((col >> 8) & 0xff); - alphaPalette[idx] = (png_byte) (col & 0xff); - } - } else if (*colorType == PNG_COLOR_TYPE_GRAY || *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { - // If the image is gray or gray + alpha, compact the pixels into outRows - for (j = 0; j < h; j++) { - png_bytep row = imageInfo.rows[j]; - png_bytep out = outRows[j]; - for (i = 0; i < w; i++) { - rr = *row++; - gg = *row++; - bb = *row++; - aa = *row++; - - if (isGrayscale) { - *out++ = rr; - } else { - *out++ = (png_byte) (rr * 0.2126f + gg * 0.7152f + bb * 0.0722f); - } - if (!isOpaque) { - *out++ = aa; - } - } - } - } -} - - -static void write_png(const char* imageName, - png_structp write_ptr, png_infop write_info, - image_info& imageInfo, int grayscaleTolerance) -{ - bool optimize = true; - png_uint_32 width, height; - int color_type; - int bit_depth, interlace_type, compression_type; - int i; - - png_unknown_chunk unknowns[2]; - unknowns[0].data = NULL; - unknowns[1].data = NULL; - - png_bytepp outRows = (png_bytepp) malloc((int) imageInfo.height * sizeof(png_bytep)); - if (outRows == (png_bytepp) 0) { - printf("Can't allocate output buffer!\n"); - exit(1); - } - for (i = 0; i < (int) imageInfo.height; i++) { - outRows[i] = (png_bytep) malloc(2 * (int) imageInfo.width); - if (outRows[i] == (png_bytep) 0) { - printf("Can't allocate output buffer!\n"); - exit(1); - } - } - - png_set_compression_level(write_ptr, Z_BEST_COMPRESSION); - - NOISY(printf("Writing image %s: w = %d, h = %d\n", imageName, - (int) imageInfo.width, (int) imageInfo.height)); - - png_color rgbPalette[256]; - png_byte alphaPalette[256]; - bool hasTransparency; - int paletteEntries; - - analyze_image(imageName, imageInfo, grayscaleTolerance, rgbPalette, alphaPalette, - &paletteEntries, &hasTransparency, &color_type, outRows); - - // If the image is a 9-patch, we need to preserve it as a ARGB file to make - // sure the pixels will not be pre-dithered/clamped until we decide they are - if (imageInfo.is9Patch && (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)) { - color_type = PNG_COLOR_TYPE_RGB_ALPHA; - } - - switch (color_type) { - case PNG_COLOR_TYPE_PALETTE: - NOISY(printf("Image %s has %d colors%s, using PNG_COLOR_TYPE_PALETTE\n", - imageName, paletteEntries, - hasTransparency ? " (with alpha)" : "")); - break; - case PNG_COLOR_TYPE_GRAY: - NOISY(printf("Image %s is opaque gray, using PNG_COLOR_TYPE_GRAY\n", imageName)); - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - NOISY(printf("Image %s is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA\n", imageName)); - break; - case PNG_COLOR_TYPE_RGB: - NOISY(printf("Image %s is opaque RGB, using PNG_COLOR_TYPE_RGB\n", imageName)); - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - NOISY(printf("Image %s is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA\n", imageName)); - break; - } - - png_set_IHDR(write_ptr, write_info, imageInfo.width, imageInfo.height, - 8, color_type, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_PLTE(write_ptr, write_info, rgbPalette, paletteEntries); - if (hasTransparency) { - png_set_tRNS(write_ptr, write_info, alphaPalette, paletteEntries, (png_color_16p) 0); - } - png_set_filter(write_ptr, 0, PNG_NO_FILTERS); - } else { - png_set_filter(write_ptr, 0, PNG_ALL_FILTERS); - } - - if (imageInfo.is9Patch) { - int chunk_count = 1 + (imageInfo.haveLayoutBounds ? 1 : 0); - int p_index = imageInfo.haveLayoutBounds ? 1 : 0; - int b_index = 0; - png_byte *chunk_names = imageInfo.haveLayoutBounds - ? (png_byte*)"npLb\0npTc\0" - : (png_byte*)"npTc"; - NOISY(printf("Adding 9-patch info...\n")); - strcpy((char*)unknowns[p_index].name, "npTc"); - unknowns[p_index].data = (png_byte*)imageInfo.info9Patch.serialize(); - unknowns[p_index].size = imageInfo.info9Patch.serializedSize(); - // TODO: remove the check below when everything works - checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data); - - if (imageInfo.haveLayoutBounds) { - int chunk_size = sizeof(png_uint_32) * 4; - strcpy((char*)unknowns[b_index].name, "npLb"); - unknowns[b_index].data = (png_byte*) calloc(chunk_size, 1); - memcpy(unknowns[b_index].data, &imageInfo.layoutBoundsLeft, chunk_size); - unknowns[b_index].size = chunk_size; - } - - for (int i = 0; i < chunk_count; i++) { - unknowns[i].location = PNG_HAVE_PLTE; - } - png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, - chunk_names, chunk_count); - png_set_unknown_chunks(write_ptr, write_info, unknowns, chunk_count); -#if PNG_LIBPNG_VER < 10600 - /* Deal with unknown chunk location bug in 1.5.x and earlier */ - png_set_unknown_chunk_location(write_ptr, write_info, 0, PNG_HAVE_PLTE); - if (imageInfo.haveLayoutBounds) { - png_set_unknown_chunk_location(write_ptr, write_info, 1, PNG_HAVE_PLTE); - } -#endif - } - - - png_write_info(write_ptr, write_info); - - png_bytepp rows; - if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - if (color_type == PNG_COLOR_TYPE_RGB) { - png_set_filler(write_ptr, 0, PNG_FILLER_AFTER); - } - rows = imageInfo.rows; - } else { - rows = outRows; - } - png_write_image(write_ptr, rows); - -// NOISY(printf("Final image data:\n")); -// dump_image(imageInfo.width, imageInfo.height, rows, color_type); - - png_write_end(write_ptr, write_info); - - for (i = 0; i < (int) imageInfo.height; i++) { - free(outRows[i]); - } - free(outRows); - free(unknowns[0].data); - free(unknowns[1].data); - - png_get_IHDR(write_ptr, write_info, &width, &height, - &bit_depth, &color_type, &interlace_type, - &compression_type, NULL); - - NOISY(printf("Image written: w=%d, h=%d, d=%d, colors=%d, inter=%d, comp=%d\n", - (int)width, (int)height, bit_depth, color_type, interlace_type, - compression_type)); -} - -status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, - const sp<AaptFile>& file, String8* outNewLeafName) -{ - String8 ext(file->getPath().getPathExtension()); - - // We currently only process PNG images. - if (strcmp(ext.string(), ".png") != 0) { - return NO_ERROR; - } - - // Example of renaming a file: - //*outNewLeafName = file->getPath().getBasePath().getFileName(); - //outNewLeafName->append(".nupng"); - - String8 printableName(file->getPrintableSource()); - - if (bundle->getVerbose()) { - printf("Processing image: %s\n", printableName.string()); - } - - png_structp read_ptr = NULL; - png_infop read_info = NULL; - FILE* fp; - - image_info imageInfo; - - png_structp write_ptr = NULL; - png_infop write_info = NULL; - - status_t error = UNKNOWN_ERROR; - - const size_t nameLen = file->getPath().length(); - - fp = fopen(file->getSourceFile().string(), "rb"); - if (fp == NULL) { - fprintf(stderr, "%s: ERROR: Unable to open PNG file\n", printableName.string()); - goto bail; - } - - read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, (png_error_ptr)NULL, - (png_error_ptr)NULL); - if (!read_ptr) { - goto bail; - } - - read_info = png_create_info_struct(read_ptr); - if (!read_info) { - goto bail; - } - - if (setjmp(png_jmpbuf(read_ptr))) { - goto bail; - } - - png_init_io(read_ptr, fp); - - read_png(printableName.string(), read_ptr, read_info, &imageInfo); - - if (nameLen > 6) { - const char* name = file->getPath().string(); - if (name[nameLen-5] == '9' && name[nameLen-6] == '.') { - if (do_9patch(printableName.string(), &imageInfo) != NO_ERROR) { - goto bail; - } - } - } - - write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, (png_error_ptr)NULL, - (png_error_ptr)NULL); - if (!write_ptr) - { - goto bail; - } - - write_info = png_create_info_struct(write_ptr); - if (!write_info) - { - goto bail; - } - - png_set_write_fn(write_ptr, (void*)file.get(), - png_write_aapt_file, png_flush_aapt_file); - - if (setjmp(png_jmpbuf(write_ptr))) - { - goto bail; - } - - write_png(printableName.string(), write_ptr, write_info, imageInfo, - bundle->getGrayscaleTolerance()); - - error = NO_ERROR; - - if (bundle->getVerbose()) { - fseek(fp, 0, SEEK_END); - size_t oldSize = (size_t)ftell(fp); - size_t newSize = file->getSize(); - float factor = ((float)newSize)/oldSize; - int percent = (int)(factor*100); - printf(" (processed image %s: %d%% size of source)\n", printableName.string(), percent); - } - -bail: - if (read_ptr) { - png_destroy_read_struct(&read_ptr, &read_info, (png_infopp)NULL); - } - if (fp) { - fclose(fp); - } - if (write_ptr) { - png_destroy_write_struct(&write_ptr, &write_info); - } - - if (error != NO_ERROR) { - fprintf(stderr, "ERROR: Failure processing PNG image %s\n", - file->getPrintableSource().string()); - } - return error; -} - -status_t preProcessImageToCache(const Bundle* bundle, const String8& source, const String8& dest) -{ - png_structp read_ptr = NULL; - png_infop read_info = NULL; - - FILE* fp; - - image_info imageInfo; - - png_structp write_ptr = NULL; - png_infop write_info = NULL; - - status_t error = UNKNOWN_ERROR; - - if (bundle->getVerbose()) { - printf("Processing image to cache: %s => %s\n", source.string(), dest.string()); - } - - // Get a file handler to read from - fp = fopen(source.string(),"rb"); - if (fp == NULL) { - fprintf(stderr, "%s ERROR: Unable to open PNG file\n", source.string()); - return error; - } - - // Call libpng to get a struct to read image data into - read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!read_ptr) { - fclose(fp); - png_destroy_read_struct(&read_ptr, &read_info,NULL); - return error; - } - - // Call libpng to get a struct to read image info into - read_info = png_create_info_struct(read_ptr); - if (!read_info) { - fclose(fp); - png_destroy_read_struct(&read_ptr, &read_info,NULL); - return error; - } - - // Set a jump point for libpng to long jump back to on error - if (setjmp(png_jmpbuf(read_ptr))) { - fclose(fp); - png_destroy_read_struct(&read_ptr, &read_info,NULL); - return error; - } - - // Set up libpng to read from our file. - png_init_io(read_ptr,fp); - - // Actually read data from the file - read_png(source.string(), read_ptr, read_info, &imageInfo); - - // We're done reading so we can clean up - // Find old file size before releasing handle - fseek(fp, 0, SEEK_END); - size_t oldSize = (size_t)ftell(fp); - fclose(fp); - png_destroy_read_struct(&read_ptr, &read_info,NULL); - - // Check to see if we're dealing with a 9-patch - // If we are, process appropriately - if (source.getBasePath().getPathExtension() == ".9") { - if (do_9patch(source.string(), &imageInfo) != NO_ERROR) { - return error; - } - } - - // Call libpng to create a structure to hold the processed image data - // that can be written to disk - write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!write_ptr) { - png_destroy_write_struct(&write_ptr, &write_info); - return error; - } - - // Call libpng to create a structure to hold processed image info that can - // be written to disk - write_info = png_create_info_struct(write_ptr); - if (!write_info) { - png_destroy_write_struct(&write_ptr, &write_info); - return error; - } - - // Open up our destination file for writing - fp = fopen(dest.string(), "wb"); - if (!fp) { - fprintf(stderr, "%s ERROR: Unable to open PNG file\n", dest.string()); - png_destroy_write_struct(&write_ptr, &write_info); - return error; - } - - // Set up libpng to write to our file - png_init_io(write_ptr, fp); - - // Set up a jump for libpng to long jump back on on errors - if (setjmp(png_jmpbuf(write_ptr))) { - fclose(fp); - png_destroy_write_struct(&write_ptr, &write_info); - return error; - } - - // Actually write out to the new png - write_png(dest.string(), write_ptr, write_info, imageInfo, - bundle->getGrayscaleTolerance()); - - if (bundle->getVerbose()) { - // Find the size of our new file - FILE* reader = fopen(dest.string(), "rb"); - fseek(reader, 0, SEEK_END); - size_t newSize = (size_t)ftell(reader); - fclose(reader); - - float factor = ((float)newSize)/oldSize; - int percent = (int)(factor*100); - printf(" (processed image to cache entry %s: %d%% size of source)\n", - dest.string(), percent); - } - - //Clean up - fclose(fp); - png_destroy_write_struct(&write_ptr, &write_info); - - return NO_ERROR; -} - -status_t postProcessImage(const sp<AaptAssets>& assets, - ResourceTable* table, const sp<AaptFile>& file) -{ - String8 ext(file->getPath().getPathExtension()); - - // At this point, now that we have all the resource data, all we need to - // do is compile XML files. - if (strcmp(ext.string(), ".xml") == 0) { - return compileXmlFile(assets, file, table); - } - - return NO_ERROR; -} diff --git a/tools/aapt/Images.h b/tools/aapt/Images.h deleted file mode 100644 index 91b6554..0000000 --- a/tools/aapt/Images.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#ifndef IMAGES_H -#define IMAGES_H - -#include "ResourceTable.h" -#include "Bundle.h" - -#include <utils/String8.h> -#include <utils/RefBase.h> - -using android::String8; - -status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, - const sp<AaptFile>& file, String8* outNewLeafName); - -status_t preProcessImageToCache(const Bundle* bundle, const String8& source, const String8& dest); - -status_t postProcessImage(const sp<AaptAssets>& assets, - ResourceTable* table, const sp<AaptFile>& file); - -#endif diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp deleted file mode 100644 index 4a8aa9c..0000000 --- a/tools/aapt/Main.cpp +++ /dev/null @@ -1,655 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Android Asset Packaging Tool main entry point. -// -#include "Main.h" -#include "Bundle.h" - -#include <utils/Log.h> -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> - -#include <stdlib.h> -#include <getopt.h> -#include <assert.h> - -using namespace android; - -static const char* gProgName = "aapt"; - -/* - * When running under Cygwin on Windows, this will convert slash-based - * paths into back-slash-based ones. Otherwise the ApptAssets file comparisons - * fail later as they use back-slash separators under Windows. - * - * This operates in-place on the path string. - */ -void convertPath(char *path) { - if (path != NULL && OS_PATH_SEPARATOR != '/') { - for (; *path; path++) { - if (*path == '/') { - *path = OS_PATH_SEPARATOR; - } - } - } -} - -/* - * Print usage info. - */ -void usage(void) -{ - fprintf(stderr, "Android Asset Packaging Tool\n\n"); - fprintf(stderr, "Usage:\n"); - fprintf(stderr, - " %s l[ist] [-v] [-a] file.{zip,jar,apk}\n" - " List contents of Zip-compatible archive.\n\n", gProgName); - fprintf(stderr, - " %s d[ump] [--values] [--include-meta-data] WHAT file.{apk} [asset [asset ...]]\n" - " strings Print the contents of the resource table string pool in the APK.\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" - " configurations Print the configurations in the APK.\n" - " xmltree Print the compiled xmls in the given assets.\n" - " 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 ...]] [-g tolerance] [-j jarfile] \\\n" - " [--debug-mode] [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n" - " [--app-version VAL] [--app-version-name TEXT] [--custom-package VAL] \\\n" - " [--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 ...]] \\\n" - " [-F apk-file] [-J R-file-dir] \\\n" - " [--product product1,product2,...] \\\n" - " [-c CONFIGS] [--preferred-configurations CONFIGS] \\\n" - " [raw-files-dir [raw-files-dir] ...] \\\n" - " [--output-text-symbols DIR]\n" - "\n" - " Package the android resources. It will read assets and resources that are\n" - " supplied with the -M -A -S or raw-files-dir arguments. The -J -P -F and -R\n" - " options control which files are output.\n\n" - , gProgName); - fprintf(stderr, - " %s r[emove] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" - " Delete specified files from Zip-compatible archive.\n\n", - gProgName); - fprintf(stderr, - " %s a[dd] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" - " Add specified files to Zip-compatible archive.\n\n", gProgName); - fprintf(stderr, - " %s c[runch] [-v] -S resource-sources ... -C output-folder ...\n" - " Do PNG preprocessing on one or several resource folders\n" - " and store the results in the output folder.\n\n", gProgName); - fprintf(stderr, - " %s s[ingleCrunch] [-v] -i input-file -o outputfile\n" - " Do PNG preprocessing on a single file.\n\n", gProgName); - fprintf(stderr, - " %s v[ersion]\n" - " Print program version.\n\n", gProgName); - fprintf(stderr, - " Modifiers:\n" - " -a print Android-specific data (resources, manifest) when listing\n" - " -c specify which configurations to include. The default is all\n" - " configurations. The value of the parameter should be a comma\n" - " separated list of configuration values. Locales should be specified\n" - " as either a language or language-region pair. Some examples:\n" - " en\n" - " port,en\n" - " port,land,en_US\n" - " If you put the special locale, zz_ZZ on the list, it will perform\n" - " pseudolocalization on the default locale, modifying all of the\n" - " strings so you can look for strings that missed the\n" - " internationalization process. For example:\n" - " port,land,zz_ZZ\n" - " -d one or more device assets to include, separated by commas\n" - " -f force overwrite of existing files\n" - " -g specify a pixel tolerance to force images to grayscale, default 0\n" - " -j specify a jar or zip file containing classes to include\n" - " -k junk path of file(s) added\n" - " -m make package directories under location specified by -J\n" -#if 0 - " -p pseudolocalize the default configuration\n" -#endif - " -u update existing packages (add new, replace older, remove deleted files)\n" - " -v verbose output\n" - " -x create extending (non-application) resource IDs\n" - " -z require localization of resource attributes marked with\n" - " localization=\"suggested\"\n" - " -A additional directory in which to find raw asset files\n" - " -G A file to output proguard options into.\n" - " -F specify the apk file to output\n" - " -I add an existing package to base include set\n" - " -J specify where to output R.java resource constant definitions\n" - " -M specify full path to AndroidManifest.xml to include in zip\n" - " -P specify where to output public resource definitions\n" - " -S directory in which to find resources. Multiple directories will be scanned\n" - " and the first match found (left to right) will take precedence.\n" - " -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" - " --debug-mode\n" - " inserts android:debuggable=\"true\" in to the application node of the\n" - " manifest, making the application debuggable even on production devices.\n" - " --include-meta-data\n" - " when used with \"dump badging\" also includes meta-data tags.\n" - " --min-sdk-version\n" - " inserts android:minSdkVersion in to manifest. If the version is 7 or\n" - " 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" - " inserts android:versionCode in to manifest.\n" - " --version-name\n" - " inserts android:versionName in to manifest.\n" - " --custom-package\n" - " generates R.java into a different package.\n" - " --extra-packages\n" - " generate R.java for libraries. Separate libraries with ':'.\n" - " --generate-dependencies\n" - " generate dependency files in the same directories for R.java and resource package\n" - " --auto-add-overlay\n" - " Automatically add resources that are only in overlays.\n" - " --preferred-configurations\n" - " Like the -c option for filtering out unneeded configurations, but\n" - " only expresses a preference. If there is no resource available with\n" - " the preferred configuration then it will not be stripped.\n" - " --rename-manifest-package\n" - " Rewrite the manifest so that its package name is the package name\n" - " given here. Relative class names (for example .Foo) will be\n" - " changed to absolute names with the old package so that the code\n" - " does not need to change.\n" - " --rename-instrumentation-target-package\n" - " Rewrite the manifest so that all of its instrumentation\n" - " components target the given package. Useful when used in\n" - " conjunction with --rename-manifest-package to fix tests against\n" - " a package that has been renamed.\n" - " --product\n" - " Specifies which variant to choose for strings that have\n" - " product variants\n" - " --utf16\n" - " changes default encoding for resources to UTF-16. Only useful when API\n" - " level is set to 7 or higher where the default encoding is UTF-8.\n" - " --non-constant-id\n" - " Make the resources ID non constant. This is required to make an R java class\n" - " that does not contain the final value but is used to make reusable compiled\n" - " libraries that need to access resources.\n" - " --error-on-failed-insert\n" - " Forces aapt to return an error if it fails to insert values into the manifest\n" - " with --debug-mode, --min-sdk-version, --target-sdk-version --version-code\n" - " and --version-name.\n" - " Insertion typically fails if the manifest already defines the attribute.\n" - " --output-text-symbols\n" - " Generates a text file containing the resource symbols of the R class in the\n" - " specified folder.\n" - " --ignore-assets\n" - " Assets to be ignored. Default pattern is:\n" - " %s\n", - gDefaultIgnoreAssets); -} - -/* - * Dispatch the command. - */ -int handleCommand(Bundle* bundle) -{ - //printf("--- command %d (verbose=%d force=%d):\n", - // bundle->getCommand(), bundle->getVerbose(), bundle->getForce()); - //for (int i = 0; i < bundle->getFileSpecCount(); i++) - // printf(" %d: '%s'\n", i, bundle->getFileSpecEntry(i)); - - switch (bundle->getCommand()) { - case kCommandVersion: return doVersion(bundle); - case kCommandList: return doList(bundle); - case kCommandDump: return doDump(bundle); - case kCommandAdd: return doAdd(bundle); - case kCommandRemove: return doRemove(bundle); - case kCommandPackage: return doPackage(bundle); - case kCommandCrunch: return doCrunch(bundle); - case kCommandSingleCrunch: return doSingleCrunch(bundle); - default: - fprintf(stderr, "%s: requested command not yet supported\n", gProgName); - return 1; - } -} - -/* - * Parse args. - */ -int main(int argc, char* const argv[]) -{ - char *prog = argv[0]; - Bundle bundle; - bool wantUsage = false; - int result = 1; // pessimistically assume an error. - int tolerance = 0; - - /* default to compression */ - bundle.setCompressionMethod(ZipEntry::kCompressDeflated); - - if (argc < 2) { - wantUsage = true; - goto bail; - } - - if (argv[1][0] == 'v') - bundle.setCommand(kCommandVersion); - else if (argv[1][0] == 'd') - bundle.setCommand(kCommandDump); - else if (argv[1][0] == 'l') - bundle.setCommand(kCommandList); - else if (argv[1][0] == 'a') - bundle.setCommand(kCommandAdd); - else if (argv[1][0] == 'r') - bundle.setCommand(kCommandRemove); - else if (argv[1][0] == 'p') - bundle.setCommand(kCommandPackage); - else if (argv[1][0] == 'c') - bundle.setCommand(kCommandCrunch); - else if (argv[1][0] == 's') - bundle.setCommand(kCommandSingleCrunch); - else { - fprintf(stderr, "ERROR: Unknown command '%s'\n", argv[1]); - wantUsage = true; - goto bail; - } - argc -= 2; - argv += 2; - - /* - * Pull out flags. We support "-fv" and "-f -v". - */ - while (argc && argv[0][0] == '-') { - /* flag(s) found */ - const char* cp = argv[0] +1; - - while (*cp != '\0') { - switch (*cp) { - case 'v': - bundle.setVerbose(true); - break; - case 'a': - bundle.setAndroidList(true); - break; - case 'c': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-c' option\n"); - wantUsage = true; - goto bail; - } - bundle.addConfigurations(argv[0]); - break; - case 'f': - bundle.setForce(true); - break; - case 'g': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-g' option\n"); - wantUsage = true; - goto bail; - } - tolerance = atoi(argv[0]); - bundle.setGrayscaleTolerance(tolerance); - printf("%s: Images with deviation <= %d will be forced to grayscale.\n", prog, tolerance); - break; - case 'k': - bundle.setJunkPath(true); - break; - case 'm': - bundle.setMakePackageDirs(true); - break; -#if 0 - case 'p': - bundle.setPseudolocalize(true); - break; -#endif - case 'u': - bundle.setUpdate(true); - break; - case 'x': - bundle.setExtending(true); - break; - case 'z': - bundle.setRequireLocalization(true); - break; - case 'j': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-j' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.addJarFile(argv[0]); - break; - case 'A': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-A' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setAssetSourceDir(argv[0]); - break; - case 'G': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-G' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setProguardFile(argv[0]); - break; - case 'I': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-I' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.addPackageInclude(argv[0]); - break; - case 'F': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-F' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setOutputAPKFile(argv[0]); - break; - case 'J': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-J' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setRClassDir(argv[0]); - break; - case 'M': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-M' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setAndroidManifestFile(argv[0]); - break; - case 'P': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-P' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setPublicOutputFile(argv[0]); - break; - case 'S': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-S' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.addResourceSourceDir(argv[0]); - break; - case 'C': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-C' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setCrunchedOutputDir(argv[0]); - break; - case 'i': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-i' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setSingleCrunchInputFile(argv[0]); - break; - case 'o': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-o' option\n"); - wantUsage = true; - goto bail; - } - convertPath(argv[0]); - bundle.setSingleCrunchOutputFile(argv[0]); - break; - case '0': - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-e' option\n"); - wantUsage = true; - goto bail; - } - if (argv[0][0] != 0) { - bundle.addNoCompressExtension(argv[0]); - } else { - bundle.setCompressionMethod(ZipEntry::kCompressStored); - } - break; - case '-': - if (strcmp(cp, "-debug-mode") == 0) { - bundle.setDebugMode(true); - } else 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, "-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++; - 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 if (strcmp(cp, "-include-meta-data") == 0) { - bundle.setIncludeMetaData(true); - } else if (strcmp(cp, "-custom-package") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--custom-package' option\n"); - wantUsage = true; - goto bail; - } - bundle.setCustomPackage(argv[0]); - } else if (strcmp(cp, "-extra-packages") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--extra-packages' option\n"); - wantUsage = true; - goto bail; - } - bundle.setExtraPackages(argv[0]); - } else if (strcmp(cp, "-generate-dependencies") == 0) { - bundle.setGenDependencies(true); - } else if (strcmp(cp, "-utf16") == 0) { - bundle.setWantUTF16(true); - } else if (strcmp(cp, "-preferred-configurations") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--preferred-configurations' option\n"); - wantUsage = true; - goto bail; - } - bundle.addPreferredConfigurations(argv[0]); - } else if (strcmp(cp, "-rename-manifest-package") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--rename-manifest-package' option\n"); - wantUsage = true; - goto bail; - } - bundle.setManifestPackageNameOverride(argv[0]); - } else if (strcmp(cp, "-rename-instrumentation-target-package") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--rename-instrumentation-target-package' option\n"); - wantUsage = true; - goto bail; - } - bundle.setInstrumentationPackageNameOverride(argv[0]); - } else if (strcmp(cp, "-auto-add-overlay") == 0) { - bundle.setAutoAddOverlay(true); - } else if (strcmp(cp, "-error-on-failed-insert") == 0) { - bundle.setErrorOnFailedInsert(true); - } else if (strcmp(cp, "-output-text-symbols") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '-output-text-symbols' option\n"); - wantUsage = true; - goto bail; - } - bundle.setOutputTextSymbols(argv[0]); - } else if (strcmp(cp, "-product") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--product' option\n"); - wantUsage = true; - goto bail; - } - bundle.setProduct(argv[0]); - } else if (strcmp(cp, "-non-constant-id") == 0) { - bundle.setNonConstantId(true); - } else if (strcmp(cp, "-no-crunch") == 0) { - bundle.setUseCrunchCache(true); - } else if (strcmp(cp, "-ignore-assets") == 0) { - argc--; - argv++; - if (!argc) { - fprintf(stderr, "ERROR: No argument supplied for '--ignore-assets' option\n"); - wantUsage = true; - goto bail; - } - gUserIgnoreAssets = argv[0]; - } 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; - goto bail; - } - - cp++; - } - argc--; - argv++; - } - - /* - * We're past the flags. The rest all goes straight in. - */ - bundle.setFileSpec(argv, argc); - - result = handleCommand(&bundle); - -bail: - if (wantUsage) { - usage(); - result = 2; - } - - //printf("--> returning %d\n", result); - return result; -} diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h deleted file mode 100644 index a6b39ac..0000000 --- a/tools/aapt/Main.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Some global defines that don't really merit their own header. -// -#ifndef __MAIN_H -#define __MAIN_H - -#include <utils/Log.h> -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> -#include "Bundle.h" -#include "AaptAssets.h" -#include "ZipFile.h" - - -/* Benchmarking Flag */ -//#define BENCHMARK 1 - -#if BENCHMARK - #include <time.h> -#endif /* BENCHMARK */ - -extern int doVersion(Bundle* bundle); -extern int doList(Bundle* bundle); -extern int doDump(Bundle* bundle); -extern int doAdd(Bundle* bundle); -extern int doRemove(Bundle* bundle); -extern int doPackage(Bundle* bundle); -extern int doCrunch(Bundle* bundle); -extern int doSingleCrunch(Bundle* bundle); - -extern int calcPercent(long uncompressedLen, long compressedLen); - -extern android::status_t writeAPK(Bundle* bundle, - const sp<AaptAssets>& assets, - const android::String8& outputFile); - -extern android::status_t updatePreProcessedCache(Bundle* bundle); - -extern android::status_t buildResources(Bundle* bundle, - const sp<AaptAssets>& assets); - -extern android::status_t writeResourceSymbols(Bundle* bundle, - const sp<AaptAssets>& assets, const String8& pkgName, bool includePrivate); - -extern android::status_t writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets); - -extern bool isValidResourceType(const String8& type); - -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptAssets>& assets); - -extern status_t filterResources(Bundle* bundle, const sp<AaptAssets>& assets); - -int dumpResources(Bundle* bundle); - -String8 getAttribute(const ResXMLTree& tree, const char* ns, - const char* attr, String8* outError); - -status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, - FILE* fp, bool includeRaw); -#endif // __MAIN_H diff --git a/tools/aapt/NOTICE b/tools/aapt/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/tools/aapt/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp deleted file mode 100644 index 872d95c..0000000 --- a/tools/aapt/Package.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Package assets into Zip files. -// -#include "Main.h" -#include "AaptAssets.h" -#include "ResourceTable.h" -#include "ResourceFilter.h" - -#include <androidfw/misc.h> - -#include <utils/Log.h> -#include <utils/threads.h> -#include <utils/List.h> -#include <utils/Errors.h> -#include <utils/misc.h> - -#include <sys/types.h> -#include <dirent.h> -#include <ctype.h> -#include <errno.h> - -using namespace android; - -static const char* kExcludeExtension = ".EXCLUDE"; - -/* these formats are already compressed, or don't compress well */ -static const char* kNoCompressExt[] = { - ".jpg", ".jpeg", ".png", ".gif", - ".wav", ".mp2", ".mp3", ".ogg", ".aac", - ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", - ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", - ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", - ".amr", ".awb", ".wma", ".wmv" -}; - -/* fwd decls, so I can write this downward */ -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptAssets>& assets); -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptDir>& dir, - const AaptGroupEntry& ge, const ResourceFilter* filter); -bool processFile(Bundle* bundle, ZipFile* zip, - const sp<AaptGroup>& group, const sp<AaptFile>& file); -bool okayToCompress(Bundle* bundle, const String8& pathName); -ssize_t processJarFiles(Bundle* bundle, ZipFile* zip); - -/* - * The directory hierarchy looks like this: - * "outputDir" and "assetRoot" are existing directories. - * - * On success, "bundle->numPackages" will be the number of Zip packages - * we created. - */ -status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets, - const String8& outputFile) -{ - #if BENCHMARK - fprintf(stdout, "BENCHMARK: Starting APK Bundling \n"); - long startAPKTime = clock(); - #endif /* BENCHMARK */ - - status_t result = NO_ERROR; - ZipFile* zip = NULL; - int count; - - //bundle->setPackageCount(0); - - /* - * Prep the Zip archive. - * - * If the file already exists, fail unless "update" or "force" is set. - * If "update" is set, update the contents of the existing archive. - * Else, if "force" is set, remove the existing archive. - */ - FileType fileType = getFileType(outputFile.string()); - if (fileType == kFileTypeNonexistent) { - // okay, create it below - } else if (fileType == kFileTypeRegular) { - if (bundle->getUpdate()) { - // okay, open it below - } else if (bundle->getForce()) { - if (unlink(outputFile.string()) != 0) { - fprintf(stderr, "ERROR: unable to remove '%s': %s\n", outputFile.string(), - strerror(errno)); - goto bail; - } - } else { - fprintf(stderr, "ERROR: '%s' exists (use '-f' to force overwrite)\n", - outputFile.string()); - goto bail; - } - } else { - fprintf(stderr, "ERROR: '%s' exists and is not a regular file\n", outputFile.string()); - goto bail; - } - - if (bundle->getVerbose()) { - printf("%s '%s'\n", (fileType == kFileTypeNonexistent) ? "Creating" : "Opening", - outputFile.string()); - } - - status_t status; - zip = new ZipFile; - status = zip->open(outputFile.string(), ZipFile::kOpenReadWrite | ZipFile::kOpenCreate); - if (status != NO_ERROR) { - fprintf(stderr, "ERROR: unable to open '%s' as Zip file for writing\n", - outputFile.string()); - goto bail; - } - - if (bundle->getVerbose()) { - printf("Writing all files...\n"); - } - - count = processAssets(bundle, zip, assets); - if (count < 0) { - fprintf(stderr, "ERROR: unable to process assets while packaging '%s'\n", - outputFile.string()); - result = count; - goto bail; - } - - if (bundle->getVerbose()) { - printf("Generated %d file%s\n", count, (count==1) ? "" : "s"); - } - - count = processJarFiles(bundle, zip); - if (count < 0) { - fprintf(stderr, "ERROR: unable to process jar files while packaging '%s'\n", - outputFile.string()); - result = count; - goto bail; - } - - if (bundle->getVerbose()) - printf("Included %d file%s from jar/zip files.\n", count, (count==1) ? "" : "s"); - - result = NO_ERROR; - - /* - * Check for cruft. We set the "marked" flag on all entries we created - * or decided not to update. If the entry isn't already slated for - * deletion, remove it now. - */ - { - if (bundle->getVerbose()) - printf("Checking for deleted files\n"); - int i, removed = 0; - for (i = 0; i < zip->getNumEntries(); i++) { - ZipEntry* entry = zip->getEntryByIndex(i); - - if (!entry->getMarked() && entry->getDeleted()) { - if (bundle->getVerbose()) { - printf(" (removing crufty '%s')\n", - entry->getFileName()); - } - zip->remove(entry); - removed++; - } - } - if (bundle->getVerbose() && removed > 0) - printf("Removed %d file%s\n", removed, (removed==1) ? "" : "s"); - } - - /* tell Zip lib to process deletions and other pending changes */ - result = zip->flush(); - if (result != NO_ERROR) { - fprintf(stderr, "ERROR: Zip flush failed, archive may be hosed\n"); - goto bail; - } - - /* anything here? */ - if (zip->getNumEntries() == 0) { - if (bundle->getVerbose()) { - printf("Archive is empty -- removing %s\n", outputFile.getPathLeaf().string()); - } - delete zip; // close the file so we can remove it in Win32 - zip = NULL; - if (unlink(outputFile.string()) != 0) { - fprintf(stderr, "warning: could not unlink '%s'\n", outputFile.string()); - } - } - - // If we've been asked to generate a dependency file for the .ap_ package, - // do so here - if (bundle->getGenDependencies()) { - // The dependency file gets output to the same directory - // as the specified output file with an additional .d extension. - // e.g. bin/resources.ap_.d - String8 dependencyFile = outputFile; - dependencyFile.append(".d"); - - FILE* fp = fopen(dependencyFile.string(), "a"); - // Add this file to the dependency file - fprintf(fp, "%s \\\n", outputFile.string()); - fclose(fp); - } - - assert(result == NO_ERROR); - -bail: - delete zip; // must close before remove in Win32 - if (result != NO_ERROR) { - if (bundle->getVerbose()) { - printf("Removing %s due to earlier failures\n", outputFile.string()); - } - if (unlink(outputFile.string()) != 0) { - fprintf(stderr, "warning: could not unlink '%s'\n", outputFile.string()); - } - } - - if (result == NO_ERROR && bundle->getVerbose()) - printf("Done!\n"); - - #if BENCHMARK - fprintf(stdout, "BENCHMARK: End APK Bundling. Time Elapsed: %f ms \n",(clock() - startAPKTime)/1000.0); - #endif /* BENCHMARK */ - return result; -} - -ssize_t processAssets(Bundle* bundle, ZipFile* zip, - const sp<AaptAssets>& assets) -{ - ResourceFilter filter; - status_t status = filter.parse(bundle->getConfigurations()); - if (status != NO_ERROR) { - return -1; - } - - ssize_t count = 0; - - const size_t N = assets->getGroupEntries().size(); - for (size_t i=0; i<N; i++) { - const AaptGroupEntry& ge = assets->getGroupEntries()[i]; - - ssize_t res = processAssets(bundle, zip, assets, ge, &filter); - if (res < 0) { - return res; - } - - count += res; - } - - return count; -} - -ssize_t processAssets(Bundle* bundle, ZipFile* zip, const sp<AaptDir>& dir, - const AaptGroupEntry& ge, const ResourceFilter* filter) -{ - ssize_t count = 0; - - const size_t ND = dir->getDirs().size(); - size_t i; - for (i=0; i<ND; i++) { - const sp<AaptDir>& subDir = dir->getDirs().valueAt(i); - - const bool filterable = filter != NULL && subDir->getLeaf().find("mipmap-") != 0; - - if (filterable && subDir->getLeaf() != subDir->getPath() && !filter->match(ge.toParams())) { - continue; - } - - ssize_t res = processAssets(bundle, zip, subDir, ge, filterable ? filter : NULL); - if (res < 0) { - return res; - } - count += res; - } - - if (filter != NULL && !filter->match(ge.toParams())) { - return count; - } - - const size_t NF = dir->getFiles().size(); - for (i=0; i<NF; i++) { - sp<AaptGroup> gp = dir->getFiles().valueAt(i); - ssize_t fi = gp->getFiles().indexOfKey(ge); - if (fi >= 0) { - sp<AaptFile> fl = gp->getFiles().valueAt(fi); - if (!processFile(bundle, zip, gp, fl)) { - return UNKNOWN_ERROR; - } - count++; - } - } - - return count; -} - -/* - * Process a regular file, adding it to the archive if appropriate. - * - * If we're in "update" mode, and the file already exists in the archive, - * delete the existing entry before adding the new one. - */ -bool processFile(Bundle* bundle, ZipFile* zip, - const sp<AaptGroup>& group, const sp<AaptFile>& file) -{ - const bool hasData = file->hasData(); - - String8 storageName(group->getPath()); - storageName.convertToResPath(); - ZipEntry* entry; - bool fromGzip = false; - status_t result; - - /* - * See if the filename ends in ".EXCLUDE". We can't use - * String8::getPathExtension() because the length of what it considers - * to be an extension is capped. - * - * The Asset Manager doesn't check for ".EXCLUDE" in Zip archives, - * so there's no value in adding them (and it makes life easier on - * the AssetManager lib if we don't). - * - * NOTE: this restriction has been removed. If you're in this code, you - * should clean this up, but I'm in here getting rid of Path Name, and I - * don't want to make other potentially breaking changes --joeo - */ - int fileNameLen = storageName.length(); - int excludeExtensionLen = strlen(kExcludeExtension); - if (fileNameLen > excludeExtensionLen - && (0 == strcmp(storageName.string() + (fileNameLen - excludeExtensionLen), - kExcludeExtension))) { - fprintf(stderr, "warning: '%s' not added to Zip\n", storageName.string()); - return true; - } - - if (strcasecmp(storageName.getPathExtension().string(), ".gz") == 0) { - fromGzip = true; - storageName = storageName.getBasePath(); - } - - if (bundle->getUpdate()) { - entry = zip->getEntryByName(storageName.string()); - if (entry != NULL) { - /* file already exists in archive; there can be only one */ - if (entry->getMarked()) { - fprintf(stderr, - "ERROR: '%s' exists twice (check for with & w/o '.gz'?)\n", - file->getPrintableSource().string()); - return false; - } - if (!hasData) { - const String8& srcName = file->getSourceFile(); - time_t fileModWhen; - fileModWhen = getFileModDate(srcName.string()); - if (fileModWhen == (time_t) -1) { // file existence tested earlier, - return false; // not expecting an error here - } - - if (fileModWhen > entry->getModWhen()) { - // mark as deleted so add() will succeed - if (bundle->getVerbose()) { - printf(" (removing old '%s')\n", storageName.string()); - } - - zip->remove(entry); - } else { - // version in archive is newer - if (bundle->getVerbose()) { - printf(" (not updating '%s')\n", storageName.string()); - } - entry->setMarked(true); - return true; - } - } else { - // Generated files are always replaced. - zip->remove(entry); - } - } - } - - //android_setMinPriority(NULL, ANDROID_LOG_VERBOSE); - - if (fromGzip) { - result = zip->addGzip(file->getSourceFile().string(), storageName.string(), &entry); - } else if (!hasData) { - /* don't compress certain files, e.g. PNGs */ - int compressionMethod = bundle->getCompressionMethod(); - if (!okayToCompress(bundle, storageName)) { - compressionMethod = ZipEntry::kCompressStored; - } - result = zip->add(file->getSourceFile().string(), storageName.string(), compressionMethod, - &entry); - } else { - result = zip->add(file->getData(), file->getSize(), storageName.string(), - file->getCompressionMethod(), &entry); - } - if (result == NO_ERROR) { - if (bundle->getVerbose()) { - printf(" '%s'%s", storageName.string(), fromGzip ? " (from .gz)" : ""); - if (entry->getCompressionMethod() == ZipEntry::kCompressStored) { - printf(" (not compressed)\n"); - } else { - printf(" (compressed %d%%)\n", calcPercent(entry->getUncompressedLen(), - entry->getCompressedLen())); - } - } - entry->setMarked(true); - } else { - if (result == ALREADY_EXISTS) { - fprintf(stderr, " Unable to add '%s': file already in archive (try '-u'?)\n", - file->getPrintableSource().string()); - } else { - fprintf(stderr, " Unable to add '%s': Zip add failed\n", - file->getPrintableSource().string()); - } - return false; - } - - return true; -} - -/* - * Determine whether or not we want to try to compress this file based - * on the file extension. - */ -bool okayToCompress(Bundle* bundle, const String8& pathName) -{ - String8 ext = pathName.getPathExtension(); - int i; - - if (ext.length() == 0) - return true; - - for (i = 0; i < NELEM(kNoCompressExt); i++) { - if (strcasecmp(ext.string(), kNoCompressExt[i]) == 0) - return false; - } - - const android::Vector<const char*>& others(bundle->getNoCompressExtensions()); - for (i = 0; i < (int)others.size(); i++) { - const char* str = others[i]; - int pos = pathName.length() - strlen(str); - if (pos < 0) { - continue; - } - const char* path = pathName.string(); - if (strcasecmp(path + pos, str) == 0) { - return false; - } - } - - return true; -} - -bool endsWith(const char* haystack, const char* needle) -{ - size_t a = strlen(haystack); - size_t b = strlen(needle); - if (a < b) return false; - return strcasecmp(haystack+(a-b), needle) == 0; -} - -ssize_t processJarFile(ZipFile* jar, ZipFile* out) -{ - status_t err; - size_t N = jar->getNumEntries(); - size_t count = 0; - for (size_t i=0; i<N; i++) { - ZipEntry* entry = jar->getEntryByIndex(i); - const char* storageName = entry->getFileName(); - if (endsWith(storageName, ".class")) { - int compressionMethod = entry->getCompressionMethod(); - size_t size = entry->getUncompressedLen(); - const void* data = jar->uncompress(entry); - if (data == NULL) { - fprintf(stderr, "ERROR: unable to uncompress entry '%s'\n", - storageName); - return -1; - } - out->add(data, size, storageName, compressionMethod, NULL); - free((void*)data); - } - count++; - } - return count; -} - -ssize_t processJarFiles(Bundle* bundle, ZipFile* zip) -{ - status_t err; - ssize_t count = 0; - const android::Vector<const char*>& jars = bundle->getJarFiles(); - - size_t N = jars.size(); - for (size_t i=0; i<N; i++) { - ZipFile jar; - err = jar.open(jars[i], ZipFile::kOpenReadOnly); - if (err != 0) { - fprintf(stderr, "ERROR: unable to open '%s' as a zip file: %d\n", - jars[i], err); - return err; - } - err += processJarFile(&jar, zip); - if (err < 0) { - fprintf(stderr, "ERROR: unable to process '%s'\n", jars[i]); - return err; - } - count += err; - } - - return count; -} diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp deleted file mode 100644 index d617928..0000000 --- a/tools/aapt/Resource.cpp +++ /dev/null @@ -1,2676 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// -#include "Main.h" -#include "AaptAssets.h" -#include "StringPool.h" -#include "XMLNode.h" -#include "ResourceTable.h" -#include "Images.h" - -#include "CrunchCache.h" -#include "FileFinder.h" -#include "CacheUpdater.h" - -#include "WorkQueue.h" - -#if HAVE_PRINTF_ZD -# define ZD "%zd" -# define ZD_TYPE ssize_t -#else -# define ZD "%ld" -# define ZD_TYPE long -#endif - -#define NOISY(x) // x - -// Number of threads to use for preprocessing images. -static const size_t MAX_THREADS = 4; - -// ========================================================================== -// ========================================================================== -// ========================================================================== - -class PackageInfo -{ -public: - PackageInfo() - { - } - ~PackageInfo() - { - } - - status_t parsePackage(const sp<AaptGroup>& grp); -}; - -// ========================================================================== -// ========================================================================== -// ========================================================================== - -static String8 parseResourceName(const String8& leaf) -{ - const char* firstDot = strchr(leaf.string(), '.'); - const char* str = leaf.string(); - - if (firstDot) { - return String8(str, firstDot-str); - } else { - return String8(str); - } -} - -ResourceTypeSet::ResourceTypeSet() - :RefBase(), - KeyedVector<String8,sp<AaptGroup> >() -{ -} - -FilePathStore::FilePathStore() - :RefBase(), - Vector<String8>() -{ -} - -class ResourceDirIterator -{ -public: - ResourceDirIterator(const sp<ResourceTypeSet>& set, const String8& resType) - : mResType(resType), mSet(set), mSetPos(0), mGroupPos(0) - { - } - - inline const sp<AaptGroup>& getGroup() const { return mGroup; } - inline const sp<AaptFile>& getFile() const { return mFile; } - - inline const String8& getBaseName() const { return mBaseName; } - inline const String8& getLeafName() const { return mLeafName; } - inline String8 getPath() const { return mPath; } - inline const ResTable_config& getParams() const { return mParams; } - - enum { - EOD = 1 - }; - - ssize_t next() - { - while (true) { - sp<AaptGroup> group; - sp<AaptFile> file; - - // Try to get next file in this current group. - if (mGroup != NULL && mGroupPos < mGroup->getFiles().size()) { - group = mGroup; - file = group->getFiles().valueAt(mGroupPos++); - - // Try to get the next group/file in this directory - } else if (mSetPos < mSet->size()) { - mGroup = group = mSet->valueAt(mSetPos++); - if (group->getFiles().size() < 1) { - continue; - } - file = group->getFiles().valueAt(0); - mGroupPos = 1; - - // All done! - } else { - return EOD; - } - - mFile = file; - - String8 leaf(group->getLeaf()); - mLeafName = String8(leaf); - mParams = file->getGroupEntry().toParams(); - NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d ui=%d density=%d touch=%d key=%d inp=%d nav=%d\n", - group->getPath().string(), mParams.mcc, mParams.mnc, - mParams.language[0] ? mParams.language[0] : '-', - mParams.language[1] ? mParams.language[1] : '-', - mParams.country[0] ? mParams.country[0] : '-', - mParams.country[1] ? mParams.country[1] : '-', - mParams.orientation, mParams.uiMode, - mParams.density, mParams.touchscreen, mParams.keyboard, - mParams.inputFlags, mParams.navigation)); - mPath = "res"; - mPath.appendPath(file->getGroupEntry().toDirName(mResType)); - mPath.appendPath(leaf); - mBaseName = parseResourceName(leaf); - if (mBaseName == "") { - fprintf(stderr, "Error: malformed resource filename %s\n", - file->getPrintableSource().string()); - return UNKNOWN_ERROR; - } - - NOISY(printf("file name=%s\n", mBaseName.string())); - - return NO_ERROR; - } - } - -private: - String8 mResType; - - const sp<ResourceTypeSet> mSet; - size_t mSetPos; - - sp<AaptGroup> mGroup; - size_t mGroupPos; - - sp<AaptFile> mFile; - String8 mBaseName; - String8 mLeafName; - String8 mPath; - ResTable_config mParams; -}; - -// ========================================================================== -// ========================================================================== -// ========================================================================== - -bool isValidResourceType(const String8& type) -{ - return type == "anim" || type == "animator" || type == "interpolator" - || type == "transition" || type == "scene" - || type == "drawable" || type == "layout" - || type == "values" || type == "xml" || type == "raw" - || type == "color" || type == "menu" || type == "mipmap"; -} - -static sp<AaptFile> getResourceFile(const sp<AaptAssets>& assets, bool makeIfNecessary=true) -{ - sp<AaptGroup> group = assets->getFiles().valueFor(String8("resources.arsc")); - sp<AaptFile> file; - if (group != NULL) { - file = group->getFiles().valueFor(AaptGroupEntry()); - if (file != NULL) { - return file; - } - } - - if (!makeIfNecessary) { - return NULL; - } - return assets->addFile(String8("resources.arsc"), AaptGroupEntry(), String8(), - NULL, String8()); -} - -static status_t parsePackage(Bundle* bundle, const sp<AaptAssets>& assets, - const sp<AaptGroup>& grp) -{ - if (grp->getFiles().size() != 1) { - fprintf(stderr, "warning: Multiple AndroidManifest.xml files found, using %s\n", - grp->getFiles().valueAt(0)->getPrintableSource().string()); - } - - sp<AaptFile> file = grp->getFiles().valueAt(0); - - ResXMLTree block; - status_t err = parseXMLResource(file, &block); - if (err != NO_ERROR) { - return err; - } - //printXMLBlock(&block); - - ResXMLTree::event_code_t code; - while ((code=block.next()) != ResXMLTree::START_TAG - && code != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - } - - size_t len; - if (code != ResXMLTree::START_TAG) { - fprintf(stderr, "%s:%d: No start tag found\n", - file->getPrintableSource().string(), block.getLineNumber()); - return UNKNOWN_ERROR; - } - if (strcmp16(block.getElementName(&len), String16("manifest").string()) != 0) { - fprintf(stderr, "%s:%d: Invalid start tag %s, expected <manifest>\n", - file->getPrintableSource().string(), block.getLineNumber(), - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - - ssize_t nameIndex = block.indexOfAttribute(NULL, "package"); - if (nameIndex < 0) { - fprintf(stderr, "%s:%d: <manifest> does not have package attribute.\n", - file->getPrintableSource().string(), block.getLineNumber()); - return UNKNOWN_ERROR; - } - - assets->setPackage(String8(block.getAttributeStringValue(nameIndex, &len))); - - String16 uses_sdk16("uses-sdk"); - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::START_TAG) { - if (strcmp16(block.getElementName(&len), uses_sdk16.string()) == 0) { - ssize_t minSdkIndex = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, - "minSdkVersion"); - if (minSdkIndex >= 0) { - const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len); - const char* minSdk8 = strdup(String8(minSdk16).string()); - bundle->setManifestMinSdkVersion(minSdk8); - } - } - } - } - - return NO_ERROR; -} - -// ========================================================================== -// ========================================================================== -// ========================================================================== - -static status_t makeFileResources(Bundle* bundle, const sp<AaptAssets>& assets, - ResourceTable* table, - const sp<ResourceTypeSet>& set, - const char* resType) -{ - String8 type8(resType); - String16 type16(resType); - - bool hasErrors = false; - - ResourceDirIterator it(set, String8(resType)); - ssize_t res; - while ((res=it.next()) == NO_ERROR) { - if (bundle->getVerbose()) { - printf(" (new resource id %s from %s)\n", - it.getBaseName().string(), it.getFile()->getPrintableSource().string()); - } - String16 baseName(it.getBaseName()); - const char16_t* str = baseName.string(); - const char16_t* const end = str + baseName.size(); - while (str < end) { - if (!((*str >= 'a' && *str <= 'z') - || (*str >= '0' && *str <= '9') - || *str == '_' || *str == '.')) { - fprintf(stderr, "%s: Invalid file name: must contain only [a-z0-9_.]\n", - it.getPath().string()); - hasErrors = true; - } - str++; - } - String8 resPath = it.getPath(); - resPath.convertToResPath(); - table->addEntry(SourcePos(it.getPath(), 0), String16(assets->getPackage()), - type16, - baseName, - String16(resPath), - NULL, - &it.getParams()); - assets->addResource(it.getLeafName(), resPath, it.getFile(), type8); - } - - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -class PreProcessImageWorkUnit : public WorkQueue::WorkUnit { -public: - PreProcessImageWorkUnit(const Bundle* bundle, const sp<AaptAssets>& assets, - const sp<AaptFile>& file, volatile bool* hasErrors) : - mBundle(bundle), mAssets(assets), mFile(file), mHasErrors(hasErrors) { - } - - virtual bool run() { - status_t status = preProcessImage(mBundle, mAssets, mFile, NULL); - if (status) { - *mHasErrors = true; - } - return true; // continue even if there are errors - } - -private: - const Bundle* mBundle; - sp<AaptAssets> mAssets; - sp<AaptFile> mFile; - volatile bool* mHasErrors; -}; - -static status_t preProcessImages(const Bundle* bundle, const sp<AaptAssets>& assets, - const sp<ResourceTypeSet>& set, const char* type) -{ - volatile bool hasErrors = false; - ssize_t res = NO_ERROR; - if (bundle->getUseCrunchCache() == false) { - WorkQueue wq(MAX_THREADS, false); - ResourceDirIterator it(set, String8(type)); - while ((res=it.next()) == NO_ERROR) { - PreProcessImageWorkUnit* w = new PreProcessImageWorkUnit( - bundle, assets, it.getFile(), &hasErrors); - status_t status = wq.schedule(w); - if (status) { - fprintf(stderr, "preProcessImages failed: schedule() returned %d\n", status); - hasErrors = true; - delete w; - break; - } - } - status_t status = wq.finish(); - if (status) { - fprintf(stderr, "preProcessImages failed: finish() returned %d\n", status); - hasErrors = true; - } - } - return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR; -} - -status_t postProcessImages(const sp<AaptAssets>& assets, - ResourceTable* table, - const sp<ResourceTypeSet>& set) -{ - ResourceDirIterator it(set, String8("drawable")); - bool hasErrors = false; - ssize_t res; - while ((res=it.next()) == NO_ERROR) { - res = postProcessImage(assets, table, it.getFile()); - if (res < NO_ERROR) { - hasErrors = true; - } - } - - return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR; -} - -static void collect_files(const sp<AaptDir>& dir, - KeyedVector<String8, sp<ResourceTypeSet> >* resources) -{ - const DefaultKeyedVector<String8, sp<AaptGroup> >& groups = dir->getFiles(); - int N = groups.size(); - for (int i=0; i<N; i++) { - String8 leafName = groups.keyAt(i); - const sp<AaptGroup>& group = groups.valueAt(i); - - const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files - = group->getFiles(); - - if (files.size() == 0) { - continue; - } - - String8 resType = files.valueAt(0)->getResourceType(); - - ssize_t index = resources->indexOfKey(resType); - - if (index < 0) { - sp<ResourceTypeSet> set = new ResourceTypeSet(); - NOISY(printf("Creating new resource type set for leaf %s with group %s (%p)\n", - leafName.string(), group->getPath().string(), group.get())); - set->add(leafName, group); - resources->add(resType, set); - } else { - sp<ResourceTypeSet> set = resources->valueAt(index); - index = set->indexOfKey(leafName); - if (index < 0) { - NOISY(printf("Adding to resource type set for leaf %s group %s (%p)\n", - leafName.string(), group->getPath().string(), group.get())); - set->add(leafName, group); - } else { - sp<AaptGroup> existingGroup = set->valueAt(index); - NOISY(printf("Extending to resource type set for leaf %s group %s (%p)\n", - leafName.string(), group->getPath().string(), group.get())); - for (size_t j=0; j<files.size(); j++) { - NOISY(printf("Adding file %s in group %s resType %s\n", - files.valueAt(j)->getSourceFile().string(), - files.keyAt(j).toDirName(String8()).string(), - resType.string())); - status_t err = existingGroup->addFile(files.valueAt(j)); - } - } - } - } -} - -static void collect_files(const sp<AaptAssets>& ass, - KeyedVector<String8, sp<ResourceTypeSet> >* resources) -{ - const Vector<sp<AaptDir> >& dirs = ass->resDirs(); - int N = dirs.size(); - - for (int i=0; i<N; i++) { - sp<AaptDir> d = dirs.itemAt(i); - NOISY(printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(), - d->getLeaf().string())); - collect_files(d, resources); - - // don't try to include the res dir - NOISY(printf("Removing dir leaf %s\n", d->getLeaf().string())); - ass->removeDir(d->getLeaf()); - } -} - -enum { - ATTR_OKAY = -1, - ATTR_NOT_FOUND = -2, - ATTR_LEADING_SPACES = -3, - ATTR_TRAILING_SPACES = -4 -}; -static int validateAttr(const String8& path, const ResTable& table, - const ResXMLParser& parser, - const char* ns, const char* attr, const char* validChars, bool required) -{ - size_t len; - - ssize_t index = parser.indexOfAttribute(ns, attr); - const uint16_t* str; - Res_value value; - if (index >= 0 && parser.getAttributeValue(index, &value) >= 0) { - const ResStringPool* pool = &parser.getStrings(); - if (value.dataType == Res_value::TYPE_REFERENCE) { - uint32_t specFlags = 0; - int strIdx; - if ((strIdx=table.resolveReference(&value, 0x10000000, NULL, &specFlags)) < 0) { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s references unknown resid 0x%08x.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr, - value.data); - return ATTR_NOT_FOUND; - } - - pool = table.getTableStringBlock(strIdx); - #if 0 - if (pool != NULL) { - str = pool->stringAt(value.data, &len); - } - printf("***** RES ATTR: %s specFlags=0x%x strIdx=%d: %s\n", attr, - specFlags, strIdx, str != NULL ? String8(str).string() : "???"); - #endif - if ((specFlags&~ResTable_typeSpec::SPEC_PUBLIC) != 0 && false) { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s varies by configurations 0x%x.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr, - specFlags); - return ATTR_NOT_FOUND; - } - } - if (value.dataType == Res_value::TYPE_STRING) { - if (pool == NULL) { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s has no string block.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr); - return ATTR_NOT_FOUND; - } - if ((str=pool->stringAt(value.data, &len)) == NULL) { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s has corrupt string value.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr); - return ATTR_NOT_FOUND; - } - } else { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s has invalid type %d.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr, - value.dataType); - return ATTR_NOT_FOUND; - } - if (validChars) { - for (size_t i=0; i<len; i++) { - uint16_t c = str[i]; - const char* p = validChars; - bool okay = false; - while (*p) { - if (c == *p) { - okay = true; - break; - } - p++; - } - if (!okay) { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s has invalid character '%c'.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr, (char)str[i]); - return (int)i; - } - } - } - if (*str == ' ') { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s can not start with a space.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr); - return ATTR_LEADING_SPACES; - } - if (str[len-1] == ' ') { - fprintf(stderr, "%s:%d: Tag <%s> attribute %s can not end with a space.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr); - return ATTR_TRAILING_SPACES; - } - return ATTR_OKAY; - } - if (required) { - fprintf(stderr, "%s:%d: Tag <%s> missing required attribute %s.\n", - path.string(), parser.getLineNumber(), - String8(parser.getElementName(&len)).string(), attr); - return ATTR_NOT_FOUND; - } - return ATTR_OKAY; -} - -static void checkForIds(const String8& path, ResXMLParser& parser) -{ - ResXMLTree::event_code_t code; - while ((code=parser.next()) != ResXMLTree::END_DOCUMENT - && code > ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::START_TAG) { - ssize_t index = parser.indexOfAttribute(NULL, "id"); - if (index >= 0) { - fprintf(stderr, "%s:%d: warning: found plain 'id' attribute; did you mean the new 'android:id' name?\n", - path.string(), parser.getLineNumber()); - } - } - } -} - -static bool applyFileOverlay(Bundle *bundle, - const sp<AaptAssets>& assets, - sp<ResourceTypeSet> *baseSet, - const char *resType) -{ - if (bundle->getVerbose()) { - printf("applyFileOverlay for %s\n", resType); - } - - // Replace any base level files in this category with any found from the overlay - // 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(); - - // get the overlay resources of the requested type - ssize_t index = overlayRes->indexOfKey(resTypeString); - if (index >= 0) { - sp<ResourceTypeSet> overlaySet = overlayRes->valueAt(index); - - // for each of the resources, check for a match in the previously built - // non-overlay "baseset". - size_t overlayCount = overlaySet->size(); - for (size_t overlayIndex=0; overlayIndex<overlayCount; overlayIndex++) { - if (bundle->getVerbose()) { - printf("trying overlaySet Key=%s\n",overlaySet->keyAt(overlayIndex).string()); - } - size_t baseIndex = UNKNOWN_ERROR; - if (baseSet->get() != NULL) { - baseIndex = (*baseSet)->indexOfKey(overlaySet->keyAt(overlayIndex)); - } - 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. - sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex); - sp<AaptGroup> baseGroup = (*baseSet)->valueAt(baseIndex); - - DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles = - overlayGroup->getFiles(); - if (bundle->getVerbose()) { - DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles = - baseGroup->getFiles(); - for (size_t i=0; i < baseFiles.size(); i++) { - printf("baseFile " ZD " has flavor %s\n", (ZD_TYPE) i, - baseFiles.keyAt(i).toString().string()); - } - for (size_t i=0; i < overlayFiles.size(); i++) { - printf("overlayFile " ZD " has flavor %s\n", (ZD_TYPE) i, - overlayFiles.keyAt(i).toString().string()); - } - } - - size_t overlayGroupSize = overlayFiles.size(); - for (size_t overlayGroupIndex = 0; - overlayGroupIndex<overlayGroupSize; - overlayGroupIndex++) { - size_t baseFileIndex = - baseGroup->getFiles().indexOfKey(overlayFiles. - keyAt(overlayGroupIndex)); - if (baseFileIndex < UNKNOWN_ERROR) { - if (bundle->getVerbose()) { - printf("found a match (" ZD ") for overlay file %s, for flavor %s\n", - (ZD_TYPE) baseFileIndex, - overlayGroup->getLeaf().string(), - overlayFiles.keyAt(overlayGroupIndex).toString().string()); - } - baseGroup->removeFile(baseFileIndex); - } else { - // didn't find a match fall through and add it.. - if (true || bundle->getVerbose()) { - printf("nothing matches overlay file %s, for flavor %s\n", - overlayGroup->getLeaf().string(), - overlayFiles.keyAt(overlayGroupIndex).toString().string()); - } - } - baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex)); - assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex)); - } - } else { - if (baseSet->get() == NULL) { - *baseSet = new ResourceTypeSet(); - assets->getResources()->add(String8(resType), *baseSet); - } - // this group doesn't exist (a file that's only in the overlay) - (*baseSet)->add(overlaySet->keyAt(overlayIndex), - overlaySet->valueAt(overlayIndex)); - // make sure all flavors are defined in the resources. - sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex); - DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles = - overlayGroup->getFiles(); - size_t overlayGroupSize = overlayFiles.size(); - for (size_t overlayGroupIndex = 0; - overlayGroupIndex<overlayGroupSize; - overlayGroupIndex++) { - assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex)); - } - } - } - // this overlay didn't have resources for this type - } - // try next overlay - overlay = overlay->getOverlay(); - } - return true; -} - -/* - * Inserts an attribute in a given node, only if the attribute does not - * exist. - * If errorOnFailedInsert is true, and the attribute already exists, returns false. - * Returns true otherwise, even if the attribute already exists. - */ -bool addTagAttribute(const sp<XMLNode>& node, const char* ns8, - const char* attr8, const char* value, bool errorOnFailedInsert) -{ - if (value == NULL) { - return true; - } - - const String16 ns(ns8); - const String16 attr(attr8); - - if (node->getAttribute(ns, attr) != NULL) { - if (errorOnFailedInsert) { - fprintf(stderr, "Error: AndroidManifest.xml already defines %s (in %s);" - " cannot insert new value %s.\n", - String8(attr).string(), String8(ns).string(), value); - return false; - } - - fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s);" - " using existing value in manifest.\n", - String8(attr).string(), String8(ns).string()); - - // don't stop the build. - return true; - } - - node->addAttribute(ns, attr, String16(value)); - return true; -} - -static void fullyQualifyClassName(const String8& package, sp<XMLNode> node, - const String16& attrName) { - XMLNode::attribute_entry* attr = node->editAttribute( - String16("http://schemas.android.com/apk/res/android"), attrName); - if (attr != NULL) { - String8 name(attr->string); - - // asdf --> package.asdf - // .asdf .a.b --> package.asdf package.a.b - // asdf.adsf --> asdf.asdf - String8 className; - const char* p = name.string(); - const char* q = strchr(p, '.'); - if (p == q) { - className += package; - className += name; - } else if (q == NULL) { - className += package; - className += "."; - className += name; - } else { - className += name; - } - NOISY(printf("Qualifying class '%s' to '%s'", name.string(), className.string())); - attr->string.setTo(String16(className)); - } -} - -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; - } - - bool errorOnFailedInsert = bundle->getErrorOnFailedInsert(); - - if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode", - bundle->getVersionCode(), errorOnFailedInsert)) { - return UNKNOWN_ERROR; - } - if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName", - bundle->getVersionName(), errorOnFailedInsert)) { - return UNKNOWN_ERROR; - } - - 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); - } - - if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion", - bundle->getMinSdkVersion(), errorOnFailedInsert)) { - return UNKNOWN_ERROR; - } - if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion", - bundle->getTargetSdkVersion(), errorOnFailedInsert)) { - return UNKNOWN_ERROR; - } - if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion", - bundle->getMaxSdkVersion(), errorOnFailedInsert)) { - return UNKNOWN_ERROR; - } - } - - if (bundle->getDebugMode()) { - sp<XMLNode> application = root->getChildElement(String16(), String16("application")); - if (application != NULL) { - if (!addTagAttribute(application, RESOURCES_ANDROID_NAMESPACE, "debuggable", "true", - errorOnFailedInsert)) { - return UNKNOWN_ERROR; - } - } - } - - // Deal with manifest package name overrides - const char* manifestPackageNameOverride = bundle->getManifestPackageNameOverride(); - if (manifestPackageNameOverride != NULL) { - // Update the actual package name - XMLNode::attribute_entry* attr = root->editAttribute(String16(), String16("package")); - if (attr == NULL) { - fprintf(stderr, "package name is required with --rename-manifest-package.\n"); - return UNKNOWN_ERROR; - } - String8 origPackage(attr->string); - attr->string.setTo(String16(manifestPackageNameOverride)); - NOISY(printf("Overriding package '%s' to be '%s'\n", origPackage.string(), manifestPackageNameOverride)); - - // Make class names fully qualified - sp<XMLNode> application = root->getChildElement(String16(), String16("application")); - if (application != NULL) { - fullyQualifyClassName(origPackage, application, String16("name")); - fullyQualifyClassName(origPackage, application, String16("backupAgent")); - - Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(application->getChildren()); - for (size_t i = 0; i < children.size(); i++) { - sp<XMLNode> child = children.editItemAt(i); - String8 tag(child->getElementName()); - if (tag == "activity" || tag == "service" || tag == "receiver" || tag == "provider") { - fullyQualifyClassName(origPackage, child, String16("name")); - } else if (tag == "activity-alias") { - fullyQualifyClassName(origPackage, child, String16("name")); - fullyQualifyClassName(origPackage, child, String16("targetActivity")); - } - } - } - } - - // Deal with manifest package name overrides - const char* instrumentationPackageNameOverride = bundle->getInstrumentationPackageNameOverride(); - if (instrumentationPackageNameOverride != NULL) { - // Fix up instrumentation targets. - Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(root->getChildren()); - for (size_t i = 0; i < children.size(); i++) { - sp<XMLNode> child = children.editItemAt(i); - String8 tag(child->getElementName()); - if (tag == "instrumentation") { - XMLNode::attribute_entry* attr = child->editAttribute( - String16("http://schemas.android.com/apk/res/android"), String16("targetPackage")); - if (attr != NULL) { - attr->string.setTo(String16(instrumentationPackageNameOverride)); - } - } - } - } - - return NO_ERROR; -} - -#define ASSIGN_IT(n) \ - do { \ - ssize_t index = resources->indexOfKey(String8(#n)); \ - if (index >= 0) { \ - n ## s = resources->valueAt(index); \ - } \ - } while (0) - -status_t updatePreProcessedCache(Bundle* bundle) -{ - #if BENCHMARK - fprintf(stdout, "BENCHMARK: Starting PNG PreProcessing \n"); - long startPNGTime = clock(); - #endif /* BENCHMARK */ - - String8 source(bundle->getResourceSourceDirs()[0]); - String8 dest(bundle->getCrunchedOutputDir()); - - FileFinder* ff = new SystemFileFinder(); - CrunchCache cc(source,dest,ff); - - CacheUpdater* cu = new SystemCacheUpdater(bundle); - size_t numFiles = cc.crunch(cu); - - if (bundle->getVerbose()) - fprintf(stdout, "Crunched %d PNG files to update cache\n", (int)numFiles); - - delete ff; - delete cu; - - #if BENCHMARK - fprintf(stdout, "BENCHMARK: End PNG PreProcessing. Time Elapsed: %f ms \n" - ,(clock() - startPNGTime)/1000.0); - #endif /* BENCHMARK */ - return 0; -} - -status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) -{ - // First, look for a package file to parse. This is required to - // be able to generate the resource information. - sp<AaptGroup> androidManifestFile = - assets->getFiles().valueFor(String8("AndroidManifest.xml")); - if (androidManifestFile == NULL) { - fprintf(stderr, "ERROR: No AndroidManifest.xml file found.\n"); - return UNKNOWN_ERROR; - } - - status_t err = parsePackage(bundle, assets, androidManifestFile); - if (err != NO_ERROR) { - return err; - } - - NOISY(printf("Creating resources for package %s\n", - assets->getPackage().string())); - - ResourceTable table(bundle, String16(assets->getPackage())); - err = table.addIncludedResources(bundle, assets); - if (err != NO_ERROR) { - return err; - } - - NOISY(printf("Found %d included resource packages\n", (int)table.size())); - - // Standard flags for compiled XML and optional UTF-8 encoding - int xmlFlags = XML_COMPILE_STANDARD_RESOURCE; - - /* Only enable UTF-8 if the caller of aapt didn't specifically - * request UTF-16 encoding and the parameters of this package - * allow UTF-8 to be used. - */ - if (!bundle->getUTF16StringsOption()) { - xmlFlags |= XML_COMPILE_UTF8; - } - - // -------------------------------------------------------------- - // First, gather all resource information. - // -------------------------------------------------------------- - - // resType -> leafName -> group - KeyedVector<String8, sp<ResourceTypeSet> > *resources = - new KeyedVector<String8, sp<ResourceTypeSet> >; - collect_files(assets, resources); - - sp<ResourceTypeSet> drawables; - sp<ResourceTypeSet> layouts; - sp<ResourceTypeSet> anims; - sp<ResourceTypeSet> animators; - sp<ResourceTypeSet> interpolators; - sp<ResourceTypeSet> transitions; - sp<ResourceTypeSet> scenes; - sp<ResourceTypeSet> xmls; - sp<ResourceTypeSet> raws; - sp<ResourceTypeSet> colors; - sp<ResourceTypeSet> menus; - sp<ResourceTypeSet> mipmaps; - - ASSIGN_IT(drawable); - ASSIGN_IT(layout); - ASSIGN_IT(anim); - ASSIGN_IT(animator); - ASSIGN_IT(interpolator); - ASSIGN_IT(transition); - ASSIGN_IT(scene); - ASSIGN_IT(xml); - ASSIGN_IT(raw); - ASSIGN_IT(color); - ASSIGN_IT(menu); - ASSIGN_IT(mipmap); - - assets->setResources(resources); - // now go through any resource overlays and collect their files - sp<AaptAssets> current = assets->getOverlay(); - while(current.get()) { - KeyedVector<String8, sp<ResourceTypeSet> > *resources = - new KeyedVector<String8, sp<ResourceTypeSet> >; - current->setResources(resources); - collect_files(current, resources); - current = current->getOverlay(); - } - // apply the overlay files to the base set - if (!applyFileOverlay(bundle, assets, &drawables, "drawable") || - !applyFileOverlay(bundle, assets, &layouts, "layout") || - !applyFileOverlay(bundle, assets, &anims, "anim") || - !applyFileOverlay(bundle, assets, &animators, "animator") || - !applyFileOverlay(bundle, assets, &interpolators, "interpolator") || - !applyFileOverlay(bundle, assets, &transitions, "transition") || - !applyFileOverlay(bundle, assets, &scenes, "scene") || - !applyFileOverlay(bundle, assets, &xmls, "xml") || - !applyFileOverlay(bundle, assets, &raws, "raw") || - !applyFileOverlay(bundle, assets, &colors, "color") || - !applyFileOverlay(bundle, assets, &menus, "menu") || - !applyFileOverlay(bundle, assets, &mipmaps, "mipmap")) { - return UNKNOWN_ERROR; - } - - bool hasErrors = false; - - if (drawables != NULL) { - if (bundle->getOutputAPKFile() != NULL) { - err = preProcessImages(bundle, assets, drawables, "drawable"); - } - if (err == NO_ERROR) { - err = makeFileResources(bundle, assets, &table, drawables, "drawable"); - if (err != NO_ERROR) { - hasErrors = true; - } - } else { - hasErrors = true; - } - } - - if (mipmaps != NULL) { - if (bundle->getOutputAPKFile() != NULL) { - err = preProcessImages(bundle, assets, mipmaps, "mipmap"); - } - if (err == NO_ERROR) { - err = makeFileResources(bundle, assets, &table, mipmaps, "mipmap"); - if (err != NO_ERROR) { - hasErrors = true; - } - } else { - hasErrors = true; - } - } - - if (layouts != NULL) { - err = makeFileResources(bundle, assets, &table, layouts, "layout"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (anims != NULL) { - err = makeFileResources(bundle, assets, &table, anims, "anim"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (animators != NULL) { - err = makeFileResources(bundle, assets, &table, animators, "animator"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (transitions != NULL) { - err = makeFileResources(bundle, assets, &table, transitions, "transition"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (scenes != NULL) { - err = makeFileResources(bundle, assets, &table, scenes, "scene"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (interpolators != NULL) { - err = makeFileResources(bundle, assets, &table, interpolators, "interpolator"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (xmls != NULL) { - err = makeFileResources(bundle, assets, &table, xmls, "xml"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (raws != NULL) { - err = makeFileResources(bundle, assets, &table, raws, "raw"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - // compile resources - current = assets; - while(current.get()) { - KeyedVector<String8, sp<ResourceTypeSet> > *resources = - current->getResources(); - - ssize_t index = resources->indexOfKey(String8("values")); - if (index >= 0) { - ResourceDirIterator it(resources->valueAt(index), String8("values")); - ssize_t res; - while ((res=it.next()) == NO_ERROR) { - sp<AaptFile> file = it.getFile(); - res = compileResourceFile(bundle, assets, file, it.getParams(), - (current!=assets), &table); - if (res != NO_ERROR) { - hasErrors = true; - } - } - } - current = current->getOverlay(); - } - - if (colors != NULL) { - err = makeFileResources(bundle, assets, &table, colors, "color"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (menus != NULL) { - err = makeFileResources(bundle, assets, &table, menus, "menu"); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - // -------------------------------------------------------------------- - // Assignment of resource IDs and initial generation of resource table. - // -------------------------------------------------------------------- - - if (table.hasResources()) { - sp<AaptFile> resFile(getResourceFile(assets)); - if (resFile == NULL) { - fprintf(stderr, "Error: unable to generate entry for resource data\n"); - return UNKNOWN_ERROR; - } - - err = table.assignResourceIds(); - if (err < NO_ERROR) { - return err; - } - } - - // -------------------------------------------------------------- - // Finally, we can now we can compile XML files, which may reference - // resources. - // -------------------------------------------------------------- - - if (layouts != NULL) { - ResourceDirIterator it(layouts, String8("layout")); - while ((err=it.next()) == NO_ERROR) { - String8 src = it.getFile()->getPrintableSource(); - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err == NO_ERROR) { - ResXMLTree block; - block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true); - checkForIds(src, block); - } else { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (anims != NULL) { - ResourceDirIterator it(anims, String8("anim")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (animators != NULL) { - ResourceDirIterator it(animators, String8("animator")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (interpolators != NULL) { - ResourceDirIterator it(interpolators, String8("interpolator")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (transitions != NULL) { - ResourceDirIterator it(transitions, String8("transition")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (scenes != NULL) { - ResourceDirIterator it(scenes, String8("scene")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (xmls != NULL) { - ResourceDirIterator it(xmls, String8("xml")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (drawables != NULL) { - err = postProcessImages(assets, &table, drawables); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (colors != NULL) { - ResourceDirIterator it(colors, String8("color")); - while ((err=it.next()) == NO_ERROR) { - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (menus != NULL) { - ResourceDirIterator it(menus, String8("menu")); - while ((err=it.next()) == NO_ERROR) { - String8 src = it.getFile()->getPrintableSource(); - err = compileXmlFile(assets, it.getFile(), &table, xmlFlags); - if (err != NO_ERROR) { - hasErrors = true; - } - ResXMLTree block; - block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true); - checkForIds(src, block); - } - - if (err < NO_ERROR) { - hasErrors = true; - } - err = NO_ERROR; - } - - if (table.validateLocalizations()) { - hasErrors = true; - } - - if (hasErrors) { - return UNKNOWN_ERROR; - } - - const sp<AaptFile> manifestFile(androidManifestFile->getFiles().valueAt(0)); - String8 manifestPath(manifestFile->getPrintableSource()); - - // Generate final compiled manifest file. - manifestFile->clearData(); - 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; - } - - //block.restart(); - //printXMLBlock(&block); - - // -------------------------------------------------------------- - // Generate the final resource table. - // Re-flatten because we may have added new resource IDs - // -------------------------------------------------------------- - - ResTable finalResTable; - sp<AaptFile> resFile; - - if (table.hasResources()) { - sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); - err = table.addSymbols(symbols); - if (err < NO_ERROR) { - return err; - } - - resFile = getResourceFile(assets); - if (resFile == NULL) { - fprintf(stderr, "Error: unable to generate entry for resource data\n"); - return UNKNOWN_ERROR; - } - - err = table.flatten(bundle, resFile); - if (err < NO_ERROR) { - return err; - } - - if (bundle->getPublicOutputFile()) { - FILE* fp = fopen(bundle->getPublicOutputFile(), "w+"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Unable to open public definitions output file %s: %s\n", - (const char*)bundle->getPublicOutputFile(), strerror(errno)); - return UNKNOWN_ERROR; - } - if (bundle->getVerbose()) { - printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile()); - } - table.writePublicDefinitions(String16(assets->getPackage()), fp); - fclose(fp); - } - - // Read resources back in, - finalResTable.add(resFile->getData(), resFile->getSize(), NULL); - -#if 0 - NOISY( - printf("Generated resources:\n"); - finalResTable.print(); - ) -#endif - } - - // Perform a basic validation of the manifest file. This time we - // parse it with the comments intact, so that we can use them to - // generate java docs... so we are not going to write this one - // back out to the final manifest data. - sp<AaptFile> outManifestFile = new AaptFile(manifestFile->getSourceFile(), - manifestFile->getGroupEntry(), - manifestFile->getResourceType()); - err = compileXmlFile(assets, manifestFile, - outManifestFile, &table, - XML_COMPILE_ASSIGN_ATTRIBUTE_IDS - | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES); - if (err < NO_ERROR) { - return err; - } - ResXMLTree block; - block.setTo(outManifestFile->getData(), outManifestFile->getSize(), true); - String16 manifest16("manifest"); - String16 permission16("permission"); - String16 permission_group16("permission-group"); - String16 uses_permission16("uses-permission"); - String16 instrumentation16("instrumentation"); - String16 application16("application"); - String16 provider16("provider"); - String16 service16("service"); - String16 receiver16("receiver"); - String16 activity16("activity"); - String16 action16("action"); - String16 category16("category"); - String16 data16("scheme"); - const char* packageIdentChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789"; - const char* packageIdentCharsWithTheStupid = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789-"; - const char* classIdentChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789$"; - const char* processIdentChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789:"; - const char* authoritiesIdentChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789-:;"; - const char* typeIdentChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789:-/*+"; - const char* schemeIdentChars = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789-"; - ResXMLTree::event_code_t code; - sp<AaptSymbols> permissionSymbols; - sp<AaptSymbols> permissionGroupSymbols; - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code > ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::START_TAG) { - size_t len; - if (block.getElementNamespace(&len) != NULL) { - continue; - } - if (strcmp16(block.getElementName(&len), manifest16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, NULL, "package", - packageIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "sharedUserId", packageIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), permission16.string()) == 0 - || strcmp16(block.getElementName(&len), permission_group16.string()) == 0) { - const bool isGroup = strcmp16(block.getElementName(&len), - permission_group16.string()) == 0; - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "name", isGroup ? packageIdentCharsWithTheStupid - : packageIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - SourcePos srcPos(manifestPath, block.getLineNumber()); - sp<AaptSymbols> syms; - if (!isGroup) { - syms = permissionSymbols; - if (syms == NULL) { - sp<AaptSymbols> symbols = - assets->getSymbolsFor(String8("Manifest")); - syms = permissionSymbols = symbols->addNestedSymbol( - String8("permission"), srcPos); - } - } else { - syms = permissionGroupSymbols; - if (syms == NULL) { - sp<AaptSymbols> symbols = - assets->getSymbolsFor(String8("Manifest")); - syms = permissionGroupSymbols = symbols->addNestedSymbol( - String8("permission_group"), srcPos); - } - } - size_t len; - ssize_t index = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, "name"); - const uint16_t* id = block.getAttributeStringValue(index, &len); - if (id == NULL) { - fprintf(stderr, "%s:%d: missing name attribute in element <%s>.\n", - manifestPath.string(), block.getLineNumber(), - String8(block.getElementName(&len)).string()); - hasErrors = true; - break; - } - String8 idStr(id); - char* p = idStr.lockBuffer(idStr.size()); - char* e = p + idStr.size(); - bool begins_with_digit = true; // init to true so an empty string fails - while (e > p) { - e--; - if (*e >= '0' && *e <= '9') { - begins_with_digit = true; - continue; - } - if ((*e >= 'a' && *e <= 'z') || - (*e >= 'A' && *e <= 'Z') || - (*e == '_')) { - begins_with_digit = false; - continue; - } - if (isGroup && (*e == '-')) { - *e = '_'; - begins_with_digit = false; - continue; - } - e++; - break; - } - idStr.unlockBuffer(); - // verify that we stopped because we hit a period or - // the beginning of the string, and that the - // identifier didn't begin with a digit. - if (begins_with_digit || (e != p && *(e-1) != '.')) { - fprintf(stderr, - "%s:%d: Permission name <%s> is not a valid Java symbol\n", - manifestPath.string(), block.getLineNumber(), idStr.string()); - hasErrors = true; - } - syms->addStringSymbol(String8(e), idStr, srcPos); - const uint16_t* cmt = block.getComment(&len); - if (cmt != NULL && *cmt != 0) { - //printf("Comment of %s: %s\n", String8(e).string(), - // String8(cmt).string()); - syms->appendComment(String8(e), String16(cmt), srcPos); - } else { - //printf("No comment for %s\n", String8(e).string()); - } - syms->makeSymbolPublic(String8(e), srcPos); - } else if (strcmp16(block.getElementName(&len), uses_permission16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "name", packageIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), instrumentation16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "name", classIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "targetPackage", - packageIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), application16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "name", classIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "permission", - packageIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "process", - processIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "taskAffinity", - processIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), provider16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "name", classIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "authorities", - authoritiesIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "permission", - packageIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "process", - processIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), service16.string()) == 0 - || strcmp16(block.getElementName(&len), receiver16.string()) == 0 - || strcmp16(block.getElementName(&len), activity16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, - "name", classIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "permission", - packageIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "process", - processIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "taskAffinity", - processIdentChars, false) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), action16.string()) == 0 - || strcmp16(block.getElementName(&len), category16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "name", - packageIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), data16.string()) == 0) { - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "mimeType", - typeIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - if (validateAttr(manifestPath, finalResTable, block, - RESOURCES_ANDROID_NAMESPACE, "scheme", - schemeIdentChars, true) != ATTR_OKAY) { - hasErrors = true; - } - } - } - } - - if (resFile != NULL) { - // These resources are now considered to be a part of the included - // resources, for others to reference. - err = assets->addIncludedResources(resFile); - if (err < NO_ERROR) { - fprintf(stderr, "ERROR: Unable to parse generated resources, aborting.\n"); - return err; - } - } - - return err; -} - -static const char* getIndentSpace(int indent) -{ -static const char whitespace[] = -" "; - - return whitespace + sizeof(whitespace) - 1 - indent*4; -} - -static String8 flattenSymbol(const String8& symbol) { - String8 result(symbol); - ssize_t first; - if ((first = symbol.find(":", 0)) >= 0 - || (first = symbol.find(".", 0)) >= 0) { - size_t size = symbol.size(); - char* buf = result.lockBuffer(size); - for (size_t i = first; i < size; i++) { - if (buf[i] == ':' || buf[i] == '.') { - buf[i] = '_'; - } - } - result.unlockBuffer(size); - } - return result; -} - -static String8 getSymbolPackage(const String8& symbol, const sp<AaptAssets>& assets, bool pub) { - ssize_t colon = symbol.find(":", 0); - if (colon >= 0) { - return String8(symbol.string(), colon); - } - return pub ? assets->getPackage() : assets->getSymbolsPrivatePackage(); -} - -static String8 getSymbolName(const String8& symbol) { - ssize_t colon = symbol.find(":", 0); - if (colon >= 0) { - return String8(symbol.string() + colon + 1); - } - return symbol; -} - -static String16 getAttributeComment(const sp<AaptAssets>& assets, - const String8& name, - String16* outTypeComment = NULL) -{ - sp<AaptSymbols> asym = assets->getSymbolsFor(String8("R")); - if (asym != NULL) { - //printf("Got R symbols!\n"); - asym = asym->getNestedSymbols().valueFor(String8("attr")); - if (asym != NULL) { - //printf("Got attrs symbols! comment %s=%s\n", - // name.string(), String8(asym->getComment(name)).string()); - if (outTypeComment != NULL) { - *outTypeComment = asym->getTypeComment(name); - } - return asym->getComment(name); - } - } - return String16(); -} - -static status_t writeLayoutClasses( - FILE* fp, const sp<AaptAssets>& assets, - const sp<AaptSymbols>& symbols, int indent, bool includePrivate) -{ - const char* indentStr = getIndentSpace(indent); - if (!includePrivate) { - fprintf(fp, "%s/** @doconly */\n", indentStr); - } - fprintf(fp, "%spublic static final class styleable {\n", indentStr); - indent++; - - String16 attr16("attr"); - String16 package16(assets->getPackage()); - - indentStr = getIndentSpace(indent); - bool hasErrors = false; - - size_t i; - size_t N = symbols->getNestedSymbols().size(); - for (i=0; i<N; i++) { - sp<AaptSymbols> nsymbols = symbols->getNestedSymbols().valueAt(i); - String8 realClassName(symbols->getNestedSymbols().keyAt(i)); - String8 nclassName(flattenSymbol(realClassName)); - - SortedVector<uint32_t> idents; - Vector<uint32_t> origOrder; - Vector<bool> publicFlags; - - size_t a; - size_t NA = nsymbols->getSymbols().size(); - for (a=0; a<NA; a++) { - const AaptSymbolEntry& sym(nsymbols->getSymbols().valueAt(a)); - int32_t code = sym.typeCode == AaptSymbolEntry::TYPE_INT32 - ? sym.int32Val : 0; - bool isPublic = true; - if (code == 0) { - String16 name16(sym.name); - uint32_t typeSpecFlags; - code = assets->getIncludedResources().identifierForName( - name16.string(), name16.size(), - attr16.string(), attr16.size(), - package16.string(), package16.size(), &typeSpecFlags); - if (code == 0) { - fprintf(stderr, "ERROR: In <declare-styleable> %s, unable to find attribute %s\n", - nclassName.string(), sym.name.string()); - hasErrors = true; - } - isPublic = (typeSpecFlags&ResTable_typeSpec::SPEC_PUBLIC) != 0; - } - idents.add(code); - origOrder.add(code); - publicFlags.add(isPublic); - } - - NA = idents.size(); - - bool deprecated = false; - - String16 comment = symbols->getComment(realClassName); - fprintf(fp, "%s/** ", indentStr); - if (comment.size() > 0) { - String8 cmt(comment); - fprintf(fp, "%s\n", cmt.string()); - if (strstr(cmt.string(), "@deprecated") != NULL) { - deprecated = true; - } - } else { - fprintf(fp, "Attributes that can be used with a %s.\n", nclassName.string()); - } - bool hasTable = false; - for (a=0; a<NA; a++) { - ssize_t pos = idents.indexOf(origOrder.itemAt(a)); - if (pos >= 0) { - if (!hasTable) { - hasTable = true; - fprintf(fp, - "%s <p>Includes the following attributes:</p>\n" - "%s <table>\n" - "%s <colgroup align=\"left\" />\n" - "%s <colgroup align=\"left\" />\n" - "%s <tr><th>Attribute</th><th>Description</th></tr>\n", - indentStr, - indentStr, - indentStr, - indentStr, - indentStr); - } - const AaptSymbolEntry& sym = nsymbols->getSymbols().valueAt(a); - if (!publicFlags.itemAt(a) && !includePrivate) { - continue; - } - String8 name8(sym.name); - String16 comment(sym.comment); - if (comment.size() <= 0) { - comment = getAttributeComment(assets, name8); - } - if (comment.size() > 0) { - const char16_t* p = comment.string(); - while (*p != 0 && *p != '.') { - if (*p == '{') { - while (*p != 0 && *p != '}') { - p++; - } - } else { - p++; - } - } - if (*p == '.') { - p++; - } - comment = String16(comment.string(), p-comment.string()); - } - fprintf(fp, "%s <tr><td><code>{@link #%s_%s %s:%s}</code></td><td>%s</td></tr>\n", - indentStr, nclassName.string(), - flattenSymbol(name8).string(), - getSymbolPackage(name8, assets, true).string(), - getSymbolName(name8).string(), - String8(comment).string()); - } - } - if (hasTable) { - fprintf(fp, "%s </table>\n", indentStr); - } - for (a=0; a<NA; a++) { - ssize_t pos = idents.indexOf(origOrder.itemAt(a)); - if (pos >= 0) { - const AaptSymbolEntry& sym = nsymbols->getSymbols().valueAt(a); - if (!publicFlags.itemAt(a) && !includePrivate) { - continue; - } - fprintf(fp, "%s @see #%s_%s\n", - indentStr, nclassName.string(), - flattenSymbol(sym.name).string()); - } - } - fprintf(fp, "%s */\n", getIndentSpace(indent)); - - if (deprecated) { - fprintf(fp, "%s@Deprecated\n", indentStr); - } - - fprintf(fp, - "%spublic static final int[] %s = {\n" - "%s", - indentStr, nclassName.string(), - getIndentSpace(indent+1)); - - for (a=0; a<NA; a++) { - if (a != 0) { - if ((a&3) == 0) { - fprintf(fp, ",\n%s", getIndentSpace(indent+1)); - } else { - fprintf(fp, ", "); - } - } - fprintf(fp, "0x%08x", idents[a]); - } - - fprintf(fp, "\n%s};\n", indentStr); - - for (a=0; a<NA; a++) { - ssize_t pos = idents.indexOf(origOrder.itemAt(a)); - if (pos >= 0) { - const AaptSymbolEntry& sym = nsymbols->getSymbols().valueAt(a); - if (!publicFlags.itemAt(a) && !includePrivate) { - continue; - } - String8 name8(sym.name); - String16 comment(sym.comment); - String16 typeComment; - if (comment.size() <= 0) { - comment = getAttributeComment(assets, name8, &typeComment); - } else { - getAttributeComment(assets, name8, &typeComment); - } - - uint32_t typeSpecFlags = 0; - String16 name16(sym.name); - assets->getIncludedResources().identifierForName( - name16.string(), name16.size(), - attr16.string(), attr16.size(), - package16.string(), package16.size(), &typeSpecFlags); - //printf("%s:%s/%s: 0x%08x\n", String8(package16).string(), - // String8(attr16).string(), String8(name16).string(), typeSpecFlags); - const bool pub = (typeSpecFlags&ResTable_typeSpec::SPEC_PUBLIC) != 0; - - bool deprecated = false; - - fprintf(fp, "%s/**\n", indentStr); - if (comment.size() > 0) { - String8 cmt(comment); - fprintf(fp, "%s <p>\n%s @attr description\n", indentStr, indentStr); - fprintf(fp, "%s %s\n", indentStr, cmt.string()); - if (strstr(cmt.string(), "@deprecated") != NULL) { - deprecated = true; - } - } else { - fprintf(fp, - "%s <p>This symbol is the offset where the {@link %s.R.attr#%s}\n" - "%s attribute's value can be found in the {@link #%s} array.\n", - indentStr, - getSymbolPackage(name8, assets, pub).string(), - getSymbolName(name8).string(), - indentStr, nclassName.string()); - } - if (typeComment.size() > 0) { - String8 cmt(typeComment); - fprintf(fp, "\n\n%s %s\n", indentStr, cmt.string()); - if (strstr(cmt.string(), "@deprecated") != NULL) { - deprecated = true; - } - } - if (comment.size() > 0) { - if (pub) { - fprintf(fp, - "%s <p>This corresponds to the global attribute\n" - "%s resource symbol {@link %s.R.attr#%s}.\n", - indentStr, indentStr, - getSymbolPackage(name8, assets, true).string(), - getSymbolName(name8).string()); - } else { - fprintf(fp, - "%s <p>This is a private symbol.\n", indentStr); - } - } - fprintf(fp, "%s @attr name %s:%s\n", indentStr, - getSymbolPackage(name8, assets, pub).string(), - getSymbolName(name8).string()); - fprintf(fp, "%s*/\n", indentStr); - if (deprecated) { - fprintf(fp, "%s@Deprecated\n", indentStr); - } - fprintf(fp, - "%spublic static final int %s_%s = %d;\n", - indentStr, nclassName.string(), - flattenSymbol(name8).string(), (int)pos); - } - } - } - - indent--; - fprintf(fp, "%s};\n", getIndentSpace(indent)); - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -static status_t writeTextLayoutClasses( - FILE* fp, const sp<AaptAssets>& assets, - const sp<AaptSymbols>& symbols, bool includePrivate) -{ - String16 attr16("attr"); - String16 package16(assets->getPackage()); - - bool hasErrors = false; - - size_t i; - size_t N = symbols->getNestedSymbols().size(); - for (i=0; i<N; i++) { - sp<AaptSymbols> nsymbols = symbols->getNestedSymbols().valueAt(i); - String8 realClassName(symbols->getNestedSymbols().keyAt(i)); - String8 nclassName(flattenSymbol(realClassName)); - - SortedVector<uint32_t> idents; - Vector<uint32_t> origOrder; - Vector<bool> publicFlags; - - size_t a; - size_t NA = nsymbols->getSymbols().size(); - for (a=0; a<NA; a++) { - const AaptSymbolEntry& sym(nsymbols->getSymbols().valueAt(a)); - int32_t code = sym.typeCode == AaptSymbolEntry::TYPE_INT32 - ? sym.int32Val : 0; - bool isPublic = true; - if (code == 0) { - String16 name16(sym.name); - uint32_t typeSpecFlags; - code = assets->getIncludedResources().identifierForName( - name16.string(), name16.size(), - attr16.string(), attr16.size(), - package16.string(), package16.size(), &typeSpecFlags); - if (code == 0) { - fprintf(stderr, "ERROR: In <declare-styleable> %s, unable to find attribute %s\n", - nclassName.string(), sym.name.string()); - hasErrors = true; - } - isPublic = (typeSpecFlags&ResTable_typeSpec::SPEC_PUBLIC) != 0; - } - idents.add(code); - origOrder.add(code); - publicFlags.add(isPublic); - } - - NA = idents.size(); - - fprintf(fp, "int[] styleable %s {", nclassName.string()); - - for (a=0; a<NA; a++) { - if (a != 0) { - fprintf(fp, ","); - } - fprintf(fp, " 0x%08x", idents[a]); - } - - fprintf(fp, " }\n"); - - for (a=0; a<NA; a++) { - ssize_t pos = idents.indexOf(origOrder.itemAt(a)); - if (pos >= 0) { - const AaptSymbolEntry& sym = nsymbols->getSymbols().valueAt(a); - if (!publicFlags.itemAt(a) && !includePrivate) { - continue; - } - String8 name8(sym.name); - String16 comment(sym.comment); - String16 typeComment; - if (comment.size() <= 0) { - comment = getAttributeComment(assets, name8, &typeComment); - } else { - getAttributeComment(assets, name8, &typeComment); - } - - uint32_t typeSpecFlags = 0; - String16 name16(sym.name); - assets->getIncludedResources().identifierForName( - name16.string(), name16.size(), - attr16.string(), attr16.size(), - package16.string(), package16.size(), &typeSpecFlags); - //printf("%s:%s/%s: 0x%08x\n", String8(package16).string(), - // String8(attr16).string(), String8(name16).string(), typeSpecFlags); - const bool pub = (typeSpecFlags&ResTable_typeSpec::SPEC_PUBLIC) != 0; - - fprintf(fp, - "int styleable %s_%s %d\n", - nclassName.string(), - flattenSymbol(name8).string(), (int)pos); - } - } - } - - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -static status_t writeSymbolClass( - FILE* fp, const sp<AaptAssets>& assets, bool includePrivate, - const sp<AaptSymbols>& symbols, const String8& className, int indent, - bool nonConstantId) -{ - fprintf(fp, "%spublic %sfinal class %s {\n", - getIndentSpace(indent), - indent != 0 ? "static " : "", className.string()); - indent++; - - size_t i; - status_t err = NO_ERROR; - - const char * id_format = nonConstantId ? - "%spublic static int %s=0x%08x;\n" : - "%spublic static final int %s=0x%08x;\n"; - - size_t N = symbols->getSymbols().size(); - for (i=0; i<N; i++) { - const AaptSymbolEntry& sym = symbols->getSymbols().valueAt(i); - if (sym.typeCode != AaptSymbolEntry::TYPE_INT32) { - continue; - } - if (!assets->isJavaSymbol(sym, includePrivate)) { - continue; - } - String8 name8(sym.name); - String16 comment(sym.comment); - bool haveComment = false; - bool deprecated = false; - if (comment.size() > 0) { - haveComment = true; - String8 cmt(comment); - fprintf(fp, - "%s/** %s\n", - getIndentSpace(indent), cmt.string()); - if (strstr(cmt.string(), "@deprecated") != NULL) { - deprecated = true; - } - } else if (sym.isPublic && !includePrivate) { - sym.sourcePos.warning("No comment for public symbol %s:%s/%s", - assets->getPackage().string(), className.string(), - String8(sym.name).string()); - } - String16 typeComment(sym.typeComment); - if (typeComment.size() > 0) { - String8 cmt(typeComment); - if (!haveComment) { - haveComment = true; - fprintf(fp, - "%s/** %s\n", getIndentSpace(indent), cmt.string()); - } else { - fprintf(fp, - "%s %s\n", getIndentSpace(indent), cmt.string()); - } - if (strstr(cmt.string(), "@deprecated") != NULL) { - deprecated = true; - } - } - if (haveComment) { - fprintf(fp,"%s */\n", getIndentSpace(indent)); - } - if (deprecated) { - fprintf(fp, "%s@Deprecated\n", getIndentSpace(indent)); - } - fprintf(fp, id_format, - getIndentSpace(indent), - flattenSymbol(name8).string(), (int)sym.int32Val); - } - - for (i=0; i<N; i++) { - const AaptSymbolEntry& sym = symbols->getSymbols().valueAt(i); - if (sym.typeCode != AaptSymbolEntry::TYPE_STRING) { - continue; - } - if (!assets->isJavaSymbol(sym, includePrivate)) { - continue; - } - String8 name8(sym.name); - String16 comment(sym.comment); - bool deprecated = false; - if (comment.size() > 0) { - String8 cmt(comment); - fprintf(fp, - "%s/** %s\n" - "%s */\n", - getIndentSpace(indent), cmt.string(), - getIndentSpace(indent)); - if (strstr(cmt.string(), "@deprecated") != NULL) { - deprecated = true; - } - } else if (sym.isPublic && !includePrivate) { - sym.sourcePos.warning("No comment for public symbol %s:%s/%s", - assets->getPackage().string(), className.string(), - String8(sym.name).string()); - } - if (deprecated) { - fprintf(fp, "%s@Deprecated\n", getIndentSpace(indent)); - } - fprintf(fp, "%spublic static final String %s=\"%s\";\n", - getIndentSpace(indent), - flattenSymbol(name8).string(), sym.stringVal.string()); - } - - sp<AaptSymbols> styleableSymbols; - - N = symbols->getNestedSymbols().size(); - for (i=0; i<N; i++) { - sp<AaptSymbols> nsymbols = symbols->getNestedSymbols().valueAt(i); - String8 nclassName(symbols->getNestedSymbols().keyAt(i)); - if (nclassName == "styleable") { - styleableSymbols = nsymbols; - } else { - err = writeSymbolClass(fp, assets, includePrivate, nsymbols, nclassName, indent, nonConstantId); - } - if (err != NO_ERROR) { - return err; - } - } - - if (styleableSymbols != NULL) { - err = writeLayoutClasses(fp, assets, styleableSymbols, indent, includePrivate); - if (err != NO_ERROR) { - return err; - } - } - - indent--; - fprintf(fp, "%s}\n", getIndentSpace(indent)); - return NO_ERROR; -} - -static status_t writeTextSymbolClass( - FILE* fp, const sp<AaptAssets>& assets, bool includePrivate, - const sp<AaptSymbols>& symbols, const String8& className) -{ - size_t i; - status_t err = NO_ERROR; - - size_t N = symbols->getSymbols().size(); - for (i=0; i<N; i++) { - const AaptSymbolEntry& sym = symbols->getSymbols().valueAt(i); - if (sym.typeCode != AaptSymbolEntry::TYPE_INT32) { - continue; - } - - if (!assets->isJavaSymbol(sym, includePrivate)) { - continue; - } - - String8 name8(sym.name); - fprintf(fp, "int %s %s 0x%08x\n", - className.string(), - flattenSymbol(name8).string(), (int)sym.int32Val); - } - - N = symbols->getNestedSymbols().size(); - for (i=0; i<N; i++) { - sp<AaptSymbols> nsymbols = symbols->getNestedSymbols().valueAt(i); - String8 nclassName(symbols->getNestedSymbols().keyAt(i)); - if (nclassName == "styleable") { - err = writeTextLayoutClasses(fp, assets, nsymbols, includePrivate); - } else { - err = writeTextSymbolClass(fp, assets, includePrivate, nsymbols, nclassName); - } - if (err != NO_ERROR) { - return err; - } - } - - return NO_ERROR; -} - -status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, - const String8& package, bool includePrivate) -{ - if (!bundle->getRClassDir()) { - return NO_ERROR; - } - - const char* textSymbolsDest = bundle->getOutputTextSymbols(); - - String8 R("R"); - const size_t N = assets->getSymbols().size(); - for (size_t i=0; i<N; i++) { - sp<AaptSymbols> symbols = assets->getSymbols().valueAt(i); - String8 className(assets->getSymbols().keyAt(i)); - String8 dest(bundle->getRClassDir()); - - if (bundle->getMakePackageDirs()) { - String8 pkg(package); - const char* last = pkg.string(); - const char* s = last-1; - do { - s++; - if (s > last && (*s == '.' || *s == 0)) { - String8 part(last, s-last); - dest.appendPath(part); -#ifdef HAVE_MS_C_RUNTIME - _mkdir(dest.string()); -#else - mkdir(dest.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP); -#endif - last = s+1; - } - } while (*s); - } - dest.appendPath(className); - dest.append(".java"); - FILE* fp = fopen(dest.string(), "w+"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Unable to open class file %s: %s\n", - dest.string(), strerror(errno)); - return UNKNOWN_ERROR; - } - if (bundle->getVerbose()) { - printf(" Writing symbols for class %s.\n", className.string()); - } - - fprintf(fp, - "/* AUTO-GENERATED FILE. DO NOT MODIFY.\n" - " *\n" - " * This class was automatically generated by the\n" - " * aapt tool from the resource data it found. It\n" - " * should not be modified by hand.\n" - " */\n" - "\n" - "package %s;\n\n", package.string()); - - status_t err = writeSymbolClass(fp, assets, includePrivate, symbols, - className, 0, bundle->getNonConstantId()); - if (err != NO_ERROR) { - return err; - } - fclose(fp); - - if (textSymbolsDest != NULL && R == className) { - String8 textDest(textSymbolsDest); - textDest.appendPath(className); - textDest.append(".txt"); - - FILE* fp = fopen(textDest.string(), "w+"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Unable to open text symbol file %s: %s\n", - textDest.string(), strerror(errno)); - return UNKNOWN_ERROR; - } - if (bundle->getVerbose()) { - printf(" Writing text symbols for class %s.\n", className.string()); - } - - status_t err = writeTextSymbolClass(fp, assets, includePrivate, symbols, - className); - if (err != NO_ERROR) { - return err; - } - fclose(fp); - } - - // If we were asked to generate a dependency file, we'll go ahead and add this R.java - // as a target in the dependency file right next to it. - if (bundle->getGenDependencies() && R == className) { - // Add this R.java to the dependency file - String8 dependencyFile(bundle->getRClassDir()); - dependencyFile.appendPath("R.java.d"); - - FILE *fp = fopen(dependencyFile.string(), "a"); - fprintf(fp,"%s \\\n", dest.string()); - fclose(fp); - } - } - - return NO_ERROR; -} - - -class ProguardKeepSet -{ -public: - // { rule --> { file locations } } - KeyedVector<String8, SortedVector<String8> > rules; - - void add(const String8& rule, const String8& where); -}; - -void ProguardKeepSet::add(const String8& rule, const String8& where) -{ - ssize_t index = rules.indexOfKey(rule); - if (index < 0) { - index = rules.add(rule, SortedVector<String8>()); - } - rules.editValueAt(index).add(where); -} - -void -addProguardKeepRule(ProguardKeepSet* keep, const String8& inClassName, - const char* pkg, const String8& srcName, int line) -{ - String8 className(inClassName); - if (pkg != NULL) { - // asdf --> package.asdf - // .asdf .a.b --> package.asdf package.a.b - // asdf.adsf --> asdf.asdf - const char* p = className.string(); - const char* q = strchr(p, '.'); - if (p == q) { - className = pkg; - className.append(inClassName); - } else if (q == NULL) { - className = pkg; - className.append("."); - className.append(inClassName); - } - } - - String8 rule("-keep class "); - rule += className; - rule += " { <init>(...); }"; - - String8 location("view "); - location += srcName; - char lineno[20]; - sprintf(lineno, ":%d", line); - location += lineno; - - keep->add(rule, location); -} - -void -addProguardKeepMethodRule(ProguardKeepSet* keep, const String8& memberName, - const char* pkg, const String8& srcName, int line) -{ - String8 rule("-keepclassmembers class * { *** "); - rule += memberName; - rule += "(...); }"; - - String8 location("onClick "); - location += srcName; - char lineno[20]; - sprintf(lineno, ":%d", line); - location += lineno; - - keep->add(rule, location); -} - -status_t -writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& assets) -{ - status_t err; - ResXMLTree tree; - size_t len; - ResXMLTree::event_code_t code; - int depth = 0; - bool inApplication = false; - String8 error; - sp<AaptGroup> assGroup; - sp<AaptFile> assFile; - String8 pkg; - - // First, look for a package file to parse. This is required to - // be able to generate the resource information. - assGroup = assets->getFiles().valueFor(String8("AndroidManifest.xml")); - if (assGroup == NULL) { - fprintf(stderr, "ERROR: No AndroidManifest.xml file found.\n"); - return -1; - } - - if (assGroup->getFiles().size() != 1) { - fprintf(stderr, "warning: Multiple AndroidManifest.xml files found, using %s\n", - assGroup->getFiles().valueAt(0)->getPrintableSource().string()); - } - - assFile = assGroup->getFiles().valueAt(0); - - err = parseXMLResource(assFile, &tree); - if (err != NO_ERROR) { - return err; - } - - tree.restart(); - - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (/* name == "Application" && */ depth == 2) { - inApplication = false; - } - depth--; - continue; - } - if (code != ResXMLTree::START_TAG) { - continue; - } - depth++; - String8 tag(tree.getElementName(&len)); - // printf("Depth %d tag %s\n", depth, tag.string()); - bool keepTag = false; - if (depth == 1) { - if (tag != "manifest") { - fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n"); - return -1; - } - pkg = getAttribute(tree, NULL, "package", NULL); - } else if (depth == 2) { - if (tag == "application") { - inApplication = true; - keepTag = true; - - String8 agent = getAttribute(tree, "http://schemas.android.com/apk/res/android", - "backupAgent", &error); - if (agent.length() > 0) { - addProguardKeepRule(keep, agent, pkg.string(), - assFile->getPrintableSource(), tree.getLineNumber()); - } - } else if (tag == "instrumentation") { - keepTag = true; - } - } - if (!keepTag && inApplication && depth == 3) { - if (tag == "activity" || tag == "service" || tag == "receiver" || tag == "provider") { - keepTag = true; - } - } - if (keepTag) { - String8 name = getAttribute(tree, "http://schemas.android.com/apk/res/android", - "name", &error); - if (error != "") { - fprintf(stderr, "ERROR: %s\n", error.string()); - return -1; - } - if (name.length() > 0) { - addProguardKeepRule(keep, name, pkg.string(), - assFile->getPrintableSource(), tree.getLineNumber()); - } - } - } - - 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 KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs) -{ - status_t err; - ResXMLTree tree; - size_t len; - ResXMLTree::event_code_t code; - - err = parseXMLResource(layoutFile, &tree); - if (err != NO_ERROR) { - return err; - } - - tree.restart(); - - if (startTag != NULL) { - bool haveStart = false; - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code != ResXMLTree::START_TAG) { - continue; - } - String8 tag(tree.getElementName(&len)); - if (tag == startTag) { - haveStart = true; - } - break; - } - if (!haveStart) { - return NO_ERROR; - } - } - - while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code != ResXMLTree::START_TAG) { - continue; - } - String8 tag(tree.getElementName(&len)); - - // If there is no '.', we'll assume that it's one of the built in names. - if (strchr(tag.string(), '.')) { - addProguardKeepRule(keep, tag, NULL, - layoutFile->getPrintableSource(), tree.getLineNumber()); - } else if (tagAttrPairs != NULL) { - ssize_t tagIndex = tagAttrPairs->indexOfKey(tag); - if (tagIndex >= 0) { - const Vector<NamespaceAttributePair>& nsAttrVector = tagAttrPairs->valueAt(tagIndex); - for (size_t i = 0; i < nsAttrVector.size(); i++) { - const NamespaceAttributePair& nsAttr = nsAttrVector[i]; - - 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()); - } - } - } - } - ssize_t attrIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, "onClick"); - if (attrIndex >= 0) { - size_t len; - addProguardKeepMethodRule(keep, - String8(tree.getAttributeStringValue(attrIndex, &len)), NULL, - layoutFile->getPrintableSource(), tree.getLineNumber()); - } - } - - return NO_ERROR; -} - -static void addTagAttrPair(KeyedVector<String8, Vector<NamespaceAttributePair> >* dest, - const char* tag, const char* ns, const char* attr) { - String8 tagStr(tag); - ssize_t index = dest->indexOfKey(tagStr); - - if (index < 0) { - Vector<NamespaceAttributePair> vector; - vector.add(NamespaceAttributePair(ns, attr)); - dest->add(tagStr, vector); - } else { - dest->editValueAt(index).add(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, Vector<NamespaceAttributePair> > kLayoutTagAttrPairs; - addTagAttrPair(&kLayoutTagAttrPairs, "view", NULL, "class"); - addTagAttrPair(&kLayoutTagAttrPairs, "fragment", NULL, "class"); - addTagAttrPair(&kLayoutTagAttrPairs, "fragment", RESOURCES_ANDROID_NAMESPACE, "name"); - - // tag:attribute pairs that should be checked in xml files. - KeyedVector<String8, Vector<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 KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs = NULL; - if ((dirName == String8("layout")) || (strncmp(dirName.string(), "layout-", 7) == 0)) { - tagAttrPairs = &kLayoutTagAttrPairs; - } else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) { - startTag = "PreferenceScreen"; - tagAttrPairs = &kXmlTagAttrPairs; - } else if ((dirName == String8("menu")) || (strncmp(dirName.string(), "menu-", 5) == 0)) { - startTag = "menu"; - tagAttrPairs = NULL; - } else { - continue; - } - - const KeyedVector<String8,sp<AaptGroup> > groups = d->getFiles(); - const size_t N = groups.size(); - for (size_t i=0; i<N; i++) { - const sp<AaptGroup>& group = groups.valueAt(i); - 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, tagAttrPairs); - if (err < 0) { - return err; - } - } - } - } - // Handle the overlays - sp<AaptAssets> overlay = assets->getOverlay(); - if (overlay.get()) { - return writeProguardForLayouts(keep, overlay); - } - - return NO_ERROR; -} - -status_t -writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets) -{ - status_t err = -1; - - if (!bundle->getProguardFile()) { - return NO_ERROR; - } - - ProguardKeepSet keep; - - err = writeProguardForAndroidManifest(&keep, assets); - if (err < 0) { - return err; - } - - err = writeProguardForLayouts(&keep, assets); - if (err < 0) { - return err; - } - - FILE* fp = fopen(bundle->getProguardFile(), "w+"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Unable to open class file %s: %s\n", - bundle->getProguardFile(), strerror(errno)); - return UNKNOWN_ERROR; - } - - const KeyedVector<String8, SortedVector<String8> >& rules = keep.rules; - const size_t N = rules.size(); - for (size_t i=0; i<N; i++) { - const SortedVector<String8>& locations = rules.valueAt(i); - const size_t M = locations.size(); - for (size_t j=0; j<M; j++) { - fprintf(fp, "# %s\n", locations.itemAt(j).string()); - } - fprintf(fp, "%s\n\n", rules.keyAt(i).string()); - } - fclose(fp); - - return err; -} - -// Loops through the string paths and writes them to the file pointer -// Each file path is written on its own line with a terminating backslash. -status_t writePathsToFile(const sp<FilePathStore>& files, FILE* fp) -{ - status_t deps = -1; - for (size_t file_i = 0; file_i < files->size(); ++file_i) { - // Add the full file path to the dependency file - fprintf(fp, "%s \\\n", files->itemAt(file_i).string()); - deps++; - } - return deps; -} - -status_t -writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp, bool includeRaw) -{ - status_t deps = -1; - deps += writePathsToFile(assets->getFullResPaths(), fp); - if (includeRaw) { - deps += writePathsToFile(assets->getFullAssetPaths(), fp); - } - return deps; -} diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp deleted file mode 100644 index 8cfd2a5..0000000 --- a/tools/aapt/ResourceFilter.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#include "ResourceFilter.h" - -status_t -ResourceFilter::parse(const char* arg) -{ - if (arg == NULL) { - return 0; - } - - const char* p = arg; - const char* q; - - while (true) { - q = strchr(p, ','); - if (q == NULL) { - q = p + strlen(p); - } - - String8 part(p, q-p); - - if (part == "zz_ZZ") { - mContainsPseudo = true; - } - int axis; - uint32_t value; - if (AaptGroupEntry::parseNamePart(part, &axis, &value)) { - fprintf(stderr, "Invalid configuration: %s\n", arg); - fprintf(stderr, " "); - for (int i=0; i<p-arg; i++) { - fprintf(stderr, " "); - } - for (int i=0; i<q-p; i++) { - fprintf(stderr, "^"); - } - fprintf(stderr, "\n"); - return 1; - } - - ssize_t index = mData.indexOfKey(axis); - if (index < 0) { - mData.add(axis, SortedVector<uint32_t>()); - } - SortedVector<uint32_t>& sv = mData.editValueFor(axis); - sv.add(value); - // if it's a locale with a region, also match an unmodified locale of the - // same language - if (axis == AXIS_LANGUAGE) { - if (value & 0xffff0000) { - sv.add(value & 0x0000ffff); - } - } - p = q; - if (!*p) break; - p++; - } - - return NO_ERROR; -} - -bool -ResourceFilter::isEmpty() const -{ - return mData.size() == 0; -} - -bool -ResourceFilter::match(int axis, uint32_t value) const -{ - if (value == 0) { - // they didn't specify anything so take everything - return true; - } - ssize_t index = mData.indexOfKey(axis); - if (index < 0) { - // we didn't request anything on this axis so take everything - return true; - } - const SortedVector<uint32_t>& sv = mData.valueAt(index); - return sv.indexOf(value) >= 0; -} - -bool -ResourceFilter::match(int axis, const ResTable_config& config) const -{ - return match(axis, AaptGroupEntry::getConfigValueForAxis(config, axis)); -} - -bool -ResourceFilter::match(const ResTable_config& config) const -{ - for (int i=AXIS_START; i<=AXIS_END; i++) { - if (!match(i, AaptGroupEntry::getConfigValueForAxis(config, i))) { - return false; - } - } - return true; -} - -const SortedVector<uint32_t>* ResourceFilter::configsForAxis(int axis) const -{ - ssize_t index = mData.indexOfKey(axis); - if (index < 0) { - return NULL; - } - return &mData.valueAt(index); -} diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h deleted file mode 100644 index 647b7bb..0000000 --- a/tools/aapt/ResourceFilter.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#ifndef RESOURCE_FILTER_H -#define RESOURCE_FILTER_H - -#include "AaptAssets.h" - -/** - * Implements logic for parsing and handling "-c" and "--preferred-configurations" - * options. - */ -class ResourceFilter -{ -public: - ResourceFilter() : mData(), mContainsPseudo(false) {} - status_t parse(const char* arg); - bool isEmpty() const; - bool match(int axis, uint32_t value) const; - bool match(int axis, const ResTable_config& config) const; - bool match(const ResTable_config& config) const; - const SortedVector<uint32_t>* configsForAxis(int axis) const; - inline bool containsPseudo() const { return mContainsPseudo; } - -private: - KeyedVector<int,SortedVector<uint32_t> > mData; - bool mContainsPseudo; -}; - -#endif diff --git a/tools/aapt/ResourceIdCache.cpp b/tools/aapt/ResourceIdCache.cpp deleted file mode 100644 index e03f4f6..0000000 --- a/tools/aapt/ResourceIdCache.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// Copyright 2012 The Android Open Source Project -// -// Manage a resource ID cache. - -#define LOG_TAG "ResourceIdCache" - -#include <utils/String16.h> -#include <utils/Log.h> -#include "ResourceIdCache.h" -#include <map> -using namespace std; - - -static size_t mHits = 0; -static size_t mMisses = 0; -static size_t mCollisions = 0; - -static const size_t MAX_CACHE_ENTRIES = 2048; -static const android::String16 TRUE16("1"); -static const android::String16 FALSE16("0"); - -struct CacheEntry { - // concatenation of the relevant strings into a single instance - android::String16 hashedName; - uint32_t id; - - CacheEntry() {} - CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { } -}; - -static map< uint32_t, CacheEntry > mIdMap; - - -// djb2; reasonable choice for strings when collisions aren't particularly important -static inline uint32_t hashround(uint32_t hash, int c) { - return ((hash << 5) + hash) + c; /* hash * 33 + c */ -} - -static uint32_t hash(const android::String16& hashableString) { - uint32_t hash = 5381; - const char16_t* str = hashableString.string(); - while (int c = *str++) hash = hashround(hash, c); - return hash; -} - -namespace android { - -static inline String16 makeHashableName(const android::String16& package, - const android::String16& type, - const android::String16& name, - bool onlyPublic) { - String16 hashable = String16(name); - hashable += type; - hashable += package; - hashable += (onlyPublic ? TRUE16 : FALSE16); - return hashable; -} - -uint32_t ResourceIdCache::lookup(const android::String16& package, - const android::String16& type, - const android::String16& name, - bool onlyPublic) { - const String16 hashedName = makeHashableName(package, type, name, onlyPublic); - const uint32_t hashcode = hash(hashedName); - map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode); - if (item == mIdMap.end()) { - // cache miss - mMisses++; - return 0; - } - - // legit match? - if (hashedName == (*item).second.hashedName) { - mHits++; - return (*item).second.id; - } - - // collision - mCollisions++; - mIdMap.erase(hashcode); - return 0; -} - -// returns the resource ID being stored, for callsite convenience -uint32_t ResourceIdCache::store(const android::String16& package, - const android::String16& type, - const android::String16& name, - bool onlyPublic, - uint32_t resId) { - if (mIdMap.size() < MAX_CACHE_ENTRIES) { - const String16 hashedName = makeHashableName(package, type, name, onlyPublic); - const uint32_t hashcode = hash(hashedName); - mIdMap[hashcode] = CacheEntry(hashedName, resId); - } - return resId; -} - -void ResourceIdCache::dump() { - printf("ResourceIdCache dump:\n"); - printf("Size: %ld\n", mIdMap.size()); - printf("Hits: %ld\n", mHits); - printf("Misses: %ld\n", mMisses); - printf("(Collisions: %ld)\n", mCollisions); -} - -} diff --git a/tools/aapt/ResourceIdCache.h b/tools/aapt/ResourceIdCache.h deleted file mode 100644 index 65f7781..0000000 --- a/tools/aapt/ResourceIdCache.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright 2012 The Android Open Source Project -// -// Manage a resource ID cache. - -#ifndef RESOURCE_ID_CACHE_H -#define RESOURCE_ID_CACHE_H - -namespace android { -class android::String16; - -class ResourceIdCache { -public: - static uint32_t lookup(const android::String16& package, - const android::String16& type, - const android::String16& name, - bool onlyPublic); - - static uint32_t store(const android::String16& package, - const android::String16& type, - const android::String16& name, - bool onlyPublic, - uint32_t resId); - - static void dump(void); -}; - -} - -#endif diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp deleted file mode 100644 index 52ebaf0..0000000 --- a/tools/aapt/ResourceTable.cpp +++ /dev/null @@ -1,3905 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#include "ResourceTable.h" - -#include "XMLNode.h" -#include "ResourceFilter.h" -#include "ResourceIdCache.h" - -#include <androidfw/ResourceTypes.h> -#include <utils/ByteOrder.h> -#include <stdarg.h> - -#define NOISY(x) //x - -status_t compileXmlFile(const sp<AaptAssets>& assets, - const sp<AaptFile>& target, - ResourceTable* table, - int options) -{ - sp<XMLNode> root = XMLNode::parse(target); - if (root == NULL) { - return UNKNOWN_ERROR; - } - - return compileXmlFile(assets, root, target, table, options); -} - -status_t compileXmlFile(const sp<AaptAssets>& assets, - const sp<AaptFile>& target, - const sp<AaptFile>& outTarget, - ResourceTable* table, - int options) -{ - sp<XMLNode> root = XMLNode::parse(target); - if (root == NULL) { - return UNKNOWN_ERROR; - } - - return compileXmlFile(assets, root, outTarget, 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) { - root->removeWhitespace(false, NULL); - } - - if ((options&XML_COMPILE_UTF8) != 0) { - root->setUTF8(true); - } - - bool hasErrors = false; - - if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) { - status_t err = root->assignResourceIds(assets, table); - if (err != NO_ERROR) { - hasErrors = true; - } - } - - status_t err = root->parseValues(assets, table); - if (err != NO_ERROR) { - hasErrors = true; - } - - if (hasErrors) { - return UNKNOWN_ERROR; - } - - NOISY(printf("Input XML Resource:\n")); - NOISY(root->print()); - err = root->flatten(target, - (options&XML_COMPILE_STRIP_COMMENTS) != 0, - (options&XML_COMPILE_STRIP_RAW_VALUES) != 0); - if (err != NO_ERROR) { - return err; - } - - NOISY(printf("Output XML Resource:\n")); - NOISY(ResXMLTree tree; - tree.setTo(target->getData(), target->getSize()); - printXMLBlock(&tree)); - - target->setCompressionMethod(ZipEntry::kCompressDeflated); - - return err; -} - -#undef NOISY -#define NOISY(x) //x - -struct flag_entry -{ - const char16_t* name; - size_t nameLen; - uint32_t value; - const char* description; -}; - -static const char16_t referenceArray[] = - { 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e' }; -static const char16_t stringArray[] = - { 's', 't', 'r', 'i', 'n', 'g' }; -static const char16_t integerArray[] = - { 'i', 'n', 't', 'e', 'g', 'e', 'r' }; -static const char16_t booleanArray[] = - { 'b', 'o', 'o', 'l', 'e', 'a', 'n' }; -static const char16_t colorArray[] = - { 'c', 'o', 'l', 'o', 'r' }; -static const char16_t floatArray[] = - { 'f', 'l', 'o', 'a', 't' }; -static const char16_t dimensionArray[] = - { 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n' }; -static const char16_t fractionArray[] = - { 'f', 'r', 'a', 'c', 't', 'i', 'o', 'n' }; -static const char16_t enumArray[] = - { 'e', 'n', 'u', 'm' }; -static const char16_t flagsArray[] = - { 'f', 'l', 'a', 'g', 's' }; - -static const flag_entry gFormatFlags[] = { - { referenceArray, sizeof(referenceArray)/2, ResTable_map::TYPE_REFERENCE, - "a reference to another resource, in the form \"<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>\"\n" - "or to a theme attribute in the form \"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\"."}, - { stringArray, sizeof(stringArray)/2, ResTable_map::TYPE_STRING, - "a string value, using '\\\\;' to escape characters such as '\\\\n' or '\\\\uxxxx' for a unicode character." }, - { integerArray, sizeof(integerArray)/2, ResTable_map::TYPE_INTEGER, - "an integer value, such as \"<code>100</code>\"." }, - { booleanArray, sizeof(booleanArray)/2, ResTable_map::TYPE_BOOLEAN, - "a boolean value, either \"<code>true</code>\" or \"<code>false</code>\"." }, - { colorArray, sizeof(colorArray)/2, ResTable_map::TYPE_COLOR, - "a color value, in the form of \"<code>#<i>rgb</i></code>\", \"<code>#<i>argb</i></code>\",\n" - "\"<code>#<i>rrggbb</i></code>\", or \"<code>#<i>aarrggbb</i></code>\"." }, - { floatArray, sizeof(floatArray)/2, ResTable_map::TYPE_FLOAT, - "a floating point value, such as \"<code>1.2</code>\"."}, - { dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION, - "a dimension value, which is a floating point number appended with a unit such as \"<code>14.5sp</code>\".\n" - "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n" - "in (inches), mm (millimeters)." }, - { fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION, - "a fractional value, which is a floating point number appended with either % or %p, such as \"<code>14.5%</code>\".\n" - "The % suffix always means a percentage of the base size; the optional %p suffix provides a size relative to\n" - "some parent container." }, - { enumArray, sizeof(enumArray)/2, ResTable_map::TYPE_ENUM, NULL }, - { flagsArray, sizeof(flagsArray)/2, ResTable_map::TYPE_FLAGS, NULL }, - { NULL, 0, 0, NULL } -}; - -static const char16_t suggestedArray[] = { 's', 'u', 'g', 'g', 'e', 's', 't', 'e', 'd' }; - -static const flag_entry l10nRequiredFlags[] = { - { suggestedArray, sizeof(suggestedArray)/2, ResTable_map::L10N_SUGGESTED, NULL }, - { NULL, 0, 0, NULL } -}; - -static const char16_t nulStr[] = { 0 }; - -static uint32_t parse_flags(const char16_t* str, size_t len, - const flag_entry* flags, bool* outError = NULL) -{ - while (len > 0 && isspace(*str)) { - str++; - len--; - } - while (len > 0 && isspace(str[len-1])) { - len--; - } - - const char16_t* const end = str + len; - uint32_t value = 0; - - while (str < end) { - const char16_t* div = str; - while (div < end && *div != '|') { - div++; - } - - const flag_entry* cur = flags; - while (cur->name) { - if (strzcmp16(cur->name, cur->nameLen, str, div-str) == 0) { - value |= cur->value; - break; - } - cur++; - } - - if (!cur->name) { - if (outError) *outError = true; - return 0; - } - - str = div < end ? div+1 : div; - } - - if (outError) *outError = false; - return value; -} - -static String16 mayOrMust(int type, int flags) -{ - if ((type&(~flags)) == 0) { - return String16("<p>Must"); - } - - return String16("<p>May"); -} - -static void appendTypeInfo(ResourceTable* outTable, const String16& pkg, - const String16& typeName, const String16& ident, int type, - const flag_entry* flags) -{ - bool hadType = false; - while (flags->name) { - if ((type&flags->value) != 0 && flags->description != NULL) { - String16 fullMsg(mayOrMust(type, flags->value)); - fullMsg.append(String16(" be ")); - fullMsg.append(String16(flags->description)); - outTable->appendTypeComment(pkg, typeName, ident, fullMsg); - hadType = true; - } - flags++; - } - if (hadType && (type&ResTable_map::TYPE_REFERENCE) == 0) { - outTable->appendTypeComment(pkg, typeName, ident, - String16("<p>This may also be a reference to a resource (in the form\n" - "\"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>\") or\n" - "theme attribute (in the form\n" - "\"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\")\n" - "containing a value of this type.")); - } -} - -struct PendingAttribute -{ - const String16 myPackage; - const SourcePos sourcePos; - const bool appendComment; - int32_t type; - String16 ident; - String16 comment; - bool hasErrors; - bool added; - - PendingAttribute(String16 _package, const sp<AaptFile>& in, - ResXMLTree& block, bool _appendComment) - : myPackage(_package) - , sourcePos(in->getPrintableSource(), block.getLineNumber()) - , appendComment(_appendComment) - , type(ResTable_map::TYPE_ANY) - , hasErrors(false) - , added(false) - { - } - - status_t createIfNeeded(ResourceTable* outTable) - { - if (added || hasErrors) { - return NO_ERROR; - } - added = true; - - String16 attr16("attr"); - - if (outTable->hasBagOrEntry(myPackage, attr16, ident)) { - sourcePos.error("Attribute \"%s\" has already been defined\n", - String8(ident).string()); - hasErrors = true; - return UNKNOWN_ERROR; - } - - char numberStr[16]; - sprintf(numberStr, "%d", type); - status_t err = outTable->addBag(sourcePos, myPackage, - attr16, ident, String16(""), - String16("^type"), - String16(numberStr), NULL, NULL); - if (err != NO_ERROR) { - hasErrors = true; - return err; - } - outTable->appendComment(myPackage, attr16, ident, comment, appendComment); - //printf("Attribute %s comment: %s\n", String8(ident).string(), - // String8(comment).string()); - return err; - } -}; - -static status_t compileAttribute(const sp<AaptFile>& in, - ResXMLTree& block, - const String16& myPackage, - ResourceTable* outTable, - String16* outIdent = NULL, - bool inStyleable = false) -{ - PendingAttribute attr(myPackage, in, block, inStyleable); - - const String16 attr16("attr"); - const String16 id16("id"); - - // Attribute type constants. - const String16 enum16("enum"); - const String16 flag16("flag"); - - ResXMLTree::event_code_t code; - size_t len; - status_t err; - - ssize_t identIdx = block.indexOfAttribute(NULL, "name"); - if (identIdx >= 0) { - attr.ident = String16(block.getAttributeStringValue(identIdx, &len)); - if (outIdent) { - *outIdent = attr.ident; - } - } else { - attr.sourcePos.error("A 'name' attribute is required for <attr>\n"); - attr.hasErrors = true; - } - - attr.comment = String16( - block.getComment(&len) ? block.getComment(&len) : nulStr); - - ssize_t typeIdx = block.indexOfAttribute(NULL, "format"); - if (typeIdx >= 0) { - String16 typeStr = String16(block.getAttributeStringValue(typeIdx, &len)); - attr.type = parse_flags(typeStr.string(), typeStr.size(), gFormatFlags); - if (attr.type == 0) { - attr.sourcePos.error("Tag <attr> 'format' attribute value \"%s\" not valid\n", - String8(typeStr).string()); - attr.hasErrors = true; - } - attr.createIfNeeded(outTable); - } else if (!inStyleable) { - // Attribute definitions outside of styleables always define the - // attribute as a generic value. - attr.createIfNeeded(outTable); - } - - //printf("Attribute %s: type=0x%08x\n", String8(attr.ident).string(), attr.type); - - ssize_t minIdx = block.indexOfAttribute(NULL, "min"); - if (minIdx >= 0) { - String16 val = String16(block.getAttributeStringValue(minIdx, &len)); - if (!ResTable::stringToInt(val.string(), val.size(), NULL)) { - attr.sourcePos.error("Tag <attr> 'min' attribute must be a number, not \"%s\"\n", - String8(val).string()); - attr.hasErrors = true; - } - attr.createIfNeeded(outTable); - if (!attr.hasErrors) { - err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident, - String16(""), String16("^min"), String16(val), NULL, NULL); - if (err != NO_ERROR) { - attr.hasErrors = true; - } - } - } - - ssize_t maxIdx = block.indexOfAttribute(NULL, "max"); - if (maxIdx >= 0) { - String16 val = String16(block.getAttributeStringValue(maxIdx, &len)); - if (!ResTable::stringToInt(val.string(), val.size(), NULL)) { - attr.sourcePos.error("Tag <attr> 'max' attribute must be a number, not \"%s\"\n", - String8(val).string()); - attr.hasErrors = true; - } - attr.createIfNeeded(outTable); - if (!attr.hasErrors) { - err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident, - String16(""), String16("^max"), String16(val), NULL, NULL); - attr.hasErrors = true; - } - } - - if ((minIdx >= 0 || maxIdx >= 0) && (attr.type&ResTable_map::TYPE_INTEGER) == 0) { - attr.sourcePos.error("Tag <attr> must have format=integer attribute if using max or min\n"); - attr.hasErrors = true; - } - - ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization"); - if (l10nIdx >= 0) { - const uint16_t* str = block.getAttributeStringValue(l10nIdx, &len); - bool error; - uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error); - if (error) { - attr.sourcePos.error("Tag <attr> 'localization' attribute value \"%s\" not valid\n", - String8(str).string()); - attr.hasErrors = true; - } - attr.createIfNeeded(outTable); - if (!attr.hasErrors) { - char buf[11]; - sprintf(buf, "%d", l10n_required); - err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident, - String16(""), String16("^l10n"), String16(buf), NULL, NULL); - if (err != NO_ERROR) { - attr.hasErrors = true; - } - } - } - - String16 enumOrFlagsComment; - - while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::START_TAG) { - uint32_t localType = 0; - if (strcmp16(block.getElementName(&len), enum16.string()) == 0) { - localType = ResTable_map::TYPE_ENUM; - } else if (strcmp16(block.getElementName(&len), flag16.string()) == 0) { - localType = ResTable_map::TYPE_FLAGS; - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("Tag <%s> can not appear inside <attr>, only <enum> or <flag>\n", - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - - attr.createIfNeeded(outTable); - - if (attr.type == ResTable_map::TYPE_ANY) { - // No type was explicitly stated, so supplying enum tags - // implicitly creates an enum or flag. - attr.type = 0; - } - - if ((attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) == 0) { - // Wasn't originally specified as an enum, so update its type. - attr.type |= localType; - if (!attr.hasErrors) { - char numberStr[16]; - sprintf(numberStr, "%d", attr.type); - err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()), - myPackage, attr16, attr.ident, String16(""), - String16("^type"), String16(numberStr), NULL, NULL, true); - if (err != NO_ERROR) { - attr.hasErrors = true; - } - } - } else if ((uint32_t)(attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) != localType) { - if (localType == ResTable_map::TYPE_ENUM) { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("<enum> attribute can not be used inside a flags format\n"); - attr.hasErrors = true; - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("<flag> attribute can not be used inside a enum format\n"); - attr.hasErrors = true; - } - } - - String16 itemIdent; - ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name"); - if (itemIdentIdx >= 0) { - itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len)); - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("A 'name' attribute is required for <enum> or <flag>\n"); - attr.hasErrors = true; - } - - String16 value; - ssize_t valueIdx = block.indexOfAttribute(NULL, "value"); - if (valueIdx >= 0) { - value = String16(block.getAttributeStringValue(valueIdx, &len)); - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("A 'value' attribute is required for <enum> or <flag>\n"); - attr.hasErrors = true; - } - if (!attr.hasErrors && !ResTable::stringToInt(value.string(), value.size(), NULL)) { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("Tag <enum> or <flag> 'value' attribute must be a number," - " not \"%s\"\n", - String8(value).string()); - attr.hasErrors = true; - } - - // Make sure an id is defined for this enum/flag identifier... - if (!attr.hasErrors && !outTable->hasBagOrEntry(itemIdent, &id16, &myPackage)) { - err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()), - myPackage, id16, itemIdent, String16(), NULL); - if (err != NO_ERROR) { - attr.hasErrors = true; - } - } - - if (!attr.hasErrors) { - if (enumOrFlagsComment.size() == 0) { - enumOrFlagsComment.append(mayOrMust(attr.type, - ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)); - enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM) - ? String16(" be one of the following constant values.") - : String16(" be one or more (separated by '|') of the following constant values.")); - enumOrFlagsComment.append(String16("</p>\n<table>\n" - "<colgroup align=\"left\" />\n" - "<colgroup align=\"left\" />\n" - "<colgroup align=\"left\" />\n" - "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>")); - } - - enumOrFlagsComment.append(String16("\n<tr><td><code>")); - enumOrFlagsComment.append(itemIdent); - enumOrFlagsComment.append(String16("</code></td><td>")); - enumOrFlagsComment.append(value); - enumOrFlagsComment.append(String16("</td><td>")); - if (block.getComment(&len)) { - enumOrFlagsComment.append(String16(block.getComment(&len))); - } - enumOrFlagsComment.append(String16("</td></tr>")); - - err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()), - myPackage, - attr16, attr.ident, String16(""), - itemIdent, value, NULL, NULL, false, true); - if (err != NO_ERROR) { - attr.hasErrors = true; - } - } - } else if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), attr16.string()) == 0) { - break; - } - if ((attr.type&ResTable_map::TYPE_ENUM) != 0) { - if (strcmp16(block.getElementName(&len), enum16.string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("Found tag </%s> where </enum> is expected\n", - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - } else { - if (strcmp16(block.getElementName(&len), flag16.string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()) - .error("Found tag </%s> where </flag> is expected\n", - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - } - } - } - - if (!attr.hasErrors && attr.added) { - appendTypeInfo(outTable, myPackage, attr16, attr.ident, attr.type, gFormatFlags); - } - - if (!attr.hasErrors && enumOrFlagsComment.size() > 0) { - enumOrFlagsComment.append(String16("\n</table>")); - outTable->appendTypeComment(myPackage, attr16, attr.ident, enumOrFlagsComment); - } - - - return NO_ERROR; -} - -bool localeIsDefined(const ResTable_config& config) -{ - return config.locale == 0; -} - -status_t parseAndAddBag(Bundle* bundle, - const sp<AaptFile>& in, - ResXMLTree* block, - const ResTable_config& config, - const String16& myPackage, - const String16& curType, - const String16& ident, - const String16& parentIdent, - const String16& itemIdent, - int32_t curFormat, - bool isFormatted, - const String16& product, - bool pseudolocalize, - const bool overwrite, - ResourceTable* outTable) -{ - status_t err; - const String16 item16("item"); - - String16 str; - Vector<StringPool::entry_style_span> spans; - err = parseStyledString(bundle, in->getPrintableSource().string(), - block, item16, &str, &spans, isFormatted, - pseudolocalize); - if (err != NO_ERROR) { - return err; - } - - NOISY(printf("Adding resource bag entry l=%c%c c=%c%c orien=%d d=%d " - " pid=%s, bag=%s, id=%s: %s\n", - config.language[0], config.language[1], - config.country[0], config.country[1], - config.orientation, config.density, - String8(parentIdent).string(), - String8(ident).string(), - String8(itemIdent).string(), - String8(str).string())); - - err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()), - myPackage, curType, ident, parentIdent, itemIdent, str, - &spans, &config, overwrite, false, curFormat); - return err; -} - -/* - * Returns true if needle is one of the elements in the comma-separated list - * haystack, false otherwise. - */ -bool isInProductList(const String16& needle, const String16& haystack) { - const char16_t *needle2 = needle.string(); - const char16_t *haystack2 = haystack.string(); - size_t needlesize = needle.size(); - - while (*haystack2 != '\0') { - if (strncmp16(haystack2, needle2, needlesize) == 0) { - if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') { - return true; - } - } - - while (*haystack2 != '\0' && *haystack2 != ',') { - haystack2++; - } - if (*haystack2 == ',') { - haystack2++; - } - } - - return false; -} - -status_t parseAndAddEntry(Bundle* bundle, - const sp<AaptFile>& in, - ResXMLTree* block, - const ResTable_config& config, - const String16& myPackage, - const String16& curType, - const String16& ident, - const String16& curTag, - bool curIsStyled, - int32_t curFormat, - bool isFormatted, - const String16& product, - bool pseudolocalize, - const bool overwrite, - ResourceTable* outTable) -{ - status_t err; - - String16 str; - Vector<StringPool::entry_style_span> spans; - err = parseStyledString(bundle, in->getPrintableSource().string(), block, - curTag, &str, curIsStyled ? &spans : NULL, - isFormatted, pseudolocalize); - - if (err < NO_ERROR) { - return err; - } - - /* - * If a product type was specified on the command line - * and also in the string, and the two are not the same, - * return without adding the string. - */ - - const char *bundleProduct = bundle->getProduct(); - if (bundleProduct == NULL) { - bundleProduct = ""; - } - - if (product.size() != 0) { - /* - * If the command-line-specified product is empty, only "default" - * matches. Other variants are skipped. This is so generation - * of the R.java file when the product is not known is predictable. - */ - - if (bundleProduct[0] == '\0') { - if (strcmp16(String16("default").string(), product.string()) != 0) { - return NO_ERROR; - } - } else { - /* - * The command-line product is not empty. - * If the product for this string is on the command-line list, - * it matches. "default" also matches, but only if nothing - * else has matched already. - */ - - if (isInProductList(product, String16(bundleProduct))) { - ; - } else if (strcmp16(String16("default").string(), product.string()) == 0 && - !outTable->hasBagOrEntry(myPackage, curType, ident, config)) { - ; - } else { - return NO_ERROR; - } - } - } - - NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n", - config.language[0], config.language[1], - config.country[0], config.country[1], - config.orientation, config.density, - String8(ident).string(), String8(str).string())); - - err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()), - myPackage, curType, ident, str, &spans, &config, - false, curFormat, overwrite); - - return err; -} - -status_t compileResourceFile(Bundle* bundle, - const sp<AaptAssets>& assets, - const sp<AaptFile>& in, - const ResTable_config& defParams, - const bool overwrite, - ResourceTable* outTable) -{ - ResXMLTree block; - status_t err = parseXMLResource(in, &block, false, true); - if (err != NO_ERROR) { - return err; - } - - // Top-level tag. - const String16 resources16("resources"); - - // Identifier declaration tags. - const String16 declare_styleable16("declare-styleable"); - const String16 attr16("attr"); - - // Data creation organizational tags. - const String16 string16("string"); - const String16 drawable16("drawable"); - const String16 color16("color"); - const String16 bool16("bool"); - const String16 integer16("integer"); - const String16 dimen16("dimen"); - const String16 fraction16("fraction"); - const String16 style16("style"); - const String16 plurals16("plurals"); - const String16 array16("array"); - 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 java_symbol16("java-symbol"); - const String16 add_resource16("add-resource"); - const String16 skip16("skip"); - const String16 eat_comment16("eat-comment"); - - // Data creation tags. - const String16 bag16("bag"); - const String16 item16("item"); - - // Attribute type constants. - const String16 enum16("enum"); - - // plural values - const String16 other16("other"); - const String16 quantityOther16("^other"); - const String16 zero16("zero"); - const String16 quantityZero16("^zero"); - const String16 one16("one"); - const String16 quantityOne16("^one"); - const String16 two16("two"); - const String16 quantityTwo16("^two"); - const String16 few16("few"); - const String16 quantityFew16("^few"); - const String16 many16("many"); - const String16 quantityMany16("^many"); - - // 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; - do { - code = block.next(); - } while (code == ResXMLTree::START_NAMESPACE); - - size_t len; - if (code != ResXMLTree::START_TAG) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "No start tag found\n"); - return UNKNOWN_ERROR; - } - if (strcmp16(block.getElementName(&len), resources16.string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Invalid start tag %s\n", String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - - ResTable_config curParams(defParams); - - ResTable_config pseudoParams(curParams); - pseudoParams.language[0] = 'z'; - pseudoParams.language[1] = 'z'; - pseudoParams.country[0] = 'Z'; - pseudoParams.country[1] = 'Z'; - - while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::START_TAG) { - const String16* curTag = NULL; - String16 curType; - int32_t curFormat = ResTable_map::TYPE_ANY; - bool curIsBag = false; - bool curIsBagReplaceOnOverwrite = false; - bool curIsStyled = false; - bool curIsPseudolocalizable = false; - bool curIsFormatted = fileIsTranslatable; - bool localHasErrors = false; - - if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { - break; - } - } - } - continue; - - } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { - break; - } - } - } - continue; - - } else if (strcmp16(block.getElementName(&len), public16.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>\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>\n"); - hasErrors = localHasErrors = true; - } - name = String16(block.getAttributeStringValue(nameIdx, &len)); - - uint32_t ident = 0; - ssize_t identIdx = block.indexOfAttribute(NULL, "id"); - if (identIdx >= 0) { - const char16_t* identStr = block.getAttributeStringValue(identIdx, &len); - Res_value identValue; - if (!ResTable::stringToInt(identStr, len, &identValue)) { - srcPos.error("Given 'id' attribute is not an integer: %s\n", - String8(block.getAttributeStringValue(identIdx, &len)).string()); - hasErrors = localHasErrors = true; - } else { - ident = identValue.data; - nextPublicId.replaceValueFor(type, ident+1); - } - } 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.valueFor(type); - nextPublicId.replaceValueFor(type, ident+1); - } - - if (!localHasErrors) { - err = outTable->addPublic(srcPos, myPackage, type, name, ident); - if (err < NO_ERROR) { - hasErrors = localHasErrors = true; - } - } - if (!localHasErrors) { - sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); - if (symbols != NULL) { - symbols = symbols->addNestedSymbol(String8(type), srcPos); - } - if (symbols != NULL) { - symbols->makeSymbolPublic(String8(name), srcPos); - String16 comment( - block.getComment(&len) ? block.getComment(&len) : nulStr); - symbols->appendComment(String8(name), 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), public16.string()) == 0) { - break; - } - } - } - 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"); - if (pkgIdx < 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "A 'package' attribute is required for <private-symbols>\n"); - hasErrors = localHasErrors = true; - } - pkg = String16(block.getAttributeStringValue(pkgIdx, &len)); - if (!localHasErrors) { - assets->setSymbolsPrivatePackage(String8(pkg)); - } - - while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) { - break; - } - } - } - continue; - - } else if (strcmp16(block.getElementName(&len), java_symbol16.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>\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>\n"); - hasErrors = localHasErrors = true; - } - name = String16(block.getAttributeStringValue(nameIdx, &len)); - - sp<AaptSymbols> symbols = assets->getJavaSymbolsFor(String8("R")); - if (symbols != NULL) { - symbols = symbols->addNestedSymbol(String8(type), srcPos); - } - if (symbols != NULL) { - symbols->makeSymbolJavaSymbol(String8(name), srcPos); - String16 comment( - block.getComment(&len) ? block.getComment(&len) : nulStr); - symbols->appendComment(String8(name), 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), java_symbol16.string()) == 0) { - break; - } - } - } - continue; - - - } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) { - SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); - - String16 typeName; - ssize_t typeIdx = block.indexOfAttribute(NULL, "type"); - if (typeIdx < 0) { - srcPos.error("A 'type' attribute is required for <add-resource>\n"); - hasErrors = localHasErrors = true; - } - typeName = 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 <add-resource>\n"); - hasErrors = localHasErrors = true; - } - name = String16(block.getAttributeStringValue(nameIdx, &len)); - - outTable->canAddEntry(srcPos, myPackage, typeName, name); - - while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) { - break; - } - } - } - continue; - - } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) { - SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); - - String16 ident; - ssize_t identIdx = block.indexOfAttribute(NULL, "name"); - if (identIdx < 0) { - srcPos.error("A 'name' attribute is required for <declare-styleable>\n"); - hasErrors = localHasErrors = true; - } - ident = String16(block.getAttributeStringValue(identIdx, &len)); - - sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); - if (!localHasErrors) { - if (symbols != NULL) { - symbols = symbols->addNestedSymbol(String8("styleable"), srcPos); - } - sp<AaptSymbols> styleSymbols = symbols; - if (symbols != NULL) { - symbols = symbols->addNestedSymbol(String8(ident), srcPos); - } - if (symbols == NULL) { - srcPos.error("Unable to create symbols!\n"); - return UNKNOWN_ERROR; - } - - String16 comment( - block.getComment(&len) ? block.getComment(&len) : nulStr); - styleSymbols->appendComment(String8(ident), comment, srcPos); - } else { - symbols = NULL; - } - - while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::START_TAG) { - if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { - break; - } - } - } - continue; - } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { - break; - } - } - } - continue; - } else if (strcmp16(block.getElementName(&len), attr16.string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Tag <%s> can not appear inside <declare-styleable>, only <attr>\n", - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - - String16 comment( - block.getComment(&len) ? block.getComment(&len) : nulStr); - String16 itemIdent; - err = compileAttribute(in, block, myPackage, outTable, &itemIdent, true); - if (err != NO_ERROR) { - hasErrors = localHasErrors = true; - } - - if (symbols != NULL) { - SourcePos srcPos(String8(in->getPrintableSource()), block.getLineNumber()); - symbols->addSymbol(String8(itemIdent), 0, srcPos); - symbols->appendComment(String8(itemIdent), comment, srcPos); - //printf("Attribute %s comment: %s\n", String8(itemIdent).string(), - // String8(comment).string()); - } - } else if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) { - break; - } - - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Found tag </%s> where </attr> is expected\n", - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - } - continue; - - } else if (strcmp16(block.getElementName(&len), attr16.string()) == 0) { - err = compileAttribute(in, block, myPackage, outTable, NULL); - if (err != NO_ERROR) { - hasErrors = true; - } - continue; - - } else if (strcmp16(block.getElementName(&len), item16.string()) == 0) { - curTag = &item16; - ssize_t attri = block.indexOfAttribute(NULL, "type"); - if (attri >= 0) { - curType = String16(block.getAttributeStringValue(attri, &len)); - ssize_t formatIdx = block.indexOfAttribute(NULL, "format"); - if (formatIdx >= 0) { - String16 formatStr = String16(block.getAttributeStringValue( - formatIdx, &len)); - curFormat = parse_flags(formatStr.string(), formatStr.size(), - gFormatFlags); - if (curFormat == 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Tag <item> 'format' attribute value \"%s\" not valid\n", - String8(formatStr).string()); - hasErrors = localHasErrors = true; - } - } - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "A 'type' attribute is required for <item>\n"); - hasErrors = localHasErrors = true; - } - curIsStyled = true; - } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) { - // Note the existence and locale of every string we process - char rawLocale[16]; - curParams.getLocale(rawLocale); - String8 locale(rawLocale); - String16 name; - String16 translatable; - String16 formatted; - - size_t n = block.getAttributeCount(); - for (size_t i = 0; i < n; i++) { - size_t length; - const uint16_t* attr = block.getAttributeName(i, &length); - if (strcmp16(attr, name16.string()) == 0) { - 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" - " in locale '%s'\n", String8(name).string(), - bundle->getResourceSourceDirs()[0], - locale.string()); - // hasErrors = localHasErrors = true; - } else { - // Intentionally empty block: - // - // Don't add untranslatable strings to the localization table; that - // way if we later see localizations of them, they'll be flagged as - // having no default translation. - } - } else { - outTable->addLocalization(name, locale); - } - - if (formatted == false16) { - curIsFormatted = false; - } - } - - curTag = &string16; - curType = string16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING; - curIsStyled = true; - curIsPseudolocalizable = true; - } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) { - curTag = &drawable16; - curType = drawable16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR; - } else if (strcmp16(block.getElementName(&len), color16.string()) == 0) { - curTag = &color16; - curType = color16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR; - } else if (strcmp16(block.getElementName(&len), bool16.string()) == 0) { - curTag = &bool16; - curType = bool16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_BOOLEAN; - } else if (strcmp16(block.getElementName(&len), integer16.string()) == 0) { - curTag = &integer16; - curType = integer16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER; - } else if (strcmp16(block.getElementName(&len), dimen16.string()) == 0) { - curTag = &dimen16; - curType = dimen16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION; - } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) { - curTag = &fraction16; - curType = fraction16; - curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION; - } else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) { - curTag = &bag16; - curIsBag = true; - ssize_t attri = block.indexOfAttribute(NULL, "type"); - if (attri >= 0) { - curType = String16(block.getAttributeStringValue(attri, &len)); - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "A 'type' attribute is required for <bag>\n"); - hasErrors = localHasErrors = true; - } - } else if (strcmp16(block.getElementName(&len), style16.string()) == 0) { - curTag = &style16; - curType = style16; - curIsBag = true; - } else if (strcmp16(block.getElementName(&len), plurals16.string()) == 0) { - curTag = &plurals16; - curType = plurals16; - curIsBag = true; - } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) { - curTag = &array16; - curType = array16; - curIsBag = true; - curIsBagReplaceOnOverwrite = true; - ssize_t formatIdx = block.indexOfAttribute(NULL, "format"); - if (formatIdx >= 0) { - String16 formatStr = String16(block.getAttributeStringValue( - formatIdx, &len)); - curFormat = parse_flags(formatStr.string(), formatStr.size(), - gFormatFlags); - if (curFormat == 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Tag <array> 'format' attribute value \"%s\" not valid\n", - String8(formatStr).string()); - hasErrors = localHasErrors = true; - } - } - } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) { - // Check whether these strings need valid formats. - // (simplified form of what string16 does above) - size_t n = block.getAttributeCount(); - for (size_t i = 0; i < n; i++) { - size_t length; - const uint16_t* attr = block.getAttributeName(i, &length); - if (strcmp16(attr, translatable16.string()) == 0 - || strcmp16(attr, formatted16.string()) == 0) { - const uint16_t* value = block.getAttributeStringValue(i, &length); - if (strcmp16(value, false16.string()) == 0) { - curIsFormatted = false; - break; - } - } - } - - curTag = &string_array16; - 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", - String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - - String16 ident; - ssize_t identIdx = block.indexOfAttribute(NULL, "name"); - if (identIdx >= 0) { - ident = String16(block.getAttributeStringValue(identIdx, &len)); - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "A 'name' attribute is required for <%s>\n", - String8(*curTag).string()); - hasErrors = localHasErrors = true; - } - - String16 product; - identIdx = block.indexOfAttribute(NULL, "product"); - if (identIdx >= 0) { - product = String16(block.getAttributeStringValue(identIdx, &len)); - } - - String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr); - - if (curIsBag) { - // Figure out the parent of this bag... - String16 parentIdent; - ssize_t parentIdentIdx = block.indexOfAttribute(NULL, "parent"); - if (parentIdentIdx >= 0) { - parentIdent = String16(block.getAttributeStringValue(parentIdentIdx, &len)); - } else { - ssize_t sep = ident.findLast('.'); - if (sep >= 0) { - parentIdent.setTo(ident, sep); - } - } - - if (!localHasErrors) { - err = outTable->startBag(SourcePos(in->getPrintableSource(), - block.getLineNumber()), myPackage, curType, ident, - parentIdent, &curParams, - overwrite, curIsBagReplaceOnOverwrite); - if (err != NO_ERROR) { - hasErrors = localHasErrors = true; - } - } - - ssize_t elmIndex = 0; - char elmIndexStr[14]; - while ((code=block.next()) != ResXMLTree::END_DOCUMENT - && code != ResXMLTree::BAD_DOCUMENT) { - - if (code == ResXMLTree::START_TAG) { - if (strcmp16(block.getElementName(&len), item16.string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Tag <%s> can not appear inside <%s>, only <item>\n", - String8(block.getElementName(&len)).string(), - String8(*curTag).string()); - return UNKNOWN_ERROR; - } - - String16 itemIdent; - if (curType == array16) { - sprintf(elmIndexStr, "^index_%d", (int)elmIndex++); - itemIdent = String16(elmIndexStr); - } else if (curType == plurals16) { - ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "quantity"); - if (itemIdentIdx >= 0) { - String16 quantity16(block.getAttributeStringValue(itemIdentIdx, &len)); - if (quantity16 == other16) { - itemIdent = quantityOther16; - } - else if (quantity16 == zero16) { - itemIdent = quantityZero16; - } - else if (quantity16 == one16) { - itemIdent = quantityOne16; - } - else if (quantity16 == two16) { - itemIdent = quantityTwo16; - } - else if (quantity16 == few16) { - itemIdent = quantityFew16; - } - else if (quantity16 == many16) { - itemIdent = quantityMany16; - } - else { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Illegal 'quantity' attribute is <item> inside <plurals>\n"); - hasErrors = localHasErrors = true; - } - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "A 'quantity' attribute is required for <item> inside <plurals>\n"); - hasErrors = localHasErrors = true; - } - } else { - ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name"); - if (itemIdentIdx >= 0) { - itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len)); - } else { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "A 'name' attribute is required for <item>\n"); - hasErrors = localHasErrors = true; - } - } - - ResXMLParser::ResXMLPosition parserPosition; - block.getPosition(&parserPosition); - - err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType, - ident, parentIdent, itemIdent, curFormat, curIsFormatted, - product, false, overwrite, outTable); - if (err == NO_ERROR) { - if (curIsPseudolocalizable && localeIsDefined(curParams) - && bundle->getPseudolocalize()) { - // pseudolocalize here -#if 1 - block.setPosition(parserPosition); - err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage, - curType, ident, parentIdent, itemIdent, curFormat, - curIsFormatted, product, true, overwrite, outTable); -#endif - } - } - if (err != NO_ERROR) { - hasErrors = localHasErrors = true; - } - } else if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), curTag->string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Found tag </%s> where </%s> is expected\n", - String8(block.getElementName(&len)).string(), - String8(*curTag).string()); - return UNKNOWN_ERROR; - } - break; - } - } - } else { - ResXMLParser::ResXMLPosition parserPosition; - block.getPosition(&parserPosition); - - err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, - *curTag, curIsStyled, curFormat, curIsFormatted, - product, false, overwrite, outTable); - - if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? - hasErrors = localHasErrors = true; - } - else if (err == NO_ERROR) { - if (curIsPseudolocalizable && localeIsDefined(curParams) - && bundle->getPseudolocalize()) { - // pseudolocalize here - block.setPosition(parserPosition); - err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, - ident, *curTag, curIsStyled, curFormat, - curIsFormatted, product, - true, overwrite, outTable); - if (err != NO_ERROR) { - hasErrors = localHasErrors = true; - } - } - } - } - -#if 0 - if (comment.size() > 0) { - printf("Comment for @%s:%s/%s: %s\n", String8(myPackage).string(), - String8(curType).string(), String8(ident).string(), - String8(comment).string()); - } -#endif - if (!localHasErrors) { - outTable->appendComment(myPackage, curType, ident, comment, false); - } - } - else if (code == ResXMLTree::END_TAG) { - if (strcmp16(block.getElementName(&len), resources16.string()) != 0) { - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Unexpected end tag %s\n", String8(block.getElementName(&len)).string()); - return UNKNOWN_ERROR; - } - } - else if (code == ResXMLTree::START_NAMESPACE || code == ResXMLTree::END_NAMESPACE) { - } - else if (code == ResXMLTree::TEXT) { - if (isWhitespace(block.getText(&len))) { - continue; - } - SourcePos(in->getPrintableSource(), block.getLineNumber()).error( - "Found text \"%s\" where item tag is expected\n", - String8(block.getText(&len)).string()); - return UNKNOWN_ERROR; - } - } - - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage) - : mAssetsPackage(assetsPackage), mNextPackageId(1), mHaveAppPackage(false), - mIsAppPackage(!bundle->getExtending()), - mNumLocal(0), - mBundle(bundle) -{ -} - -status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets) -{ - status_t err = assets->buildIncludedResources(bundle); - if (err != NO_ERROR) { - return err; - } - - // For future reference to included resources. - mAssets = assets; - - const ResTable& incl = assets->getIncludedResources(); - - // Retrieve all the packages. - const size_t N = incl.getBasePackageCount(); - for (size_t phase=0; phase<2; phase++) { - for (size_t i=0; i<N; i++) { - String16 name(incl.getBasePackageName(i)); - uint32_t id = incl.getBasePackageId(i); - // First time through: only add base packages (id - // is not 0); second time through add the other - // packages. - if (phase != 0) { - if (id != 0) { - // Skip base packages -- already one. - id = 0; - } else { - // Assign a dynamic id. - id = mNextPackageId; - } - } else if (id != 0) { - if (id == 127) { - if (mHaveAppPackage) { - fprintf(stderr, "Included resources have two application packages!\n"); - return UNKNOWN_ERROR; - } - mHaveAppPackage = true; - } - if (mNextPackageId > id) { - fprintf(stderr, "Included base package ID %d already in use!\n", id); - return UNKNOWN_ERROR; - } - } - if (id != 0) { - NOISY(printf("Including package %s with ID=%d\n", - String8(name).string(), id)); - sp<Package> p = new Package(name, id); - mPackages.add(name, p); - mOrderedPackages.add(p); - - if (id >= mNextPackageId) { - mNextPackageId = id+1; - } - } - } - } - - // Every resource table always has one first entry, the bag attributes. - const SourcePos unknown(String8("????"), 0); - sp<Type> attr = getType(mAssetsPackage, String16("attr"), unknown); - - return NO_ERROR; -} - -status_t ResourceTable::addPublic(const SourcePos& sourcePos, - const String16& package, - const String16& type, - const String16& name, - const uint32_t ident) -{ - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size()); - if (rid != 0) { - sourcePos.error("Error declaring public resource %s/%s for included package %s\n", - String8(type).string(), String8(name).string(), - String8(package).string()); - return UNKNOWN_ERROR; - } - - sp<Type> t = getType(package, type, sourcePos); - if (t == NULL) { - return UNKNOWN_ERROR; - } - return t->addPublic(sourcePos, name, ident); -} - -status_t ResourceTable::addEntry(const SourcePos& sourcePos, - const String16& package, - const String16& type, - const String16& name, - const String16& value, - const Vector<StringPool::entry_style_span>* style, - const ResTable_config* params, - const bool doSetIndex, - const int32_t format, - const bool overwrite) -{ - // Check for adding entries in other packages... for now we do - // nothing. We need to do the right thing here to support skinning. - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size()); - if (rid != 0) { - return NO_ERROR; - } - -#if 0 - if (name == String16("left")) { - printf("Adding entry left: file=%s, line=%d, type=%s, value=%s\n", - sourcePos.file.string(), sourcePos.line, String8(type).string(), - String8(value).string()); - } -#endif - - sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite, - params, doSetIndex); - if (e == NULL) { - return UNKNOWN_ERROR; - } - status_t err = e->setItem(sourcePos, value, style, format, overwrite); - if (err == NO_ERROR) { - mNumLocal++; - } - return err; -} - -status_t ResourceTable::startBag(const SourcePos& sourcePos, - const String16& package, - const String16& type, - const String16& name, - const String16& bagParent, - const ResTable_config* params, - bool overlay, - bool replace, bool isId) -{ - status_t result = NO_ERROR; - - // Check for adding entries in other packages... for now we do - // nothing. We need to do the right thing here to support skinning. - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size()); - if (rid != 0) { - return NO_ERROR; - } - -#if 0 - if (name == String16("left")) { - printf("Adding bag left: file=%s, line=%d, type=%s\n", - sourcePos.file.striing(), sourcePos.line, String8(type).string()); - } -#endif - if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) { - bool canAdd = false; - sp<Package> p = mPackages.valueFor(package); - if (p != NULL) { - sp<Type> t = p->getTypes().valueFor(type); - if (t != NULL) { - if (t->getCanAddEntries().indexOf(name) >= 0) { - canAdd = true; - } - } - } - if (!canAdd) { - sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n", - String8(name).string()); - return UNKNOWN_ERROR; - } - } - sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params); - if (e == NULL) { - return UNKNOWN_ERROR; - } - - // If a parent is explicitly specified, set it. - if (bagParent.size() > 0) { - e->setParent(bagParent); - } - - if ((result = e->makeItABag(sourcePos)) != NO_ERROR) { - return result; - } - - if (overlay && replace) { - return e->emptyBag(sourcePos); - } - return result; -} - -status_t ResourceTable::addBag(const SourcePos& sourcePos, - const String16& package, - const String16& type, - const String16& name, - const String16& bagParent, - const String16& bagKey, - const String16& value, - const Vector<StringPool::entry_style_span>* style, - const ResTable_config* params, - bool replace, bool isId, const int32_t format) -{ - // Check for adding entries in other packages... for now we do - // nothing. We need to do the right thing here to support skinning. - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size()); - if (rid != 0) { - return NO_ERROR; - } - -#if 0 - if (name == String16("left")) { - printf("Adding bag left: file=%s, line=%d, type=%s\n", - sourcePos.file.striing(), sourcePos.line, String8(type).string()); - } -#endif - sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params); - if (e == NULL) { - return UNKNOWN_ERROR; - } - - // If a parent is explicitly specified, set it. - if (bagParent.size() > 0) { - e->setParent(bagParent); - } - - const bool first = e->getBag().indexOfKey(bagKey) < 0; - status_t err = e->addToBag(sourcePos, bagKey, value, style, replace, isId, format); - if (err == NO_ERROR && first) { - mNumLocal++; - } - return err; -} - -bool ResourceTable::hasBagOrEntry(const String16& package, - const String16& type, - const String16& name) const -{ - // First look for this in the included resources... - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size()); - if (rid != 0) { - return true; - } - - sp<Package> p = mPackages.valueFor(package); - if (p != NULL) { - sp<Type> t = p->getTypes().valueFor(type); - if (t != NULL) { - sp<ConfigList> c = t->getConfigs().valueFor(name); - if (c != NULL) return true; - } - } - - return false; -} - -bool ResourceTable::hasBagOrEntry(const String16& package, - const String16& type, - const String16& name, - const ResTable_config& config) const -{ - // First look for this in the included resources... - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size()); - if (rid != 0) { - return true; - } - - sp<Package> p = mPackages.valueFor(package); - if (p != NULL) { - sp<Type> t = p->getTypes().valueFor(type); - if (t != NULL) { - sp<ConfigList> c = t->getConfigs().valueFor(name); - if (c != NULL) { - sp<Entry> e = c->getEntries().valueFor(config); - if (e != NULL) { - return true; - } - } - } - } - - return false; -} - -bool ResourceTable::hasBagOrEntry(const String16& ref, - const String16* defType, - const String16* defPackage) -{ - String16 package, type, name; - if (!ResTable::expandResourceRef(ref.string(), ref.size(), &package, &type, &name, - defType, defPackage ? defPackage:&mAssetsPackage, NULL)) { - return false; - } - return hasBagOrEntry(package, type, name); -} - -bool ResourceTable::appendComment(const String16& package, - const String16& type, - const String16& name, - const String16& comment, - bool onlyIfEmpty) -{ - if (comment.size() <= 0) { - return true; - } - - sp<Package> p = mPackages.valueFor(package); - if (p != NULL) { - sp<Type> t = p->getTypes().valueFor(type); - if (t != NULL) { - sp<ConfigList> c = t->getConfigs().valueFor(name); - if (c != NULL) { - c->appendComment(comment, onlyIfEmpty); - return true; - } - } - } - return false; -} - -bool ResourceTable::appendTypeComment(const String16& package, - const String16& type, - const String16& name, - const String16& comment) -{ - if (comment.size() <= 0) { - return true; - } - - sp<Package> p = mPackages.valueFor(package); - if (p != NULL) { - sp<Type> t = p->getTypes().valueFor(type); - if (t != NULL) { - sp<ConfigList> c = t->getConfigs().valueFor(name); - if (c != NULL) { - c->appendTypeComment(comment); - return true; - } - } - } - return false; -} - -void ResourceTable::canAddEntry(const SourcePos& pos, - const String16& package, const String16& type, const String16& name) -{ - sp<Type> t = getType(package, type, pos); - if (t != NULL) { - t->canAddEntry(name); - } -} - -size_t ResourceTable::size() const { - return mPackages.size(); -} - -size_t ResourceTable::numLocalResources() const { - return mNumLocal; -} - -bool ResourceTable::hasResources() const { - return mNumLocal > 0; -} - -sp<AaptFile> ResourceTable::flatten(Bundle* bundle) -{ - sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8()); - status_t err = flatten(bundle, data); - return err == NO_ERROR ? data : NULL; -} - -inline uint32_t ResourceTable::getResId(const sp<Package>& p, - const sp<Type>& t, - uint32_t nameId) -{ - return makeResId(p->getAssignedId(), t->getIndex(), nameId); -} - -uint32_t ResourceTable::getResId(const String16& package, - const String16& type, - const String16& name, - bool onlyPublic) const -{ - uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic); - if (id != 0) return id; // cache hit - - sp<Package> p = mPackages.valueFor(package); - if (p == NULL) return 0; - - // First look for this in the included resources... - uint32_t specFlags = 0; - uint32_t rid = mAssets->getIncludedResources() - .identifierForName(name.string(), name.size(), - type.string(), type.size(), - package.string(), package.size(), - &specFlags); - if (rid != 0) { - if (onlyPublic) { - if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) { - return 0; - } - } - - if (Res_INTERNALID(rid)) { - return ResourceIdCache::store(package, type, name, onlyPublic, rid); - } - return ResourceIdCache::store(package, type, name, onlyPublic, - Res_MAKEID(p->getAssignedId()-1, Res_GETTYPE(rid), Res_GETENTRY(rid))); - } - - sp<Type> t = p->getTypes().valueFor(type); - if (t == NULL) return 0; - sp<ConfigList> c = t->getConfigs().valueFor(name); - if (c == NULL) return 0; - int32_t ei = c->getEntryIndex(); - if (ei < 0) return 0; - - return ResourceIdCache::store(package, type, name, onlyPublic, - getResId(p, t, ei)); -} - -uint32_t ResourceTable::getResId(const String16& ref, - const String16* defType, - const String16* defPackage, - const char** outErrorMsg, - bool onlyPublic) const -{ - String16 package, type, name; - bool refOnlyPublic = true; - if (!ResTable::expandResourceRef( - ref.string(), ref.size(), &package, &type, &name, - defType, defPackage ? defPackage:&mAssetsPackage, - outErrorMsg, &refOnlyPublic)) { - NOISY(printf("Expanding resource: ref=%s\n", - String8(ref).string())); - NOISY(printf("Expanding resource: defType=%s\n", - defType ? String8(*defType).string() : "NULL")); - NOISY(printf("Expanding resource: defPackage=%s\n", - defPackage ? String8(*defPackage).string() : "NULL")); - NOISY(printf("Expanding resource: ref=%s\n", String8(ref).string())); - NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=0\n", - String8(package).string(), String8(type).string(), - String8(name).string())); - return 0; - } - uint32_t res = getResId(package, type, name, onlyPublic && refOnlyPublic); - NOISY(printf("Expanded resource: p=%s, t=%s, n=%s, res=%d\n", - String8(package).string(), String8(type).string(), - String8(name).string(), res)); - if (res == 0) { - if (outErrorMsg) - *outErrorMsg = "No resource found that matches the given name"; - } - return res; -} - -bool ResourceTable::isValidResourceName(const String16& s) -{ - const char16_t* p = s.string(); - bool first = true; - while (*p) { - if ((*p >= 'a' && *p <= 'z') - || (*p >= 'A' && *p <= 'Z') - || *p == '_' - || (!first && *p >= '0' && *p <= '9')) { - first = false; - p++; - continue; - } - return false; - } - return true; -} - -bool ResourceTable::stringToValue(Res_value* outValue, StringPool* pool, - const String16& str, - bool preserveSpaces, bool coerceType, - uint32_t attrID, - const Vector<StringPool::entry_style_span>* style, - String16* outStr, void* accessorCookie, - uint32_t attrType, const String8* configTypeName, - const ConfigDescription* config) -{ - String16 finalStr; - - bool res = true; - if (style == NULL || style->size() == 0) { - // Text is not styled so it can be any type... let's figure it out. - res = mAssets->getIncludedResources() - .stringToValue(outValue, &finalStr, str.string(), str.size(), preserveSpaces, - coerceType, attrID, NULL, &mAssetsPackage, this, - accessorCookie, attrType); - } else { - // Styled text can only be a string, and while collecting the style - // information we have already processed that string! - outValue->size = sizeof(Res_value); - outValue->res0 = 0; - outValue->dataType = outValue->TYPE_STRING; - outValue->data = 0; - finalStr = str; - } - - if (!res) { - return false; - } - - if (outValue->dataType == outValue->TYPE_STRING) { - // Should do better merging styles. - if (pool) { - String8 configStr; - if (config != NULL) { - configStr = config->toString(); - } else { - configStr = "(null)"; - } - NOISY(printf("Adding to pool string style #%d config %s: %s\n", - style != NULL ? style->size() : 0, - configStr.string(), String8(finalStr).string())); - if (style != NULL && style->size() > 0) { - outValue->data = pool->add(finalStr, *style, configTypeName, config); - } else { - outValue->data = pool->add(finalStr, true, configTypeName, config); - } - } else { - // Caller will fill this in later. - outValue->data = 0; - } - - if (outStr) { - *outStr = finalStr; - } - - } - - return true; -} - -uint32_t ResourceTable::getCustomResource( - const String16& package, const String16& type, const String16& name) const -{ - //printf("getCustomResource: %s %s %s\n", String8(package).string(), - // String8(type).string(), String8(name).string()); - sp<Package> p = mPackages.valueFor(package); - if (p == NULL) return 0; - sp<Type> t = p->getTypes().valueFor(type); - if (t == NULL) return 0; - sp<ConfigList> c = t->getConfigs().valueFor(name); - if (c == NULL) return 0; - int32_t ei = c->getEntryIndex(); - if (ei < 0) return 0; - return getResId(p, t, ei); -} - -uint32_t ResourceTable::getCustomResourceWithCreation( - const String16& package, const String16& type, const String16& name, - const bool createIfNotFound) -{ - uint32_t resId = getCustomResource(package, type, name); - if (resId != 0 || !createIfNotFound) { - return resId; - } - String16 value("false"); - - status_t status = addEntry(mCurrentXmlPos, package, type, name, value, NULL, NULL, true); - if (status == NO_ERROR) { - resId = getResId(package, type, name); - return resId; - } - return 0; -} - -uint32_t ResourceTable::getRemappedPackage(uint32_t origPackage) const -{ - return origPackage; -} - -bool ResourceTable::getAttributeType(uint32_t attrID, uint32_t* outType) -{ - //printf("getAttributeType #%08x\n", attrID); - Res_value value; - if (getItemValue(attrID, ResTable_map::ATTR_TYPE, &value)) { - //printf("getAttributeType #%08x (%s): #%08x\n", attrID, - // String8(getEntry(attrID)->getName()).string(), value.data); - *outType = value.data; - return true; - } - return false; -} - -bool ResourceTable::getAttributeMin(uint32_t attrID, uint32_t* outMin) -{ - //printf("getAttributeMin #%08x\n", attrID); - Res_value value; - if (getItemValue(attrID, ResTable_map::ATTR_MIN, &value)) { - *outMin = value.data; - return true; - } - return false; -} - -bool ResourceTable::getAttributeMax(uint32_t attrID, uint32_t* outMax) -{ - //printf("getAttributeMax #%08x\n", attrID); - Res_value value; - if (getItemValue(attrID, ResTable_map::ATTR_MAX, &value)) { - *outMax = value.data; - return true; - } - return false; -} - -uint32_t ResourceTable::getAttributeL10N(uint32_t attrID) -{ - //printf("getAttributeL10N #%08x\n", attrID); - Res_value value; - if (getItemValue(attrID, ResTable_map::ATTR_L10N, &value)) { - return value.data; - } - return ResTable_map::L10N_NOT_REQUIRED; -} - -bool ResourceTable::getLocalizationSetting() -{ - return mBundle->getRequireLocalization(); -} - -void ResourceTable::reportError(void* accessorCookie, const char* fmt, ...) -{ - if (accessorCookie != NULL && fmt != NULL) { - AccessorCookie* ac = (AccessorCookie*)accessorCookie; - int retval=0; - char buf[1024]; - va_list ap; - va_start(ap, fmt); - retval = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n", - buf, ac->attr.string(), ac->value.string()); - } -} - -bool ResourceTable::getAttributeKeys( - uint32_t attrID, Vector<String16>* outKeys) -{ - sp<const Entry> e = getEntry(attrID); - if (e != NULL) { - const size_t N = e->getBag().size(); - for (size_t i=0; i<N; i++) { - const String16& key = e->getBag().keyAt(i); - if (key.size() > 0 && key.string()[0] != '^') { - outKeys->add(key); - } - } - return true; - } - return false; -} - -bool ResourceTable::getAttributeEnum( - uint32_t attrID, const char16_t* name, size_t nameLen, - Res_value* outValue) -{ - //printf("getAttributeEnum #%08x %s\n", attrID, String8(name, nameLen).string()); - String16 nameStr(name, nameLen); - sp<const Entry> e = getEntry(attrID); - if (e != NULL) { - const size_t N = e->getBag().size(); - for (size_t i=0; i<N; i++) { - //printf("Comparing %s to %s\n", String8(name, nameLen).string(), - // String8(e->getBag().keyAt(i)).string()); - if (e->getBag().keyAt(i) == nameStr) { - return getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, outValue); - } - } - } - return false; -} - -bool ResourceTable::getAttributeFlags( - uint32_t attrID, const char16_t* name, size_t nameLen, - Res_value* outValue) -{ - outValue->dataType = Res_value::TYPE_INT_HEX; - outValue->data = 0; - - //printf("getAttributeFlags #%08x %s\n", attrID, String8(name, nameLen).string()); - String16 nameStr(name, nameLen); - sp<const Entry> e = getEntry(attrID); - if (e != NULL) { - const size_t N = e->getBag().size(); - - const char16_t* end = name + nameLen; - const char16_t* pos = name; - while (pos < end) { - const char16_t* start = pos; - while (pos < end && *pos != '|') { - pos++; - } - - String16 nameStr(start, pos-start); - size_t i; - for (i=0; i<N; i++) { - //printf("Comparing \"%s\" to \"%s\"\n", String8(nameStr).string(), - // String8(e->getBag().keyAt(i)).string()); - if (e->getBag().keyAt(i) == nameStr) { - Res_value val; - bool got = getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, &val); - if (!got) { - return false; - } - //printf("Got value: 0x%08x\n", val.data); - outValue->data |= val.data; - break; - } - } - - if (i >= N) { - // Didn't find this flag identifier. - return false; - } - pos++; - } - - return true; - } - return false; -} - -status_t ResourceTable::assignResourceIds() -{ - const size_t N = mOrderedPackages.size(); - size_t pi; - status_t firstError = NO_ERROR; - - // First generate all bag attributes and assign indices. - for (pi=0; pi<N; pi++) { - sp<Package> p = mOrderedPackages.itemAt(pi); - if (p == NULL || p->getTypes().size() == 0) { - // Empty, skip! - continue; - } - - status_t err = p->applyPublicTypeOrder(); - if (err != NO_ERROR && firstError == NO_ERROR) { - firstError = err; - } - - // Generate attributes... - const size_t N = p->getOrderedTypes().size(); - size_t ti; - for (ti=0; ti<N; ti++) { - sp<Type> t = p->getOrderedTypes().itemAt(ti); - if (t == NULL) { - continue; - } - const size_t N = t->getOrderedConfigs().size(); - for (size_t ci=0; ci<N; ci++) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); - if (c == NULL) { - continue; - } - const size_t N = c->getEntries().size(); - for (size_t ei=0; ei<N; ei++) { - sp<Entry> e = c->getEntries().valueAt(ei); - if (e == NULL) { - continue; - } - status_t err = e->generateAttributes(this, p->getName()); - if (err != NO_ERROR && firstError == NO_ERROR) { - firstError = err; - } - } - } - } - - const SourcePos unknown(String8("????"), 0); - sp<Type> attr = p->getType(String16("attr"), unknown); - - // Assign indices... - for (ti=0; ti<N; ti++) { - sp<Type> t = p->getOrderedTypes().itemAt(ti); - if (t == NULL) { - continue; - } - err = t->applyPublicEntryOrder(); - if (err != NO_ERROR && firstError == NO_ERROR) { - firstError = err; - } - - const size_t N = t->getOrderedConfigs().size(); - t->setIndex(ti+1); - - LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t, - "First type is not attr!"); - - for (size_t ei=0; ei<N; ei++) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(ei); - if (c == NULL) { - continue; - } - c->setEntryIndex(ei); - } - } - - // Assign resource IDs to keys in bags... - for (ti=0; ti<N; ti++) { - sp<Type> t = p->getOrderedTypes().itemAt(ti); - if (t == NULL) { - continue; - } - const size_t N = t->getOrderedConfigs().size(); - for (size_t ci=0; ci<N; ci++) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); - //printf("Ordered config #%d: %p\n", ci, c.get()); - const size_t N = c->getEntries().size(); - for (size_t ei=0; ei<N; ei++) { - sp<Entry> e = c->getEntries().valueAt(ei); - if (e == NULL) { - continue; - } - status_t err = e->assignResourceIds(this, p->getName()); - if (err != NO_ERROR && firstError == NO_ERROR) { - firstError = err; - } - } - } - } - } - return firstError; -} - -status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) { - const size_t N = mOrderedPackages.size(); - size_t pi; - - for (pi=0; pi<N; pi++) { - sp<Package> p = mOrderedPackages.itemAt(pi); - if (p->getTypes().size() == 0) { - // Empty, skip! - continue; - } - - const size_t N = p->getOrderedTypes().size(); - size_t ti; - - for (ti=0; ti<N; ti++) { - sp<Type> t = p->getOrderedTypes().itemAt(ti); - if (t == NULL) { - continue; - } - const size_t N = t->getOrderedConfigs().size(); - sp<AaptSymbols> typeSymbols; - typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos()); - for (size_t ci=0; ci<N; ci++) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); - if (c == NULL) { - continue; - } - uint32_t rid = getResId(p, t, ci); - if (rid == 0) { - return UNKNOWN_ERROR; - } - if (Res_GETPACKAGE(rid) == (size_t)(p->getAssignedId()-1)) { - typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos()); - - String16 comment(c->getComment()); - typeSymbols->appendComment(String8(c->getName()), comment, c->getPos()); - //printf("Type symbol %s comment: %s\n", String8(e->getName()).string(), - // String8(comment).string()); - comment = c->getTypeComment(); - typeSymbols->appendTypeComment(String8(c->getName()), comment); - } else { -#if 0 - printf("**** NO MATCH: 0x%08x vs 0x%08x\n", - Res_GETPACKAGE(rid), p->getAssignedId()); -#endif - } - } - } - } - return NO_ERROR; -} - - -void -ResourceTable::addLocalization(const String16& name, const String8& locale) -{ - mLocalizations[name].insert(locale); -} - - -/*! - * Flag various sorts of localization problems. '+' indicates checks already implemented; - * '-' indicates checks that will be implemented in the future. - * - * + A localized string for which no default-locale version exists => warning - * + A string for which no version in an explicitly-requested locale exists => warning - * + A localized translation of an translateable="false" string => warning - * - A localized string not provided in every locale used by the table - */ -status_t -ResourceTable::validateLocalizations(void) -{ - status_t err = NO_ERROR; - const String8 defaultLocale; - - // For all strings... - for (map<String16, set<String8> >::iterator nameIter = mLocalizations.begin(); - nameIter != mLocalizations.end(); - nameIter++) { - const set<String8>& configSet = nameIter->second; // naming convenience - - // Look for strings with no default localization - if (configSet.count(defaultLocale) == 0) { - fprintf(stdout, "aapt: warning: string '%s' has no default translation in %s; found:", - String8(nameIter->first).string(), mBundle->getResourceSourceDirs()[0]); - for (set<String8>::const_iterator locales = configSet.begin(); - locales != configSet.end(); - locales++) { - fprintf(stdout, " %s", (*locales).string()); - } - fprintf(stdout, "\n"); - // !!! TODO: throw an error here in some circumstances - } - - // Check that all requested localizations are present for this string - if (mBundle->getConfigurations() != NULL && mBundle->getRequireLocalization()) { - const char* allConfigs = mBundle->getConfigurations(); - const char* start = allConfigs; - const char* comma; - - do { - String8 config; - comma = strchr(start, ','); - if (comma != NULL) { - config.setTo(start, comma - start); - start = comma + 1; - } else { - config.setTo(start); - } - - // don't bother with the pseudolocale "zz_ZZ" - if (config != "zz_ZZ") { - if (configSet.find(config) == configSet.end()) { - // okay, no specific localization found. it's possible that we are - // requiring a specific regional localization [e.g. de_DE] but there is an - // available string in the generic language localization [e.g. de]; - // consider that string to have fulfilled the localization requirement. - String8 region(config.string(), 2); - if (configSet.find(region) == configSet.end()) { - if (configSet.count(defaultLocale) == 0) { - fprintf(stdout, "aapt: warning: " - "**** string '%s' has no default or required localization " - "for '%s' in %s\n", - String8(nameIter->first).string(), - config.string(), - mBundle->getResourceSourceDirs()[0]); - } - } - } - } - } while (comma != NULL); - } - } - - return err; -} - -status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest) -{ - ResourceFilter filter; - status_t err = filter.parse(bundle->getConfigurations()); - if (err != NO_ERROR) { - return err; - } - - const ConfigDescription nullConfig; - - const size_t N = mOrderedPackages.size(); - size_t pi; - - const static String16 mipmap16("mipmap"); - - bool useUTF8 = !bundle->getUTF16StringsOption(); - - // Iterate through all data, collecting all values (strings, - // references, etc). - StringPool valueStrings(useUTF8); - Vector<sp<Entry> > allEntries; - for (pi=0; pi<N; pi++) { - sp<Package> p = mOrderedPackages.itemAt(pi); - if (p->getTypes().size() == 0) { - // Empty, skip! - continue; - } - - StringPool typeStrings(useUTF8); - StringPool keyStrings(useUTF8); - - const size_t N = p->getOrderedTypes().size(); - for (size_t ti=0; ti<N; ti++) { - sp<Type> t = p->getOrderedTypes().itemAt(ti); - if (t == NULL) { - typeStrings.add(String16("<empty>"), false); - continue; - } - const String16 typeName(t->getName()); - typeStrings.add(typeName, false); - - // This is a hack to tweak the sorting order of the final strings, - // to put stuff that is generally not language-specific first. - String8 configTypeName(typeName); - if (configTypeName == "drawable" || configTypeName == "layout" - || configTypeName == "color" || configTypeName == "anim" - || configTypeName == "interpolator" || configTypeName == "animator" - || configTypeName == "xml" || configTypeName == "menu" - || configTypeName == "mipmap" || configTypeName == "raw") { - configTypeName = "1complex"; - } else { - configTypeName = "2value"; - } - - const bool filterable = (typeName != mipmap16); - - const size_t N = t->getOrderedConfigs().size(); - for (size_t ci=0; ci<N; ci++) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); - if (c == NULL) { - continue; - } - const size_t N = c->getEntries().size(); - for (size_t ei=0; ei<N; ei++) { - ConfigDescription config = c->getEntries().keyAt(ei); - if (filterable && !filter.match(config)) { - continue; - } - sp<Entry> e = c->getEntries().valueAt(ei); - if (e == NULL) { - continue; - } - e->setNameIndex(keyStrings.add(e->getName(), true)); - - // If this entry has no values for other configs, - // and is the default config, then it is special. Otherwise - // we want to add it with the config info. - ConfigDescription* valueConfig = NULL; - if (N != 1 || config == nullConfig) { - valueConfig = &config; - } - - status_t err = e->prepareFlatten(&valueStrings, this, - &configTypeName, &config); - if (err != NO_ERROR) { - return err; - } - allEntries.add(e); - } - } - } - - p->setTypeStrings(typeStrings.createStringBlock()); - p->setKeyStrings(keyStrings.createStringBlock()); - } - - if (bundle->getOutputAPKFile() != NULL) { - // Now we want to sort the value strings for better locality. This will - // cause the positions of the strings to change, so we need to go back - // through out resource entries and update them accordingly. Only need - // to do this if actually writing the output file. - valueStrings.sortByConfig(); - for (pi=0; pi<allEntries.size(); pi++) { - allEntries[pi]->remapStringValue(&valueStrings); - } - } - - ssize_t strAmt = 0; - - // Now build the array of package chunks. - Vector<sp<AaptFile> > flatPackages; - for (pi=0; pi<N; pi++) { - sp<Package> p = mOrderedPackages.itemAt(pi); - if (p->getTypes().size() == 0) { - // Empty, skip! - continue; - } - - const size_t N = p->getTypeStrings().size(); - - const size_t baseSize = sizeof(ResTable_package); - - // Start the package data. - sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8()); - ResTable_package* header = (ResTable_package*)data->editData(baseSize); - if (header == NULL) { - fprintf(stderr, "ERROR: out of memory creating ResTable_package\n"); - return NO_MEMORY; - } - memset(header, 0, sizeof(*header)); - header->header.type = htods(RES_TABLE_PACKAGE_TYPE); - header->header.headerSize = htods(sizeof(*header)); - header->id = htodl(p->getAssignedId()); - strcpy16_htod(header->name, p->getName().string()); - - // Write the string blocks. - const size_t typeStringsStart = data->getSize(); - sp<AaptFile> strFile = p->getTypeStringsData(); - ssize_t amt = data->writeData(strFile->getData(), strFile->getSize()); - #if PRINT_STRING_METRICS - fprintf(stderr, "**** type strings: %d\n", amt); - #endif - strAmt += amt; - if (amt < 0) { - return amt; - } - const size_t keyStringsStart = data->getSize(); - strFile = p->getKeyStringsData(); - amt = data->writeData(strFile->getData(), strFile->getSize()); - #if PRINT_STRING_METRICS - fprintf(stderr, "**** key strings: %d\n", amt); - #endif - strAmt += amt; - if (amt < 0) { - return amt; - } - - // Build the type chunks inside of this package. - for (size_t ti=0; ti<N; ti++) { - // Retrieve them in the same order as the type string block. - size_t len; - String16 typeName(p->getTypeStrings().stringAt(ti, &len)); - sp<Type> t = p->getTypes().valueFor(typeName); - LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"), - "Type name %s not found", - String8(typeName).string()); - - const bool filterable = (typeName != mipmap16); - - const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0; - - // Until a non-NO_ENTRY value has been written for a resource, - // that resource is invalid; validResources[i] represents - // the item at t->getOrderedConfigs().itemAt(i). - Vector<bool> validResources; - validResources.insertAt(false, 0, N); - - // First write the typeSpec chunk, containing information about - // each resource entry in this type. - { - const size_t typeSpecSize = sizeof(ResTable_typeSpec) + sizeof(uint32_t)*N; - const size_t typeSpecStart = data->getSize(); - ResTable_typeSpec* tsHeader = (ResTable_typeSpec*) - (((uint8_t*)data->editData(typeSpecStart+typeSpecSize)) + typeSpecStart); - if (tsHeader == NULL) { - fprintf(stderr, "ERROR: out of memory creating ResTable_typeSpec\n"); - return NO_MEMORY; - } - memset(tsHeader, 0, sizeof(*tsHeader)); - tsHeader->header.type = htods(RES_TABLE_TYPE_SPEC_TYPE); - tsHeader->header.headerSize = htods(sizeof(*tsHeader)); - tsHeader->header.size = htodl(typeSpecSize); - tsHeader->id = ti+1; - tsHeader->entryCount = htodl(N); - - uint32_t* typeSpecFlags = (uint32_t*) - (((uint8_t*)data->editData()) - + typeSpecStart + sizeof(ResTable_typeSpec)); - memset(typeSpecFlags, 0, sizeof(uint32_t)*N); - - for (size_t ei=0; ei<N; ei++) { - sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei); - if (cl->getPublic()) { - typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC); - } - const size_t CN = cl->getEntries().size(); - for (size_t ci=0; ci<CN; ci++) { - if (filterable && !filter.match(cl->getEntries().keyAt(ci))) { - continue; - } - for (size_t cj=ci+1; cj<CN; cj++) { - if (filterable && !filter.match(cl->getEntries().keyAt(cj))) { - continue; - } - typeSpecFlags[ei] |= htodl( - cl->getEntries().keyAt(ci).diff(cl->getEntries().keyAt(cj))); - } - } - } - } - - // We need to write one type chunk for each configuration for - // which we have entries in this type. - const size_t NC = t->getUniqueConfigs().size(); - - const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N; - - for (size_t ci=0; ci<NC; ci++) { - ConfigDescription config = t->getUniqueConfigs().itemAt(ci); - - NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c " - "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " - "sw%ddp w%ddp h%ddp dir:%d\n", - ti+1, - config.mcc, config.mnc, - config.language[0] ? config.language[0] : '-', - config.language[1] ? config.language[1] : '-', - config.country[0] ? config.country[0] : '-', - config.country[1] ? config.country[1] : '-', - config.orientation, - config.uiMode, - config.touchscreen, - config.density, - config.keyboard, - config.inputFlags, - config.navigation, - config.screenWidth, - config.screenHeight, - config.smallestScreenWidthDp, - config.screenWidthDp, - config.screenHeightDp, - config.layoutDirection)); - - if (filterable && !filter.match(config)) { - continue; - } - - const size_t typeStart = data->getSize(); - - ResTable_type* tHeader = (ResTable_type*) - (((uint8_t*)data->editData(typeStart+typeSize)) + typeStart); - if (tHeader == NULL) { - fprintf(stderr, "ERROR: out of memory creating ResTable_type\n"); - return NO_MEMORY; - } - - memset(tHeader, 0, sizeof(*tHeader)); - tHeader->header.type = htods(RES_TABLE_TYPE_TYPE); - tHeader->header.headerSize = htods(sizeof(*tHeader)); - tHeader->id = ti+1; - tHeader->entryCount = htodl(N); - tHeader->entriesStart = htodl(typeSize); - tHeader->config = config; - NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c " - "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " - "sw%ddp w%ddp h%ddp dir:%d\n", - ti+1, - tHeader->config.mcc, tHeader->config.mnc, - tHeader->config.language[0] ? tHeader->config.language[0] : '-', - tHeader->config.language[1] ? tHeader->config.language[1] : '-', - tHeader->config.country[0] ? tHeader->config.country[0] : '-', - tHeader->config.country[1] ? tHeader->config.country[1] : '-', - tHeader->config.orientation, - tHeader->config.uiMode, - tHeader->config.touchscreen, - tHeader->config.density, - tHeader->config.keyboard, - tHeader->config.inputFlags, - tHeader->config.navigation, - tHeader->config.screenWidth, - tHeader->config.screenHeight, - tHeader->config.smallestScreenWidthDp, - tHeader->config.screenWidthDp, - tHeader->config.screenHeightDp, - tHeader->config.layoutDirection)); - tHeader->config.swapHtoD(); - - // Build the entries inside of this type. - for (size_t ei=0; ei<N; ei++) { - sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei); - sp<Entry> e = cl->getEntries().valueFor(config); - - // Set the offset for this entry in its type. - uint32_t* index = (uint32_t*) - (((uint8_t*)data->editData()) - + typeStart + sizeof(ResTable_type)); - if (e != NULL) { - index[ei] = htodl(data->getSize()-typeStart-typeSize); - - // Create the entry. - ssize_t amt = e->flatten(bundle, data, cl->getPublic()); - if (amt < 0) { - return amt; - } - validResources.editItemAt(ei) = true; - } else { - index[ei] = htodl(ResTable_type::NO_ENTRY); - } - } - - // Fill in the rest of the type information. - tHeader = (ResTable_type*) - (((uint8_t*)data->editData()) + typeStart); - tHeader->header.size = htodl(data->getSize()-typeStart); - } - - for (size_t i = 0; i < N; ++i) { - if (!validResources[i]) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(i); - fprintf(stderr, "warning: no entries written for %s/%s\n", - String8(typeName).string(), String8(c->getName()).string()); - } - } - } - - // Fill in the rest of the package information. - header = (ResTable_package*)data->editData(); - header->header.size = htodl(data->getSize()); - header->typeStrings = htodl(typeStringsStart); - header->lastPublicType = htodl(p->getTypeStrings().size()); - header->keyStrings = htodl(keyStringsStart); - header->lastPublicKey = htodl(p->getKeyStrings().size()); - - flatPackages.add(data); - } - - // And now write out the final chunks. - const size_t dataStart = dest->getSize(); - - { - // blah - ResTable_header header; - memset(&header, 0, sizeof(header)); - header.header.type = htods(RES_TABLE_TYPE); - header.header.headerSize = htods(sizeof(header)); - header.packageCount = htodl(flatPackages.size()); - status_t err = dest->writeData(&header, sizeof(header)); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: out of memory creating ResTable_header\n"); - return err; - } - } - - ssize_t strStart = dest->getSize(); - err = valueStrings.writeStringBlock(dest); - if (err != NO_ERROR) { - return err; - } - - ssize_t amt = (dest->getSize()-strStart); - strAmt += amt; - #if PRINT_STRING_METRICS - fprintf(stderr, "**** value strings: %d\n", amt); - fprintf(stderr, "**** total strings: %d\n", strAmt); - #endif - - for (pi=0; pi<flatPackages.size(); pi++) { - err = dest->writeData(flatPackages[pi]->getData(), - flatPackages[pi]->getSize()); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: out of memory creating package chunk for ResTable_header\n"); - return err; - } - } - - ResTable_header* header = (ResTable_header*) - (((uint8_t*)dest->getData()) + dataStart); - header->header.size = htodl(dest->getSize() - dataStart); - - NOISY(aout << "Resource table:" - << HexDump(dest->getData(), dest->getSize()) << endl); - - #if PRINT_STRING_METRICS - fprintf(stderr, "**** total resource table size: %d / %d%% strings\n", - dest->getSize(), (strAmt*100)/dest->getSize()); - #endif - - return NO_ERROR; -} - -void ResourceTable::writePublicDefinitions(const String16& package, FILE* fp) -{ - fprintf(fp, - "<!-- This file contains <public> resource definitions for all\n" - " resources that were generated from the source data. -->\n" - "\n" - "<resources>\n"); - - writePublicDefinitions(package, fp, true); - writePublicDefinitions(package, fp, false); - - fprintf(fp, - "\n" - "</resources>\n"); -} - -void ResourceTable::writePublicDefinitions(const String16& package, FILE* fp, bool pub) -{ - bool didHeader = false; - - sp<Package> pkg = mPackages.valueFor(package); - if (pkg != NULL) { - const size_t NT = pkg->getOrderedTypes().size(); - for (size_t i=0; i<NT; i++) { - sp<Type> t = pkg->getOrderedTypes().itemAt(i); - if (t == NULL) { - continue; - } - - bool didType = false; - - const size_t NC = t->getOrderedConfigs().size(); - for (size_t j=0; j<NC; j++) { - sp<ConfigList> c = t->getOrderedConfigs().itemAt(j); - if (c == NULL) { - continue; - } - - if (c->getPublic() != pub) { - continue; - } - - if (!didType) { - fprintf(fp, "\n"); - didType = true; - } - if (!didHeader) { - if (pub) { - fprintf(fp," <!-- PUBLIC SECTION. These resources have been declared public.\n"); - fprintf(fp," Changes to these definitions will break binary compatibility. -->\n\n"); - } else { - fprintf(fp," <!-- PRIVATE SECTION. These resources have not been declared public.\n"); - fprintf(fp," You can make them public my moving these lines into a file in res/values. -->\n\n"); - } - didHeader = true; - } - if (!pub) { - const size_t NE = c->getEntries().size(); - for (size_t k=0; k<NE; k++) { - const SourcePos& pos = c->getEntries().valueAt(k)->getPos(); - if (pos.file != "") { - fprintf(fp," <!-- Declared at %s:%d -->\n", - pos.file.string(), pos.line); - } - } - } - fprintf(fp, " <public type=\"%s\" name=\"%s\" id=\"0x%08x\" />\n", - String8(t->getName()).string(), - String8(c->getName()).string(), - getResId(pkg, t, c->getEntryIndex())); - } - } - } -} - -ResourceTable::Item::Item(const SourcePos& _sourcePos, - bool _isId, - const String16& _value, - const Vector<StringPool::entry_style_span>* _style, - int32_t _format) - : sourcePos(_sourcePos) - , isId(_isId) - , value(_value) - , format(_format) - , bagKeyId(0) - , evaluating(false) -{ - if (_style) { - style = *_style; - } -} - -status_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos) -{ - if (mType == TYPE_BAG) { - return NO_ERROR; - } - if (mType == TYPE_UNKNOWN) { - mType = TYPE_BAG; - return NO_ERROR; - } - sourcePos.error("Resource entry %s is already defined as a single item.\n" - "%s:%d: Originally defined here.\n", - String8(mName).string(), - mItem.sourcePos.file.string(), mItem.sourcePos.line); - return UNKNOWN_ERROR; -} - -status_t ResourceTable::Entry::setItem(const SourcePos& sourcePos, - const String16& value, - const Vector<StringPool::entry_style_span>* style, - int32_t format, - const bool overwrite) -{ - Item item(sourcePos, false, value, style); - - if (mType == TYPE_BAG) { - const Item& item(mBag.valueAt(0)); - sourcePos.error("Resource entry %s is already defined as a bag.\n" - "%s:%d: Originally defined here.\n", - String8(mName).string(), - item.sourcePos.file.string(), item.sourcePos.line); - return UNKNOWN_ERROR; - } - if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) { - sourcePos.error("Resource entry %s is already defined.\n" - "%s:%d: Originally defined here.\n", - String8(mName).string(), - mItem.sourcePos.file.string(), mItem.sourcePos.line); - return UNKNOWN_ERROR; - } - - mType = TYPE_ITEM; - mItem = item; - mItemFormat = format; - return NO_ERROR; -} - -status_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos, - const String16& key, const String16& value, - const Vector<StringPool::entry_style_span>* style, - bool replace, bool isId, int32_t format) -{ - status_t err = makeItABag(sourcePos); - if (err != NO_ERROR) { - return err; - } - - Item item(sourcePos, isId, value, style, format); - - // XXX NOTE: there is an error if you try to have a bag with two keys, - // one an attr and one an id, with the same name. Not something we - // currently ever have to worry about. - ssize_t origKey = mBag.indexOfKey(key); - if (origKey >= 0) { - if (!replace) { - const Item& item(mBag.valueAt(origKey)); - sourcePos.error("Resource entry %s already has bag item %s.\n" - "%s:%d: Originally defined here.\n", - String8(mName).string(), String8(key).string(), - item.sourcePos.file.string(), item.sourcePos.line); - return UNKNOWN_ERROR; - } - //printf("Replacing %s with %s\n", - // String8(mBag.valueFor(key).value).string(), String8(value).string()); - mBag.replaceValueFor(key, item); - } - - mBag.add(key, item); - return NO_ERROR; -} - -status_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos) -{ - status_t err = makeItABag(sourcePos); - if (err != NO_ERROR) { - return err; - } - - mBag.clear(); - return NO_ERROR; -} - -status_t ResourceTable::Entry::generateAttributes(ResourceTable* table, - const String16& package) -{ - const String16 attr16("attr"); - const String16 id16("id"); - const size_t N = mBag.size(); - for (size_t i=0; i<N; i++) { - const String16& key = mBag.keyAt(i); - const Item& it = mBag.valueAt(i); - if (it.isId) { - if (!table->hasBagOrEntry(key, &id16, &package)) { - String16 value("false"); - status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package, - id16, key, value); - if (err != NO_ERROR) { - return err; - } - } - } else if (!table->hasBagOrEntry(key, &attr16, &package)) { - -#if 1 -// fprintf(stderr, "ERROR: Bag attribute '%s' has not been defined.\n", -// String8(key).string()); -// const Item& item(mBag.valueAt(i)); -// fprintf(stderr, "Referenced from file %s line %d\n", -// item.sourcePos.file.string(), item.sourcePos.line); -// return UNKNOWN_ERROR; -#else - char numberStr[16]; - sprintf(numberStr, "%d", ResTable_map::TYPE_ANY); - status_t err = table->addBag(SourcePos("<generated>", 0), package, - attr16, key, String16(""), - String16("^type"), - String16(numberStr), NULL, NULL); - if (err != NO_ERROR) { - return err; - } -#endif - } - } - return NO_ERROR; -} - -status_t ResourceTable::Entry::assignResourceIds(ResourceTable* table, - const String16& package) -{ - bool hasErrors = false; - - if (mType == TYPE_BAG) { - const char* errorMsg; - const String16 style16("style"); - const String16 attr16("attr"); - const String16 id16("id"); - mParentId = 0; - if (mParent.size() > 0) { - mParentId = table->getResId(mParent, &style16, NULL, &errorMsg); - if (mParentId == 0) { - mPos.error("Error retrieving parent for item: %s '%s'.\n", - errorMsg, String8(mParent).string()); - hasErrors = true; - } - } - const size_t N = mBag.size(); - for (size_t i=0; i<N; i++) { - const String16& key = mBag.keyAt(i); - Item& it = mBag.editValueAt(i); - it.bagKeyId = table->getResId(key, - it.isId ? &id16 : &attr16, NULL, &errorMsg); - //printf("Bag key of %s: #%08x\n", String8(key).string(), it.bagKeyId); - if (it.bagKeyId == 0) { - it.sourcePos.error("Error: %s: %s '%s'.\n", errorMsg, - String8(it.isId ? id16 : attr16).string(), - String8(key).string()); - hasErrors = true; - } - } - } - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -status_t ResourceTable::Entry::prepareFlatten(StringPool* strings, ResourceTable* table, - const String8* configTypeName, const ConfigDescription* config) -{ - if (mType == TYPE_ITEM) { - Item& it = mItem; - AccessorCookie ac(it.sourcePos, String8(mName), String8(it.value)); - if (!table->stringToValue(&it.parsedValue, strings, - it.value, false, true, 0, - &it.style, NULL, &ac, mItemFormat, - configTypeName, config)) { - return UNKNOWN_ERROR; - } - } else if (mType == TYPE_BAG) { - const size_t N = mBag.size(); - for (size_t i=0; i<N; i++) { - const String16& key = mBag.keyAt(i); - Item& it = mBag.editValueAt(i); - AccessorCookie ac(it.sourcePos, String8(key), String8(it.value)); - if (!table->stringToValue(&it.parsedValue, strings, - it.value, false, true, it.bagKeyId, - &it.style, NULL, &ac, it.format, - configTypeName, config)) { - return UNKNOWN_ERROR; - } - } - } else { - mPos.error("Error: entry %s is not a single item or a bag.\n", - String8(mName).string()); - return UNKNOWN_ERROR; - } - return NO_ERROR; -} - -status_t ResourceTable::Entry::remapStringValue(StringPool* strings) -{ - if (mType == TYPE_ITEM) { - Item& it = mItem; - if (it.parsedValue.dataType == Res_value::TYPE_STRING) { - it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data); - } - } else if (mType == TYPE_BAG) { - const size_t N = mBag.size(); - for (size_t i=0; i<N; i++) { - Item& it = mBag.editValueAt(i); - if (it.parsedValue.dataType == Res_value::TYPE_STRING) { - it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data); - } - } - } else { - mPos.error("Error: entry %s is not a single item or a bag.\n", - String8(mName).string()); - return UNKNOWN_ERROR; - } - return NO_ERROR; -} - -ssize_t ResourceTable::Entry::flatten(Bundle* bundle, const sp<AaptFile>& data, bool isPublic) -{ - size_t amt = 0; - ResTable_entry header; - memset(&header, 0, sizeof(header)); - header.size = htods(sizeof(header)); - const type ty = this != NULL ? mType : TYPE_ITEM; - if (this != NULL) { - if (ty == TYPE_BAG) { - header.flags |= htods(header.FLAG_COMPLEX); - } - if (isPublic) { - header.flags |= htods(header.FLAG_PUBLIC); - } - header.key.index = htodl(mNameIndex); - } - if (ty != TYPE_BAG) { - status_t err = data->writeData(&header, sizeof(header)); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n"); - return err; - } - - const Item& it = mItem; - Res_value par; - memset(&par, 0, sizeof(par)); - par.size = htods(it.parsedValue.size); - par.dataType = it.parsedValue.dataType; - par.res0 = it.parsedValue.res0; - par.data = htodl(it.parsedValue.data); - #if 0 - printf("Writing item (%s): type=%d, data=0x%x, res0=0x%x\n", - String8(mName).string(), it.parsedValue.dataType, - it.parsedValue.data, par.res0); - #endif - err = data->writeData(&par, it.parsedValue.size); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: out of memory creating Res_value\n"); - return err; - } - amt += it.parsedValue.size; - } else { - size_t N = mBag.size(); - size_t i; - // Create correct ordering of items. - KeyedVector<uint32_t, const Item*> items; - for (i=0; i<N; i++) { - const Item& it = mBag.valueAt(i); - items.add(it.bagKeyId, &it); - } - N = items.size(); - - ResTable_map_entry mapHeader; - memcpy(&mapHeader, &header, sizeof(header)); - mapHeader.size = htods(sizeof(mapHeader)); - mapHeader.parent.ident = htodl(mParentId); - mapHeader.count = htodl(N); - status_t err = data->writeData(&mapHeader, sizeof(mapHeader)); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n"); - return err; - } - - for (i=0; i<N; i++) { - const Item& it = *items.valueAt(i); - ResTable_map map; - map.name.ident = htodl(it.bagKeyId); - map.value.size = htods(it.parsedValue.size); - map.value.dataType = it.parsedValue.dataType; - map.value.res0 = it.parsedValue.res0; - map.value.data = htodl(it.parsedValue.data); - err = data->writeData(&map, sizeof(map)); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: out of memory creating Res_value\n"); - return err; - } - amt += sizeof(map); - } - } - return amt; -} - -void ResourceTable::ConfigList::appendComment(const String16& comment, - bool onlyIfEmpty) -{ - if (comment.size() <= 0) { - return; - } - if (onlyIfEmpty && mComment.size() > 0) { - return; - } - if (mComment.size() > 0) { - mComment.append(String16("\n")); - } - mComment.append(comment); -} - -void ResourceTable::ConfigList::appendTypeComment(const String16& comment) -{ - if (comment.size() <= 0) { - return; - } - if (mTypeComment.size() > 0) { - mTypeComment.append(String16("\n")); - } - mTypeComment.append(comment); -} - -status_t ResourceTable::Type::addPublic(const SourcePos& sourcePos, - const String16& name, - const uint32_t ident) -{ - #if 0 - int32_t entryIdx = Res_GETENTRY(ident); - if (entryIdx < 0) { - sourcePos.error("Public resource %s/%s has an invalid 0 identifier (0x%08x).\n", - String8(mName).string(), String8(name).string(), ident); - return UNKNOWN_ERROR; - } - #endif - - int32_t typeIdx = Res_GETTYPE(ident); - if (typeIdx >= 0) { - typeIdx++; - if (mPublicIndex > 0 && mPublicIndex != typeIdx) { - sourcePos.error("Public resource %s/%s has conflicting type codes for its" - " public identifiers (0x%x vs 0x%x).\n", - String8(mName).string(), String8(name).string(), - mPublicIndex, typeIdx); - return UNKNOWN_ERROR; - } - mPublicIndex = typeIdx; - } - - if (mFirstPublicSourcePos == NULL) { - mFirstPublicSourcePos = new SourcePos(sourcePos); - } - - if (mPublic.indexOfKey(name) < 0) { - mPublic.add(name, Public(sourcePos, String16(), ident)); - } else { - Public& p = mPublic.editValueFor(name); - if (p.ident != ident) { - sourcePos.error("Public resource %s/%s has conflicting public identifiers" - " (0x%08x vs 0x%08x).\n" - "%s:%d: Originally defined here.\n", - String8(mName).string(), String8(name).string(), p.ident, ident, - p.sourcePos.file.string(), p.sourcePos.line); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -void ResourceTable::Type::canAddEntry(const String16& name) -{ - mCanAddEntries.add(name); -} - -sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry, - const SourcePos& sourcePos, - const ResTable_config* config, - bool doSetIndex, - bool overlay, - bool autoAddOverlay) -{ - int pos = -1; - sp<ConfigList> c = mConfigs.valueFor(entry); - if (c == NULL) { - if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) { - sourcePos.error("Resource at %s appears in overlay but not" - " in the base package; use <add-resource> to add.\n", - String8(entry).string()); - return NULL; - } - c = new ConfigList(entry, sourcePos); - mConfigs.add(entry, c); - pos = (int)mOrderedConfigs.size(); - mOrderedConfigs.add(c); - if (doSetIndex) { - c->setEntryIndex(pos); - } - } - - ConfigDescription cdesc; - if (config) cdesc = *config; - - sp<Entry> e = c->getEntries().valueFor(cdesc); - if (e == NULL) { - if (config != NULL) { - NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c " - "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " - "sw%ddp w%ddp h%ddp dir:%d\n", - sourcePos.file.string(), sourcePos.line, - config->mcc, config->mnc, - config->language[0] ? config->language[0] : '-', - config->language[1] ? config->language[1] : '-', - config->country[0] ? config->country[0] : '-', - config->country[1] ? config->country[1] : '-', - config->orientation, - config->touchscreen, - config->density, - config->keyboard, - config->inputFlags, - config->navigation, - config->screenWidth, - config->screenHeight, - config->smallestScreenWidthDp, - config->screenWidthDp, - config->screenHeightDp, - config->layoutDirection)); - } else { - NOISY(printf("New entry at %s:%d: NULL config\n", - sourcePos.file.string(), sourcePos.line)); - } - e = new Entry(entry, sourcePos); - c->addEntry(cdesc, e); - /* - if (doSetIndex) { - if (pos < 0) { - for (pos=0; pos<(int)mOrderedConfigs.size(); pos++) { - if (mOrderedConfigs[pos] == c) { - break; - } - } - if (pos >= (int)mOrderedConfigs.size()) { - sourcePos.error("Internal error: config not found in mOrderedConfigs when adding entry"); - return NULL; - } - } - e->setEntryIndex(pos); - } - */ - } - - mUniqueConfigs.add(cdesc); - - return e; -} - -status_t ResourceTable::Type::applyPublicEntryOrder() -{ - size_t N = mOrderedConfigs.size(); - Vector<sp<ConfigList> > origOrder(mOrderedConfigs); - bool hasError = false; - - size_t i; - for (i=0; i<N; i++) { - mOrderedConfigs.replaceAt(NULL, i); - } - - const size_t NP = mPublic.size(); - //printf("Ordering %d configs from %d public defs\n", N, NP); - size_t j; - for (j=0; j<NP; j++) { - const String16& name = mPublic.keyAt(j); - const Public& p = mPublic.valueAt(j); - int32_t idx = Res_GETENTRY(p.ident); - //printf("Looking for entry \"%s\"/\"%s\" (0x%08x) in %d...\n", - // String8(mName).string(), String8(name).string(), p.ident, N); - bool found = false; - for (i=0; i<N; i++) { - sp<ConfigList> e = origOrder.itemAt(i); - //printf("#%d: \"%s\"\n", i, String8(e->getName()).string()); - if (e->getName() == name) { - if (idx >= (int32_t)mOrderedConfigs.size()) { - p.sourcePos.error("Public entry identifier 0x%x entry index " - "is larger than available symbols (index %d, total symbols %d).\n", - p.ident, idx, mOrderedConfigs.size()); - hasError = true; - } else if (mOrderedConfigs.itemAt(idx) == NULL) { - e->setPublic(true); - e->setPublicSourcePos(p.sourcePos); - mOrderedConfigs.replaceAt(e, idx); - origOrder.removeAt(i); - N--; - found = true; - break; - } else { - sp<ConfigList> oe = mOrderedConfigs.itemAt(idx); - - p.sourcePos.error("Multiple entry names declared for public entry" - " identifier 0x%x in type %s (%s vs %s).\n" - "%s:%d: Originally defined here.", - idx+1, String8(mName).string(), - String8(oe->getName()).string(), - String8(name).string(), - oe->getPublicSourcePos().file.string(), - oe->getPublicSourcePos().line); - hasError = true; - } - } - } - - if (!found) { - p.sourcePos.error("Public symbol %s/%s declared here is not defined.", - String8(mName).string(), String8(name).string()); - hasError = true; - } - } - - //printf("Copying back in %d non-public configs, have %d\n", N, origOrder.size()); - - if (N != origOrder.size()) { - printf("Internal error: remaining private symbol count mismatch\n"); - N = origOrder.size(); - } - - j = 0; - for (i=0; i<N; i++) { - sp<ConfigList> e = origOrder.itemAt(i); - // There will always be enough room for the remaining entries. - while (mOrderedConfigs.itemAt(j) != NULL) { - j++; - } - mOrderedConfigs.replaceAt(e, j); - j++; - } - - return hasError ? UNKNOWN_ERROR : NO_ERROR; -} - -ResourceTable::Package::Package(const String16& name, ssize_t includedId) - : mName(name), mIncludedId(includedId), - mTypeStringsMapping(0xffffffff), - mKeyStringsMapping(0xffffffff) -{ -} - -sp<ResourceTable::Type> ResourceTable::Package::getType(const String16& type, - const SourcePos& sourcePos, - bool doSetIndex) -{ - sp<Type> t = mTypes.valueFor(type); - if (t == NULL) { - t = new Type(type, sourcePos); - mTypes.add(type, t); - mOrderedTypes.add(t); - if (doSetIndex) { - // For some reason the type's index is set to one plus the index - // in the mOrderedTypes list, rather than just the index. - t->setIndex(mOrderedTypes.size()); - } - } - return t; -} - -status_t ResourceTable::Package::setTypeStrings(const sp<AaptFile>& data) -{ - mTypeStringsData = data; - status_t err = setStrings(data, &mTypeStrings, &mTypeStringsMapping); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: Type string data is corrupt!\n"); - } - return err; -} - -status_t ResourceTable::Package::setKeyStrings(const sp<AaptFile>& data) -{ - mKeyStringsData = data; - status_t err = setStrings(data, &mKeyStrings, &mKeyStringsMapping); - if (err != NO_ERROR) { - fprintf(stderr, "ERROR: Key string data is corrupt!\n"); - } - return err; -} - -status_t ResourceTable::Package::setStrings(const sp<AaptFile>& data, - ResStringPool* strings, - DefaultKeyedVector<String16, uint32_t>* mappings) -{ - if (data->getData() == NULL) { - return UNKNOWN_ERROR; - } - - NOISY(aout << "Setting restable string pool: " - << HexDump(data->getData(), data->getSize()) << endl); - - status_t err = strings->setTo(data->getData(), data->getSize()); - if (err == NO_ERROR) { - const size_t N = strings->size(); - for (size_t i=0; i<N; i++) { - size_t len; - mappings->add(String16(strings->stringAt(i, &len)), i); - } - } - return err; -} - -status_t ResourceTable::Package::applyPublicTypeOrder() -{ - size_t N = mOrderedTypes.size(); - Vector<sp<Type> > origOrder(mOrderedTypes); - - size_t i; - for (i=0; i<N; i++) { - mOrderedTypes.replaceAt(NULL, i); - } - - for (i=0; i<N; i++) { - sp<Type> t = origOrder.itemAt(i); - int32_t idx = t->getPublicIndex(); - if (idx > 0) { - idx--; - while (idx >= (int32_t)mOrderedTypes.size()) { - mOrderedTypes.add(); - } - if (mOrderedTypes.itemAt(idx) != NULL) { - sp<Type> ot = mOrderedTypes.itemAt(idx); - t->getFirstPublicSourcePos().error("Multiple type names declared for public type" - " identifier 0x%x (%s vs %s).\n" - "%s:%d: Originally defined here.", - idx, String8(ot->getName()).string(), - String8(t->getName()).string(), - ot->getFirstPublicSourcePos().file.string(), - ot->getFirstPublicSourcePos().line); - return UNKNOWN_ERROR; - } - mOrderedTypes.replaceAt(t, idx); - origOrder.removeAt(i); - i--; - N--; - } - } - - size_t j=0; - for (i=0; i<N; i++) { - sp<Type> t = origOrder.itemAt(i); - // There will always be enough room for the remaining types. - while (mOrderedTypes.itemAt(j) != NULL) { - j++; - } - mOrderedTypes.replaceAt(t, j); - } - - return NO_ERROR; -} - -sp<ResourceTable::Package> ResourceTable::getPackage(const String16& package) -{ - sp<Package> p = mPackages.valueFor(package); - if (p == NULL) { - if (mIsAppPackage) { - if (mHaveAppPackage) { - fprintf(stderr, "Adding multiple application package resources; only one is allowed.\n" - "Use -x to create extended resources.\n"); - return NULL; - } - mHaveAppPackage = true; - p = new Package(package, 127); - } else { - p = new Package(package, mNextPackageId); - } - //printf("*** NEW PACKAGE: \"%s\" id=%d\n", - // String8(package).string(), p->getAssignedId()); - mPackages.add(package, p); - mOrderedPackages.add(p); - mNextPackageId++; - } - return p; -} - -sp<ResourceTable::Type> ResourceTable::getType(const String16& package, - const String16& type, - const SourcePos& sourcePos, - bool doSetIndex) -{ - sp<Package> p = getPackage(package); - if (p == NULL) { - return NULL; - } - return p->getType(type, sourcePos, doSetIndex); -} - -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) -{ - sp<Type> t = getType(package, type, sourcePos, doSetIndex); - if (t == NULL) { - return NULL; - } - return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay()); -} - -sp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID, - const ResTable_config* config) const -{ - int pid = Res_GETPACKAGE(resID)+1; - const size_t N = mOrderedPackages.size(); - size_t i; - sp<Package> p; - for (i=0; i<N; i++) { - sp<Package> check = mOrderedPackages[i]; - if (check->getAssignedId() == pid) { - p = check; - break; - } - - } - if (p == NULL) { - fprintf(stderr, "warning: Package not found for resource #%08x\n", resID); - return NULL; - } - - int tid = Res_GETTYPE(resID); - if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) { - fprintf(stderr, "warning: Type not found for resource #%08x\n", resID); - return NULL; - } - sp<Type> t = p->getOrderedTypes()[tid]; - - int eid = Res_GETENTRY(resID); - if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) { - fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID); - return NULL; - } - - sp<ConfigList> c = t->getOrderedConfigs()[eid]; - if (c == NULL) { - fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID); - return NULL; - } - - ConfigDescription cdesc; - if (config) cdesc = *config; - sp<Entry> e = c->getEntries().valueFor(cdesc); - if (c == NULL) { - fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID); - return NULL; - } - - return e; -} - -const ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrID) const -{ - sp<const Entry> e = getEntry(resID); - if (e == NULL) { - return NULL; - } - - const size_t N = e->getBag().size(); - for (size_t i=0; i<N; i++) { - const Item& it = e->getBag().valueAt(i); - if (it.bagKeyId == 0) { - fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n", - String8(e->getName()).string(), - String8(e->getBag().keyAt(i)).string()); - } - if (it.bagKeyId == attrID) { - return ⁢ - } - } - - return NULL; -} - -bool ResourceTable::getItemValue( - uint32_t resID, uint32_t attrID, Res_value* outValue) -{ - const Item* item = getItem(resID, attrID); - - bool res = false; - if (item != NULL) { - if (item->evaluating) { - sp<const Entry> e = getEntry(resID); - const size_t N = e->getBag().size(); - size_t i; - for (i=0; i<N; i++) { - if (&e->getBag().valueAt(i) == item) { - break; - } - } - fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n", - String8(e->getName()).string(), - String8(e->getBag().keyAt(i)).string()); - return false; - } - item->evaluating = true; - res = stringToValue(outValue, NULL, item->value, false, false, item->bagKeyId); - NOISY( - if (res) { - printf("getItemValue of #%08x[#%08x] (%s): type=#%08x, data=#%08x\n", - resID, attrID, String8(getEntry(resID)->getName()).string(), - outValue->dataType, outValue->data); - } else { - printf("getItemValue of #%08x[#%08x]: failed\n", - resID, attrID); - } - ); - item->evaluating = false; - } - return res; -} diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h deleted file mode 100644 index a3e0666..0000000 --- a/tools/aapt/ResourceTable.h +++ /dev/null @@ -1,557 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#ifndef RESOURCE_TABLE_H -#define RESOURCE_TABLE_H - -#include "StringPool.h" -#include "SourcePos.h" - -#include <set> -#include <map> - -using namespace std; - -class XMLNode; -class ResourceTable; - -enum { - XML_COMPILE_STRIP_COMMENTS = 1<<0, - XML_COMPILE_ASSIGN_ATTRIBUTE_IDS = 1<<1, - XML_COMPILE_COMPACT_WHITESPACE = 1<<2, - XML_COMPILE_STRIP_WHITESPACE = 1<<3, - XML_COMPILE_STRIP_RAW_VALUES = 1<<4, - XML_COMPILE_UTF8 = 1<<5, - - XML_COMPILE_STANDARD_RESOURCE = - XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS - | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES -}; - -status_t compileXmlFile(const sp<AaptAssets>& assets, - const sp<AaptFile>& target, - ResourceTable* table, - int options = XML_COMPILE_STANDARD_RESOURCE); - -status_t compileXmlFile(const sp<AaptAssets>& assets, - const sp<AaptFile>& target, - const sp<AaptFile>& outTarget, - 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, - const ResTable_config& defParams, - const bool overwrite, - ResourceTable* outTable); - -struct AccessorCookie -{ - SourcePos sourcePos; - String8 attr; - String8 value; - - AccessorCookie(const SourcePos&p, const String8& a, const String8& v) - :sourcePos(p), - attr(a), - value(v) - { - } -}; - -class ResourceTable : public ResTable::Accessor -{ -public: - class Package; - class Type; - class Entry; - - struct ConfigDescription : public ResTable_config { - ConfigDescription() { - memset(this, 0, sizeof(*this)); - size = sizeof(ResTable_config); - } - ConfigDescription(const ResTable_config&o) { - *static_cast<ResTable_config*>(this) = o; - size = sizeof(ResTable_config); - } - ConfigDescription(const ConfigDescription&o) { - *static_cast<ResTable_config*>(this) = o; - } - - ConfigDescription& operator=(const ResTable_config& o) { - *static_cast<ResTable_config*>(this) = o; - size = sizeof(ResTable_config); - return *this; - } - ConfigDescription& operator=(const ConfigDescription& o) { - *static_cast<ResTable_config*>(this) = o; - return *this; - } - - inline bool operator<(const ConfigDescription& o) const { return compare(o) < 0; } - inline bool operator<=(const ConfigDescription& o) const { return compare(o) <= 0; } - inline bool operator==(const ConfigDescription& o) const { return compare(o) == 0; } - inline bool operator!=(const ConfigDescription& o) const { return compare(o) != 0; } - inline bool operator>=(const ConfigDescription& o) const { return compare(o) >= 0; } - inline bool operator>(const ConfigDescription& o) const { return compare(o) > 0; } - }; - - ResourceTable(Bundle* bundle, const String16& assetsPackage); - - status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets); - - status_t addPublic(const SourcePos& pos, - const String16& package, - const String16& type, - const String16& name, - const uint32_t ident); - - status_t addEntry(const SourcePos& pos, - const String16& package, - const String16& type, - const String16& name, - const String16& value, - const Vector<StringPool::entry_style_span>* style = NULL, - const ResTable_config* params = NULL, - const bool doSetIndex = false, - const int32_t format = ResTable_map::TYPE_ANY, - const bool overwrite = false); - - status_t startBag(const SourcePos& pos, - const String16& package, - const String16& type, - const String16& name, - const String16& bagParent, - const ResTable_config* params = NULL, - bool overlay = false, - bool replace = false, - bool isId = false); - - status_t addBag(const SourcePos& pos, - const String16& package, - const String16& type, - const String16& name, - const String16& bagParent, - const String16& bagKey, - const String16& value, - const Vector<StringPool::entry_style_span>* style = NULL, - const ResTable_config* params = NULL, - bool replace = false, - bool isId = false, - const int32_t format = ResTable_map::TYPE_ANY); - - bool hasBagOrEntry(const String16& package, - const String16& type, - const String16& name) const; - - bool hasBagOrEntry(const String16& package, - const String16& type, - const String16& name, - const ResTable_config& config) const; - - bool hasBagOrEntry(const String16& ref, - const String16* defType = NULL, - const String16* defPackage = NULL); - - bool appendComment(const String16& package, - const String16& type, - const String16& name, - const String16& comment, - bool onlyIfEmpty = false); - - bool appendTypeComment(const String16& package, - const String16& type, - const String16& name, - const String16& comment); - - void canAddEntry(const SourcePos& pos, - const String16& package, const String16& type, const String16& name); - - size_t size() const; - size_t numLocalResources() const; - bool hasResources() const; - - sp<AaptFile> flatten(Bundle*); - - static inline uint32_t makeResId(uint32_t packageId, - uint32_t typeId, - uint32_t nameId) - { - return nameId | (typeId<<16) | (packageId<<24); - } - - static inline uint32_t getResId(const sp<Package>& p, - const sp<Type>& t, - uint32_t nameId); - - uint32_t getResId(const String16& package, - const String16& type, - const String16& name, - bool onlyPublic = true) const; - - uint32_t getResId(const String16& ref, - const String16* defType = NULL, - const String16* defPackage = NULL, - const char** outErrorMsg = NULL, - bool onlyPublic = true) const; - - static bool isValidResourceName(const String16& s); - - bool stringToValue(Res_value* outValue, StringPool* pool, - const String16& str, - bool preserveSpaces, bool coerceType, - uint32_t attrID, - const Vector<StringPool::entry_style_span>* style = NULL, - String16* outStr = NULL, void* accessorCookie = NULL, - uint32_t attrType = ResTable_map::TYPE_ANY, - const String8* configTypeName = NULL, - const ConfigDescription* config = NULL); - - status_t assignResourceIds(); - status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL); - void addLocalization(const String16& name, const String8& locale); - status_t validateLocalizations(void); - - status_t flatten(Bundle*, const sp<AaptFile>& dest); - - void writePublicDefinitions(const String16& package, FILE* fp); - - virtual uint32_t getCustomResource(const String16& package, - const String16& type, - const String16& name) const; - virtual uint32_t getCustomResourceWithCreation(const String16& package, - const String16& type, - const String16& name, - const bool createIfNeeded); - virtual uint32_t getRemappedPackage(uint32_t origPackage) const; - virtual bool getAttributeType(uint32_t attrID, uint32_t* outType); - virtual bool getAttributeMin(uint32_t attrID, uint32_t* outMin); - virtual bool getAttributeMax(uint32_t attrID, uint32_t* outMax); - virtual bool getAttributeKeys(uint32_t attrID, Vector<String16>* outKeys); - virtual bool getAttributeEnum(uint32_t attrID, - const char16_t* name, size_t nameLen, - Res_value* outValue); - virtual bool getAttributeFlags(uint32_t attrID, - const char16_t* name, size_t nameLen, - Res_value* outValue); - virtual uint32_t getAttributeL10N(uint32_t attrID); - - virtual bool getLocalizationSetting(); - virtual void reportError(void* accessorCookie, const char* fmt, ...); - - void setCurrentXmlPos(const SourcePos& pos) { mCurrentXmlPos = pos; } - - class Item { - public: - Item() : isId(false), format(ResTable_map::TYPE_ANY), bagKeyId(0), evaluating(false) - { memset(&parsedValue, 0, sizeof(parsedValue)); } - Item(const SourcePos& pos, - bool _isId, - const String16& _value, - const Vector<StringPool::entry_style_span>* _style = NULL, - int32_t format = ResTable_map::TYPE_ANY); - Item(const Item& o) : sourcePos(o.sourcePos), - isId(o.isId), value(o.value), style(o.style), - format(o.format), bagKeyId(o.bagKeyId), evaluating(false) { - memset(&parsedValue, 0, sizeof(parsedValue)); - } - ~Item() { } - - Item& operator=(const Item& o) { - sourcePos = o.sourcePos; - isId = o.isId; - value = o.value; - style = o.style; - format = o.format; - bagKeyId = o.bagKeyId; - parsedValue = o.parsedValue; - return *this; - } - - SourcePos sourcePos; - mutable bool isId; - String16 value; - Vector<StringPool::entry_style_span> style; - int32_t format; - uint32_t bagKeyId; - mutable bool evaluating; - Res_value parsedValue; - }; - - class Entry : public RefBase { - public: - Entry(const String16& name, const SourcePos& pos) - : mName(name), mType(TYPE_UNKNOWN), - mItemFormat(ResTable_map::TYPE_ANY), mNameIndex(-1), mPos(pos) - { } - virtual ~Entry() { } - - enum type { - TYPE_UNKNOWN = 0, - TYPE_ITEM, - TYPE_BAG - }; - - String16 getName() const { return mName; } - type getType() const { return mType; } - - void setParent(const String16& parent) { mParent = parent; } - String16 getParent() const { return mParent; } - - status_t makeItABag(const SourcePos& sourcePos); - - status_t emptyBag(const SourcePos& sourcePos); - - status_t setItem(const SourcePos& pos, - const String16& value, - const Vector<StringPool::entry_style_span>* style = NULL, - int32_t format = ResTable_map::TYPE_ANY, - const bool overwrite = false); - - status_t addToBag(const SourcePos& pos, - const String16& key, const String16& value, - const Vector<StringPool::entry_style_span>* style = NULL, - bool replace=false, bool isId = false, - int32_t format = ResTable_map::TYPE_ANY); - - // Index of the entry's name string in the key pool. - int32_t getNameIndex() const { return mNameIndex; } - void setNameIndex(int32_t index) { mNameIndex = index; } - - const Item* getItem() const { return mType == TYPE_ITEM ? &mItem : NULL; } - const KeyedVector<String16, Item>& getBag() const { return mBag; } - - status_t generateAttributes(ResourceTable* table, - const String16& package); - - status_t assignResourceIds(ResourceTable* table, - const String16& package); - - status_t prepareFlatten(StringPool* strings, ResourceTable* table, - const String8* configTypeName, const ConfigDescription* config); - - status_t remapStringValue(StringPool* strings); - - ssize_t flatten(Bundle*, const sp<AaptFile>& data, bool isPublic); - - const SourcePos& getPos() const { return mPos; } - - private: - String16 mName; - String16 mParent; - type mType; - Item mItem; - int32_t mItemFormat; - KeyedVector<String16, Item> mBag; - int32_t mNameIndex; - uint32_t mParentId; - SourcePos mPos; - }; - - class ConfigList : public RefBase { - public: - ConfigList(const String16& name, const SourcePos& pos) - : mName(name), mPos(pos), mPublic(false), mEntryIndex(-1) { } - virtual ~ConfigList() { } - - String16 getName() const { return mName; } - const SourcePos& getPos() const { return mPos; } - - void appendComment(const String16& comment, bool onlyIfEmpty = false); - const String16& getComment() const { return mComment; } - - void appendTypeComment(const String16& comment); - const String16& getTypeComment() const { return mTypeComment; } - - // Index of this entry in its Type. - int32_t getEntryIndex() const { return mEntryIndex; } - void setEntryIndex(int32_t index) { mEntryIndex = index; } - - void setPublic(bool pub) { mPublic = pub; } - bool getPublic() const { return mPublic; } - void setPublicSourcePos(const SourcePos& pos) { mPublicSourcePos = pos; } - const SourcePos& getPublicSourcePos() { return mPublicSourcePos; } - - void addEntry(const ResTable_config& config, const sp<Entry>& entry) { - mEntries.add(config, entry); - } - - const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; } - private: - const String16 mName; - const SourcePos mPos; - String16 mComment; - String16 mTypeComment; - bool mPublic; - SourcePos mPublicSourcePos; - int32_t mEntryIndex; - DefaultKeyedVector<ConfigDescription, sp<Entry> > mEntries; - }; - - class Public { - public: - Public() : sourcePos(), ident(0) { } - Public(const SourcePos& pos, - const String16& _comment, - uint32_t _ident) - : sourcePos(pos), - comment(_comment), ident(_ident) { } - Public(const Public& o) : sourcePos(o.sourcePos), - comment(o.comment), ident(o.ident) { } - ~Public() { } - - Public& operator=(const Public& o) { - sourcePos = o.sourcePos; - comment = o.comment; - ident = o.ident; - return *this; - } - - SourcePos sourcePos; - String16 comment; - uint32_t ident; - }; - - class Type : public RefBase { - public: - Type(const String16& name, const SourcePos& pos) - : mName(name), mFirstPublicSourcePos(NULL), mPublicIndex(-1), mIndex(-1), mPos(pos) - { } - virtual ~Type() { delete mFirstPublicSourcePos; } - - status_t addPublic(const SourcePos& pos, - const String16& name, - const uint32_t ident); - - void canAddEntry(const String16& name); - - String16 getName() const { return mName; } - sp<Entry> getEntry(const String16& entry, - const SourcePos& pos, - const ResTable_config* config = NULL, - bool doSetIndex = false, - bool overlay = false, - bool autoAddOverlay = false); - - const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; } - - int32_t getPublicIndex() const { return mPublicIndex; } - - int32_t getIndex() const { return mIndex; } - void setIndex(int32_t index) { mIndex = index; } - - status_t applyPublicEntryOrder(); - - const SortedVector<ConfigDescription>& getUniqueConfigs() const { return mUniqueConfigs; } - - const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; } - const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; } - - const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; } - - const SourcePos& getPos() const { return mPos; } - private: - String16 mName; - SourcePos* mFirstPublicSourcePos; - DefaultKeyedVector<String16, Public> mPublic; - SortedVector<ConfigDescription> mUniqueConfigs; - DefaultKeyedVector<String16, sp<ConfigList> > mConfigs; - Vector<sp<ConfigList> > mOrderedConfigs; - SortedVector<String16> mCanAddEntries; - int32_t mPublicIndex; - int32_t mIndex; - SourcePos mPos; - }; - - class Package : public RefBase { - public: - Package(const String16& name, ssize_t includedId=-1); - virtual ~Package() { } - - String16 getName() const { return mName; } - sp<Type> getType(const String16& type, - const SourcePos& pos, - bool doSetIndex = false); - - ssize_t getAssignedId() const { return mIncludedId; } - - const ResStringPool& getTypeStrings() const { return mTypeStrings; } - uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); } - const sp<AaptFile> getTypeStringsData() const { return mTypeStringsData; } - status_t setTypeStrings(const sp<AaptFile>& data); - - const ResStringPool& getKeyStrings() const { return mKeyStrings; } - uint32_t indexOfKeyString(const String16& s) const { return mKeyStringsMapping.valueFor(s); } - const sp<AaptFile> getKeyStringsData() const { return mKeyStringsData; } - status_t setKeyStrings(const sp<AaptFile>& data); - - status_t applyPublicTypeOrder(); - - const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; } - const Vector<sp<Type> >& getOrderedTypes() const { return mOrderedTypes; } - - private: - status_t setStrings(const sp<AaptFile>& data, - ResStringPool* strings, - DefaultKeyedVector<String16, uint32_t>* mappings); - - const String16 mName; - const ssize_t mIncludedId; - DefaultKeyedVector<String16, sp<Type> > mTypes; - Vector<sp<Type> > mOrderedTypes; - sp<AaptFile> mTypeStringsData; - sp<AaptFile> mKeyStringsData; - ResStringPool mTypeStrings; - ResStringPool mKeyStrings; - DefaultKeyedVector<String16, uint32_t> mTypeStringsMapping; - DefaultKeyedVector<String16, uint32_t> mKeyStringsMapping; - }; - -private: - void writePublicDefinitions(const String16& package, FILE* fp, bool pub); - sp<Package> getPackage(const String16& package); - sp<Type> getType(const String16& package, - const String16& type, - const SourcePos& pos, - bool doSetIndex = false); - sp<Entry> getEntry(const String16& package, - 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, - const ResTable_config* config = NULL) const; - const Item* getItem(uint32_t resID, uint32_t attrID) const; - bool getItemValue(uint32_t resID, uint32_t attrID, - Res_value* outValue); - - - String16 mAssetsPackage; - sp<AaptAssets> mAssets; - DefaultKeyedVector<String16, sp<Package> > mPackages; - Vector<sp<Package> > mOrderedPackages; - uint32_t mNextPackageId; - bool mHaveAppPackage; - bool mIsAppPackage; - size_t mNumLocal; - SourcePos mCurrentXmlPos; - Bundle* mBundle; - - // key = string resource name, value = set of locales in which that name is defined - map<String16, set<String8> > mLocalizations; -}; - -#endif diff --git a/tools/aapt/SourcePos.cpp b/tools/aapt/SourcePos.cpp deleted file mode 100644 index e2a921c..0000000 --- a/tools/aapt/SourcePos.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include "SourcePos.h" - -#include <stdarg.h> -#include <vector> - -using namespace std; - - -// ErrorPos -// ============================================================================= -struct ErrorPos -{ - String8 file; - int line; - String8 error; - bool fatal; - - ErrorPos(); - ErrorPos(const ErrorPos& that); - ErrorPos(const String8& file, int line, const String8& error, bool fatal); - ~ErrorPos(); - bool operator<(const ErrorPos& rhs) const; - bool operator==(const ErrorPos& rhs) const; - ErrorPos& operator=(const ErrorPos& rhs); - - void print(FILE* to) const; -}; - -static vector<ErrorPos> g_errors; - -ErrorPos::ErrorPos() - :line(-1), fatal(false) -{ -} - -ErrorPos::ErrorPos(const ErrorPos& that) - :file(that.file), - line(that.line), - error(that.error), - fatal(that.fatal) -{ -} - -ErrorPos::ErrorPos(const String8& f, int l, const String8& e, bool fat) - :file(f), - line(l), - error(e), - fatal(fat) -{ -} - -ErrorPos::~ErrorPos() -{ -} - -bool -ErrorPos::operator<(const ErrorPos& rhs) const -{ - if (this->file < rhs.file) return true; - if (this->file == rhs.file) { - if (this->line < rhs.line) return true; - if (this->line == rhs.line) { - if (this->error < rhs.error) return true; - } - } - return false; -} - -bool -ErrorPos::operator==(const ErrorPos& rhs) const -{ - return this->file == rhs.file - && this->line == rhs.line - && this->error == rhs.error; -} - -ErrorPos& -ErrorPos::operator=(const ErrorPos& rhs) -{ - this->file = rhs.file; - this->line = rhs.line; - this->error = rhs.error; - return *this; -} - -void -ErrorPos::print(FILE* to) const -{ - const char* type = fatal ? "error:" : "warning:"; - - if (this->line >= 0) { - fprintf(to, "%s:%d: %s %s\n", this->file.string(), this->line, type, this->error.string()); - } else { - fprintf(to, "%s: %s %s\n", this->file.string(), type, this->error.string()); - } -} - -// SourcePos -// ============================================================================= -SourcePos::SourcePos(const String8& f, int l) - : file(f), line(l) -{ -} - -SourcePos::SourcePos(const SourcePos& that) - : file(that.file), line(that.line) -{ -} - -SourcePos::SourcePos() - : file("???", 0), line(-1) -{ -} - -SourcePos::~SourcePos() -{ -} - -int -SourcePos::error(const char* fmt, ...) const -{ - int retval=0; - char buf[1024]; - va_list ap; - va_start(ap, fmt); - retval = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - char* p = buf + retval - 1; - while (p > buf && *p == '\n') { - *p = '\0'; - p--; - } - g_errors.push_back(ErrorPos(this->file, this->line, String8(buf), true)); - return retval; -} - -int -SourcePos::warning(const char* fmt, ...) const -{ - int retval=0; - char buf[1024]; - va_list ap; - va_start(ap, fmt); - retval = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - char* p = buf + retval - 1; - while (p > buf && *p == '\n') { - *p = '\0'; - p--; - } - ErrorPos(this->file, this->line, String8(buf), false).print(stderr); - return retval; -} - -bool -SourcePos::hasErrors() -{ - return g_errors.size() > 0; -} - -void -SourcePos::printErrors(FILE* to) -{ - vector<ErrorPos>::const_iterator it; - for (it=g_errors.begin(); it!=g_errors.end(); it++) { - it->print(to); - } -} - - - diff --git a/tools/aapt/SourcePos.h b/tools/aapt/SourcePos.h deleted file mode 100644 index 33f72a9..0000000 --- a/tools/aapt/SourcePos.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SOURCEPOS_H -#define SOURCEPOS_H - -#include <utils/String8.h> -#include <stdio.h> - -using namespace android; - -class SourcePos -{ -public: - String8 file; - int line; - - SourcePos(const String8& f, int l); - SourcePos(const SourcePos& that); - SourcePos(); - ~SourcePos(); - - int error(const char* fmt, ...) const; - int warning(const char* fmt, ...) const; - - static bool hasErrors(); - static void printErrors(FILE* to); -}; - - -#endif // SOURCEPOS_H diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp deleted file mode 100644 index 158b391..0000000 --- a/tools/aapt/StringPool.cpp +++ /dev/null @@ -1,574 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#include "StringPool.h" -#include "ResourceTable.h" - -#include <utils/ByteOrder.h> -#include <utils/SortedVector.h> -#include "qsort_r_compat.h" - -#if HAVE_PRINTF_ZD -# define ZD "%zd" -# define ZD_TYPE ssize_t -#else -# define ZD "%ld" -# define ZD_TYPE long -#endif - -#define NOISY(x) //x - -void strcpy16_htod(uint16_t* dst, const uint16_t* src) -{ - while (*src) { - char16_t s = htods(*src); - *dst++ = s; - src++; - } - *dst = 0; -} - -void printStringPool(const ResStringPool* pool) -{ - SortedVector<const void*> uniqueStrings; - const size_t N = pool->size(); - for (size_t i=0; i<N; i++) { - size_t len; - if (pool->isUTF8()) { - uniqueStrings.add(pool->string8At(i, &len)); - } else { - uniqueStrings.add(pool->stringAt(i, &len)); - } - } - - printf("String pool of " ZD " unique %s %s strings, " ZD " entries and " - ZD " styles using " ZD " bytes:\n", - (ZD_TYPE)uniqueStrings.size(), pool->isUTF8() ? "UTF-8" : "UTF-16", - pool->isSorted() ? "sorted" : "non-sorted", - (ZD_TYPE)N, (ZD_TYPE)pool->styleCount(), (ZD_TYPE)pool->bytes()); - - const size_t NS = pool->size(); - for (size_t s=0; s<NS; s++) { - String8 str = pool->string8ObjectAt(s); - printf("String #" ZD ": %s\n", (ZD_TYPE) s, str.string()); - } -} - -String8 StringPool::entry::makeConfigsString() const { - String8 configStr(configTypeName); - if (configStr.size() > 0) configStr.append(" "); - if (configs.size() > 0) { - for (size_t j=0; j<configs.size(); j++) { - if (j > 0) configStr.append(", "); - configStr.append(configs[j].toString()); - } - } else { - configStr = "(none)"; - } - return configStr; -} - -int StringPool::entry::compare(const entry& o) const { - // Strings with styles go first, to reduce the size of the styles array. - // We don't care about the relative order of these strings. - if (hasStyles) { - return o.hasStyles ? 0 : -1; - } - if (o.hasStyles) { - return 1; - } - - // Sort unstyled strings by type, then by logical configuration. - int comp = configTypeName.compare(o.configTypeName); - if (comp != 0) { - return comp; - } - const size_t LHN = configs.size(); - const size_t RHN = o.configs.size(); - size_t i=0; - while (i < LHN && i < RHN) { - comp = configs[i].compareLogical(o.configs[i]); - if (comp != 0) { - return comp; - } - i++; - } - if (LHN < RHN) return -1; - else if (LHN > RHN) return 1; - return 0; -} - -StringPool::StringPool(bool utf8) : - mUTF8(utf8), mValues(-1) -{ -} - -ssize_t StringPool::add(const String16& value, const Vector<entry_style_span>& spans, - const String8* configTypeName, const ResTable_config* config) -{ - ssize_t res = add(value, false, configTypeName, config); - if (res >= 0) { - addStyleSpans(res, spans); - } - return res; -} - -ssize_t StringPool::add(const String16& value, - bool mergeDuplicates, const String8* configTypeName, const ResTable_config* config) -{ - ssize_t vidx = mValues.indexOfKey(value); - ssize_t pos = vidx >= 0 ? mValues.valueAt(vidx) : -1; - ssize_t eidx = pos >= 0 ? mEntryArray.itemAt(pos) : -1; - if (eidx < 0) { - eidx = mEntries.add(entry(value)); - if (eidx < 0) { - fprintf(stderr, "Failure adding string %s\n", String8(value).string()); - return eidx; - } - } - - if (configTypeName != NULL) { - entry& ent = mEntries.editItemAt(eidx); - NOISY(printf("*** adding config type name %s, was %s\n", - configTypeName->string(), ent.configTypeName.string())); - if (ent.configTypeName.size() <= 0) { - ent.configTypeName = *configTypeName; - } else if (ent.configTypeName != *configTypeName) { - ent.configTypeName = " "; - } - } - - if (config != NULL) { - // Add this to the set of configs associated with the string. - entry& ent = mEntries.editItemAt(eidx); - size_t addPos; - for (addPos=0; addPos<ent.configs.size(); addPos++) { - int cmp = ent.configs.itemAt(addPos).compareLogical(*config); - if (cmp >= 0) { - if (cmp > 0) { - NOISY(printf("*** inserting config: %s\n", config->toString().string())); - ent.configs.insertAt(*config, addPos); - } - break; - } - } - if (addPos >= ent.configs.size()) { - NOISY(printf("*** adding config: %s\n", config->toString().string())); - ent.configs.add(*config); - } - } - - const bool first = vidx < 0; - const bool styled = (pos >= 0 && (size_t)pos < mEntryStyleArray.size()) ? - mEntryStyleArray[pos].spans.size() : 0; - if (first || styled || !mergeDuplicates) { - pos = mEntryArray.add(eidx); - if (first) { - vidx = mValues.add(value, pos); - } - entry& ent = mEntries.editItemAt(eidx); - ent.indices.add(pos); - } - - NOISY(printf("Adding string %s to pool: pos=%d eidx=%d vidx=%d\n", - String8(value).string(), pos, eidx, vidx)); - - return pos; -} - -status_t StringPool::addStyleSpan(size_t idx, const String16& name, - uint32_t start, uint32_t end) -{ - entry_style_span span; - span.name = name; - span.span.firstChar = start; - span.span.lastChar = end; - return addStyleSpan(idx, span); -} - -status_t StringPool::addStyleSpans(size_t idx, const Vector<entry_style_span>& spans) -{ - const size_t N=spans.size(); - for (size_t i=0; i<N; i++) { - status_t err = addStyleSpan(idx, spans[i]); - if (err != NO_ERROR) { - return err; - } - } - return NO_ERROR; -} - -status_t StringPool::addStyleSpan(size_t idx, const entry_style_span& span) -{ - // Place blank entries in the span array up to this index. - while (mEntryStyleArray.size() <= idx) { - mEntryStyleArray.add(); - } - - entry_style& style = mEntryStyleArray.editItemAt(idx); - style.spans.add(span); - mEntries.editItemAt(mEntryArray[idx]).hasStyles = true; - return NO_ERROR; -} - -int StringPool::config_sort(void* state, const void* lhs, const void* rhs) -{ - StringPool* pool = (StringPool*)state; - const entry& lhe = pool->mEntries[pool->mEntryArray[*static_cast<const size_t*>(lhs)]]; - const entry& rhe = pool->mEntries[pool->mEntryArray[*static_cast<const size_t*>(rhs)]]; - return lhe.compare(rhe); -} - -void StringPool::sortByConfig() -{ - LOG_ALWAYS_FATAL_IF(mOriginalPosToNewPos.size() > 0, "Can't sort string pool after already sorted."); - - const size_t N = mEntryArray.size(); - - // This is a vector that starts out with a 1:1 mapping to entries - // in the array, which we will sort to come up with the desired order. - // At that point it maps from the new position in the array to the - // original position the entry appeared. - Vector<size_t> newPosToOriginalPos; - newPosToOriginalPos.setCapacity(N); - for (size_t i=0; i < N; i++) { - newPosToOriginalPos.add(i); - } - - // Sort the array. - NOISY(printf("SORTING STRINGS BY CONFIGURATION...\n")); - // Vector::sort uses insertion sort, which is very slow for this data set. - // Use quicksort instead because we don't need a stable sort here. - qsort_r_compat(newPosToOriginalPos.editArray(), N, sizeof(size_t), this, config_sort); - //newPosToOriginalPos.sort(config_sort, this); - NOISY(printf("DONE SORTING STRINGS BY CONFIGURATION.\n")); - - // Create the reverse mapping from the original position in the array - // to the new position where it appears in the sorted array. This is - // so that clients can re-map any positions they had previously stored. - mOriginalPosToNewPos = newPosToOriginalPos; - for (size_t i=0; i<N; i++) { - mOriginalPosToNewPos.editItemAt(newPosToOriginalPos[i]) = i; - } - -#if 0 - SortedVector<entry> entries; - - for (size_t i=0; i<N; i++) { - printf("#%d was %d: %s\n", i, newPosToOriginalPos[i], - mEntries[mEntryArray[newPosToOriginalPos[i]]].makeConfigsString().string()); - entries.add(mEntries[mEntryArray[i]]); - } - - for (size_t i=0; i<entries.size(); i++) { - printf("Sorted config #%d: %s\n", i, - entries[i].makeConfigsString().string()); - } -#endif - - // Now we rebuild the arrays. - Vector<entry> newEntries; - Vector<size_t> newEntryArray; - Vector<entry_style> newEntryStyleArray; - DefaultKeyedVector<size_t, size_t> origOffsetToNewOffset; - - for (size_t i=0; i<N; i++) { - // We are filling in new offset 'i'; oldI is where we can find it - // in the original data structure. - size_t oldI = newPosToOriginalPos[i]; - // This is the actual entry associated with the old offset. - const entry& oldEnt = mEntries[mEntryArray[oldI]]; - // This is the same entry the last time we added it to the - // new entry array, if any. - ssize_t newIndexOfOffset = origOffsetToNewOffset.indexOfKey(oldI); - size_t newOffset; - if (newIndexOfOffset < 0) { - // This is the first time we have seen the entry, so add - // it. - newOffset = newEntries.add(oldEnt); - newEntries.editItemAt(newOffset).indices.clear(); - } else { - // We have seen this entry before, use the existing one - // instead of adding it again. - newOffset = origOffsetToNewOffset.valueAt(newIndexOfOffset); - } - // Update the indices to include this new position. - newEntries.editItemAt(newOffset).indices.add(i); - // And add the offset of the entry to the new entry array. - newEntryArray.add(newOffset); - // Add any old style to the new style array. - if (mEntryStyleArray.size() > 0) { - if (oldI < mEntryStyleArray.size()) { - newEntryStyleArray.add(mEntryStyleArray[oldI]); - } else { - newEntryStyleArray.add(entry_style()); - } - } - } - - // Now trim any entries at the end of the new style array that are - // not needed. - for (ssize_t i=newEntryStyleArray.size()-1; i>=0; i--) { - const entry_style& style = newEntryStyleArray[i]; - if (style.spans.size() > 0) { - // That's it. - break; - } - // This one is not needed; remove. - newEntryStyleArray.removeAt(i); - } - - // All done, install the new data structures and upate mValues with - // the new positions. - mEntries = newEntries; - mEntryArray = newEntryArray; - mEntryStyleArray = newEntryStyleArray; - mValues.clear(); - for (size_t i=0; i<mEntries.size(); i++) { - const entry& ent = mEntries[i]; - mValues.add(ent.value, ent.indices[0]); - } - -#if 0 - printf("FINAL SORTED STRING CONFIGS:\n"); - for (size_t i=0; i<mEntries.size(); i++) { - const entry& ent = mEntries[i]; - printf("#" ZD " %s: %s\n", (ZD_TYPE)i, ent.makeConfigsString().string(), - String8(ent.value).string()); - } -#endif -} - -sp<AaptFile> StringPool::createStringBlock() -{ - sp<AaptFile> pool = new AaptFile(String8(), AaptGroupEntry(), - String8()); - status_t err = writeStringBlock(pool); - return err == NO_ERROR ? pool : NULL; -} - -#define ENCODE_LENGTH(str, chrsz, strSize) \ -{ \ - size_t maxMask = 1 << ((chrsz*8)-1); \ - size_t maxSize = maxMask-1; \ - if (strSize > maxSize) { \ - *str++ = maxMask | ((strSize>>(chrsz*8))&maxSize); \ - } \ - *str++ = strSize; \ -} - -status_t StringPool::writeStringBlock(const sp<AaptFile>& pool) -{ - // Allow appending. Sorry this is a little wacky. - if (pool->getSize() > 0) { - sp<AaptFile> block = createStringBlock(); - if (block == NULL) { - return UNKNOWN_ERROR; - } - ssize_t res = pool->writeData(block->getData(), block->getSize()); - return (res >= 0) ? (status_t)NO_ERROR : res; - } - - // First we need to add all style span names to the string pool. - // We do this now (instead of when the span is added) so that these - // will appear at the end of the pool, not disrupting the order - // our client placed their own strings in it. - - const size_t STYLES = mEntryStyleArray.size(); - size_t i; - - for (i=0; i<STYLES; i++) { - entry_style& style = mEntryStyleArray.editItemAt(i); - const size_t N = style.spans.size(); - for (size_t i=0; i<N; i++) { - entry_style_span& span = style.spans.editItemAt(i); - ssize_t idx = add(span.name, true); - if (idx < 0) { - fprintf(stderr, "Error adding span for style tag '%s'\n", - String8(span.name).string()); - return idx; - } - span.span.name.index = (uint32_t)idx; - } - } - - const size_t ENTRIES = mEntryArray.size(); - - // Now build the pool of unique strings. - - const size_t STRINGS = mEntries.size(); - const size_t preSize = sizeof(ResStringPool_header) - + (sizeof(uint32_t)*ENTRIES) - + (sizeof(uint32_t)*STYLES); - if (pool->editData(preSize) == NULL) { - fprintf(stderr, "ERROR: Out of memory for string pool\n"); - return NO_MEMORY; - } - - const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(char16_t); - - size_t strPos = 0; - for (i=0; i<STRINGS; i++) { - entry& ent = mEntries.editItemAt(i); - const size_t strSize = (ent.value.size()); - const size_t lenSize = strSize > (size_t)(1<<((charSize*8)-1))-1 ? - charSize*2 : charSize; - - String8 encStr; - if (mUTF8) { - encStr = String8(ent.value); - } - - const size_t encSize = mUTF8 ? encStr.size() : 0; - const size_t encLenSize = mUTF8 ? - (encSize > (size_t)(1<<((charSize*8)-1))-1 ? - charSize*2 : charSize) : 0; - - ent.offset = strPos; - - const size_t totalSize = lenSize + encLenSize + - ((mUTF8 ? encSize : strSize)+1)*charSize; - - void* dat = (void*)pool->editData(preSize + strPos + totalSize); - if (dat == NULL) { - fprintf(stderr, "ERROR: Out of memory for string pool\n"); - return NO_MEMORY; - } - dat = (uint8_t*)dat + preSize + strPos; - if (mUTF8) { - uint8_t* strings = (uint8_t*)dat; - - ENCODE_LENGTH(strings, sizeof(uint8_t), strSize) - - ENCODE_LENGTH(strings, sizeof(uint8_t), encSize) - - strncpy((char*)strings, encStr, encSize+1); - } else { - uint16_t* strings = (uint16_t*)dat; - - ENCODE_LENGTH(strings, sizeof(uint16_t), strSize) - - strcpy16_htod(strings, ent.value); - } - - strPos += totalSize; - } - - // Pad ending string position up to a uint32_t boundary. - - if (strPos&0x3) { - size_t padPos = ((strPos+3)&~0x3); - uint8_t* dat = (uint8_t*)pool->editData(preSize + padPos); - if (dat == NULL) { - fprintf(stderr, "ERROR: Out of memory padding string pool\n"); - return NO_MEMORY; - } - memset(dat+preSize+strPos, 0, padPos-strPos); - strPos = padPos; - } - - // Build the pool of style spans. - - size_t styPos = strPos; - for (i=0; i<STYLES; i++) { - entry_style& ent = mEntryStyleArray.editItemAt(i); - const size_t N = ent.spans.size(); - const size_t totalSize = (N*sizeof(ResStringPool_span)) - + sizeof(ResStringPool_ref); - - ent.offset = styPos-strPos; - uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + totalSize); - if (dat == NULL) { - fprintf(stderr, "ERROR: Out of memory for string styles\n"); - return NO_MEMORY; - } - ResStringPool_span* span = (ResStringPool_span*)(dat+preSize+styPos); - for (size_t i=0; i<N; i++) { - span->name.index = htodl(ent.spans[i].span.name.index); - span->firstChar = htodl(ent.spans[i].span.firstChar); - span->lastChar = htodl(ent.spans[i].span.lastChar); - span++; - } - span->name.index = htodl(ResStringPool_span::END); - - styPos += totalSize; - } - - if (STYLES > 0) { - // Add full terminator at the end (when reading we validate that - // the end of the pool is fully terminated to simplify error - // checking). - size_t extra = sizeof(ResStringPool_span)-sizeof(ResStringPool_ref); - uint8_t* dat = (uint8_t*)pool->editData(preSize + styPos + extra); - if (dat == NULL) { - fprintf(stderr, "ERROR: Out of memory for string styles\n"); - return NO_MEMORY; - } - uint32_t* p = (uint32_t*)(dat+preSize+styPos); - while (extra > 0) { - *p++ = htodl(ResStringPool_span::END); - extra -= sizeof(uint32_t); - } - styPos += extra; - } - - // Write header. - - ResStringPool_header* header = - (ResStringPool_header*)pool->padData(sizeof(uint32_t)); - if (header == NULL) { - fprintf(stderr, "ERROR: Out of memory for string pool\n"); - return NO_MEMORY; - } - memset(header, 0, sizeof(*header)); - header->header.type = htods(RES_STRING_POOL_TYPE); - header->header.headerSize = htods(sizeof(*header)); - header->header.size = htodl(pool->getSize()); - header->stringCount = htodl(ENTRIES); - header->styleCount = htodl(STYLES); - if (mUTF8) { - header->flags |= htodl(ResStringPool_header::UTF8_FLAG); - } - header->stringsStart = htodl(preSize); - header->stylesStart = htodl(STYLES > 0 ? (preSize+strPos) : 0); - - // Write string index array. - - uint32_t* index = (uint32_t*)(header+1); - for (i=0; i<ENTRIES; i++) { - entry& ent = mEntries.editItemAt(mEntryArray[i]); - *index++ = htodl(ent.offset); - NOISY(printf("Writing entry #%d: \"%s\" ent=%d off=%d\n", i, - String8(ent.value).string(), - mEntryArray[i], ent.offset)); - } - - // Write style index array. - - for (i=0; i<STYLES; i++) { - *index++ = htodl(mEntryStyleArray[i].offset); - } - - return NO_ERROR; -} - -ssize_t StringPool::offsetForString(const String16& val) const -{ - const Vector<size_t>* indices = offsetsForString(val); - ssize_t res = indices != NULL && indices->size() > 0 ? indices->itemAt(0) : -1; - NOISY(printf("Offset for string %s: %d (%s)\n", String8(val).string(), res, - res >= 0 ? String8(mEntries[mEntryArray[res]].value).string() : String8())); - return res; -} - -const Vector<size_t>* StringPool::offsetsForString(const String16& val) const -{ - ssize_t pos = mValues.valueFor(val); - if (pos < 0) { - return NULL; - } - return &mEntries[mEntryArray[pos]].indices; -} diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h deleted file mode 100644 index 1b3abfd..0000000 --- a/tools/aapt/StringPool.h +++ /dev/null @@ -1,183 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#ifndef STRING_POOL_H -#define STRING_POOL_H - -#include "Main.h" -#include "AaptAssets.h" - -#include <androidfw/ResourceTypes.h> -#include <utils/String16.h> -#include <utils/TypeHelpers.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> - -#include <libexpat/expat.h> - -using namespace android; - -#define PRINT_STRING_METRICS 0 - -void strcpy16_htod(uint16_t* dst, const uint16_t* src); - -void printStringPool(const ResStringPool* pool); - -/** - * The StringPool class is used as an intermediate representation for - * generating the string pool resource data structure that can be parsed with - * ResStringPool in include/utils/ResourceTypes.h. - */ -class StringPool -{ -public: - struct entry { - entry() : offset(0) { } - entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { } - entry(const entry& o) : value(o.value), offset(o.offset), - hasStyles(o.hasStyles), indices(o.indices), - configTypeName(o.configTypeName), configs(o.configs) { } - - String16 value; - size_t offset; - bool hasStyles; - Vector<size_t> indices; - String8 configTypeName; - Vector<ResTable_config> configs; - - String8 makeConfigsString() const; - - int compare(const entry& o) const; - - inline bool operator<(const entry& o) const { return compare(o) < 0; } - inline bool operator<=(const entry& o) const { return compare(o) <= 0; } - inline bool operator==(const entry& o) const { return compare(o) == 0; } - inline bool operator!=(const entry& o) const { return compare(o) != 0; } - inline bool operator>=(const entry& o) const { return compare(o) >= 0; } - inline bool operator>(const entry& o) const { return compare(o) > 0; } - }; - - struct entry_style_span { - String16 name; - ResStringPool_span span; - }; - - struct entry_style { - entry_style() : offset(0) { } - - entry_style(const entry_style& o) : offset(o.offset), spans(o.spans) { } - - size_t offset; - Vector<entry_style_span> spans; - }; - - /** - * If 'utf8' is true, strings will be encoded with UTF-8 instead of - * left in Java's native UTF-16. - */ - explicit StringPool(bool utf8 = false); - - /** - * Add a new string to the pool. If mergeDuplicates is true, thenif - * the string already exists the existing entry for it will be used; - * otherwise, or if the value doesn't already exist, a new entry is - * created. - * - * Returns the index in the entry array of the new string entry. - */ - ssize_t add(const String16& value, bool mergeDuplicates = false, - const String8* configTypeName = NULL, const ResTable_config* config = NULL); - - ssize_t add(const String16& value, const Vector<entry_style_span>& spans, - const String8* configTypeName = NULL, const ResTable_config* config = NULL); - - status_t addStyleSpan(size_t idx, const String16& name, - uint32_t start, uint32_t end); - status_t addStyleSpans(size_t idx, const Vector<entry_style_span>& spans); - status_t addStyleSpan(size_t idx, const entry_style_span& span); - - // Sort the contents of the string block by the configuration associated - // with each item. After doing this you can use mapOriginalPosToNewPos() - // to find out the new position given the position originally returned by - // add(). - void sortByConfig(); - - // For use after sortByConfig() to map from the original position of - // a string to its new sorted position. - size_t mapOriginalPosToNewPos(size_t originalPos) const { - return mOriginalPosToNewPos.itemAt(originalPos); - } - - sp<AaptFile> createStringBlock(); - - status_t writeStringBlock(const sp<AaptFile>& pool); - - /** - * Find out an offset in the pool for a particular string. If the string - * pool is sorted, this can not be called until after createStringBlock() - * or writeStringBlock() has been called - * (which determines the offsets). In the case of a string that appears - * multiple times in the pool, the first offset will be returned. Returns - * -1 if the string does not exist. - */ - ssize_t offsetForString(const String16& val) const; - - /** - * Find all of the offsets in the pool for a particular string. If the - * string pool is sorted, this can not be called until after - * createStringBlock() or writeStringBlock() has been called - * (which determines the offsets). Returns NULL if the string does not exist. - */ - const Vector<size_t>* offsetsForString(const String16& val) const; - -private: - static int config_sort(void* state, const void* lhs, const void* rhs); - - const bool mUTF8; - - // The following data structures represent the actual structures - // that will be generated for the final string pool. - - // Raw array of unique strings, in some arbitrary order. This is the - // actual strings that appear in the final string pool, in the order - // that they will be written. - Vector<entry> mEntries; - // Array of indices into mEntries, in the order they were - // added to the pool. This can be different than mEntries - // if the same string was added multiple times (it will appear - // once in mEntries, with multiple occurrences in this array). - // This is the lookup array that will be written for finding - // the string for each offset/position in the string pool. - Vector<size_t> mEntryArray; - // Optional style span information associated with each index of - // mEntryArray. - Vector<entry_style> mEntryStyleArray; - - // The following data structures are used for book-keeping as the - // string pool is constructed. - - // Unique set of all the strings added to the pool, mapped to - // the first index of mEntryArray where the value was added. - DefaultKeyedVector<String16, ssize_t> mValues; - // This array maps from the original position a string was placed at - // in mEntryArray to its new position after being sorted with sortByConfig(). - Vector<size_t> mOriginalPosToNewPos; -}; - -// The entry types are trivially movable because all fields they contain, including -// the vectors and strings, are trivially movable. -namespace android { - ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry); - ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style_span); - ANDROID_TRIVIAL_MOVE_TRAIT(StringPool::entry_style); -}; - -#endif - diff --git a/tools/aapt/WorkQueue.cpp b/tools/aapt/WorkQueue.cpp deleted file mode 100644 index 24a962f..0000000 --- a/tools/aapt/WorkQueue.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -// #define LOG_NDEBUG 0 -#define LOG_TAG "WorkQueue" - -#include <utils/Log.h> -#include "WorkQueue.h" - -namespace android { - -// --- WorkQueue --- - -WorkQueue::WorkQueue(size_t maxThreads, bool canCallJava) : - mMaxThreads(maxThreads), mCanCallJava(canCallJava), - mCanceled(false), mFinished(false), mIdleThreads(0) { -} - -WorkQueue::~WorkQueue() { - if (!cancel()) { - finish(); - } -} - -status_t WorkQueue::schedule(WorkUnit* workUnit, size_t backlog) { - AutoMutex _l(mLock); - - if (mFinished || mCanceled) { - return INVALID_OPERATION; - } - - if (mWorkThreads.size() < mMaxThreads - && mIdleThreads < mWorkUnits.size() + 1) { - sp<WorkThread> workThread = new WorkThread(this, mCanCallJava); - status_t status = workThread->run("WorkQueue::WorkThread"); - if (status) { - return status; - } - mWorkThreads.add(workThread); - mIdleThreads += 1; - } else if (backlog) { - while (mWorkUnits.size() >= mMaxThreads * backlog) { - mWorkDequeuedCondition.wait(mLock); - if (mFinished || mCanceled) { - return INVALID_OPERATION; - } - } - } - - mWorkUnits.add(workUnit); - mWorkChangedCondition.broadcast(); - return OK; -} - -status_t WorkQueue::cancel() { - AutoMutex _l(mLock); - - return cancelLocked(); -} - -status_t WorkQueue::cancelLocked() { - if (mFinished) { - return INVALID_OPERATION; - } - - if (!mCanceled) { - mCanceled = true; - - size_t count = mWorkUnits.size(); - for (size_t i = 0; i < count; i++) { - delete mWorkUnits.itemAt(i); - } - mWorkUnits.clear(); - mWorkChangedCondition.broadcast(); - mWorkDequeuedCondition.broadcast(); - } - return OK; -} - -status_t WorkQueue::finish() { - { // acquire lock - AutoMutex _l(mLock); - - if (mFinished) { - return INVALID_OPERATION; - } - - mFinished = true; - mWorkChangedCondition.broadcast(); - } // release lock - - // It is not possible for the list of work threads to change once the mFinished - // flag has been set, so we can access mWorkThreads outside of the lock here. - size_t count = mWorkThreads.size(); - for (size_t i = 0; i < count; i++) { - mWorkThreads.itemAt(i)->join(); - } - mWorkThreads.clear(); - return OK; -} - -bool WorkQueue::threadLoop() { - WorkUnit* workUnit; - { // acquire lock - AutoMutex _l(mLock); - - for (;;) { - if (mCanceled) { - return false; - } - - if (!mWorkUnits.isEmpty()) { - workUnit = mWorkUnits.itemAt(0); - mWorkUnits.removeAt(0); - mIdleThreads -= 1; - mWorkDequeuedCondition.broadcast(); - break; - } - - if (mFinished) { - return false; - } - - mWorkChangedCondition.wait(mLock); - } - } // release lock - - bool shouldContinue = workUnit->run(); - delete workUnit; - - { // acquire lock - AutoMutex _l(mLock); - - mIdleThreads += 1; - - if (!shouldContinue) { - cancelLocked(); - return false; - } - } // release lock - - return true; -} - -// --- WorkQueue::WorkThread --- - -WorkQueue::WorkThread::WorkThread(WorkQueue* workQueue, bool canCallJava) : - Thread(canCallJava), mWorkQueue(workQueue) { -} - -WorkQueue::WorkThread::~WorkThread() { -} - -bool WorkQueue::WorkThread::threadLoop() { - return mWorkQueue->threadLoop(); -} - -}; // namespace android diff --git a/tools/aapt/WorkQueue.h b/tools/aapt/WorkQueue.h deleted file mode 100644 index d38f05d..0000000 --- a/tools/aapt/WorkQueue.h +++ /dev/null @@ -1,119 +0,0 @@ -/*] - * Copyright (C) 2012 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. - */ - -#ifndef AAPT_WORK_QUEUE_H -#define AAPT_WORK_QUEUE_H - -#include <utils/Errors.h> -#include <utils/Vector.h> -#include <utils/threads.h> - -namespace android { - -/* - * A threaded work queue. - * - * This class is designed to make it easy to run a bunch of isolated work - * units in parallel, using up to the specified number of threads. - * To use it, write a loop to post work units to the work queue, then synchronize - * on the queue at the end. - */ -class WorkQueue { -public: - class WorkUnit { - public: - WorkUnit() { } - virtual ~WorkUnit() { } - - /* - * Runs the work unit. - * If the result is 'true' then the work queue continues scheduling work as usual. - * If the result is 'false' then the work queue is canceled. - */ - virtual bool run() = 0; - }; - - /* Creates a work queue with the specified maximum number of work threads. */ - WorkQueue(size_t maxThreads, bool canCallJava = true); - - /* Destroys the work queue. - * Cancels pending work and waits for all remaining threads to complete. - */ - ~WorkQueue(); - - /* Posts a work unit to run later. - * If the work queue has been canceled or is already finished, returns INVALID_OPERATION - * and does not take ownership of the work unit (caller must destroy it itself). - * Otherwise, returns OK and takes ownership of the work unit (the work queue will - * destroy it automatically). - * - * For flow control, this method blocks when the size of the pending work queue is more - * 'backlog' times the number of threads. This condition reduces the rate of entry into - * the pending work queue and prevents it from growing much more rapidly than the - * work threads can actually handle. - * - * If 'backlog' is 0, then no throttle is applied. - */ - status_t schedule(WorkUnit* workUnit, size_t backlog = 2); - - /* Cancels all pending work. - * If the work queue is already finished, returns INVALID_OPERATION. - * If the work queue is already canceled, returns OK and does nothing else. - * Otherwise, returns OK, discards all pending work units and prevents additional - * work units from being scheduled. - * - * Call finish() after cancel() to wait for all remaining work to complete. - */ - status_t cancel(); - - /* Waits for all work to complete. - * If the work queue is already finished, returns INVALID_OPERATION. - * Otherwise, waits for all work to complete and returns OK. - */ - status_t finish(); - -private: - class WorkThread : public Thread { - public: - WorkThread(WorkQueue* workQueue, bool canCallJava); - virtual ~WorkThread(); - - private: - virtual bool threadLoop(); - - WorkQueue* const mWorkQueue; - }; - - status_t cancelLocked(); - bool threadLoop(); // called from each work thread - - const size_t mMaxThreads; - const bool mCanCallJava; - - Mutex mLock; - Condition mWorkChangedCondition; - Condition mWorkDequeuedCondition; - - bool mCanceled; - bool mFinished; - size_t mIdleThreads; - Vector<sp<WorkThread> > mWorkThreads; - Vector<WorkUnit*> mWorkUnits; -}; - -}; // namespace android - -#endif // AAPT_WORK_QUEUE_H diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp deleted file mode 100644 index a663ad5..0000000 --- a/tools/aapt/XMLNode.cpp +++ /dev/null @@ -1,1510 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#include "XMLNode.h" -#include "ResourceTable.h" -#include "pseudolocalize.h" - -#include <utils/ByteOrder.h> -#include <errno.h> -#include <string.h> - -#ifndef HAVE_MS_C_RUNTIME -#define O_BINARY 0 -#endif - -#define NOISY(x) //x -#define NOISY_PARSE(x) //x - -const char* const RESOURCES_ROOT_NAMESPACE = "http://schemas.android.com/apk/res/"; -const char* const RESOURCES_ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android"; -const char* const RESOURCES_AUTO_PACKAGE_NAMESPACE = "http://schemas.android.com/apk/res-auto"; -const char* const RESOURCES_ROOT_PRV_NAMESPACE = "http://schemas.android.com/apk/prv/res/"; - -const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2"; -const char* const ALLOWED_XLIFF_ELEMENTS[] = { - "bpt", - "ept", - "it", - "ph", - "g", - "bx", - "ex", - "x" - }; - -bool isWhitespace(const char16_t* str) -{ - while (*str != 0 && *str < 128 && isspace(*str)) { - str++; - } - return *str == 0; -} - -static const String16 RESOURCES_PREFIX(RESOURCES_ROOT_NAMESPACE); -static const String16 RESOURCES_PREFIX_AUTO_PACKAGE(RESOURCES_AUTO_PACKAGE_NAMESPACE); -static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE); -static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools"); - -String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic) -{ - //printf("%s starts with %s?\n", String8(namespaceUri).string(), - // String8(RESOURCES_PREFIX).string()); - size_t prefixSize; - bool isPublic = true; - if(namespaceUri.startsWith(RESOURCES_PREFIX_AUTO_PACKAGE)) { - NOISY(printf("Using default application package: %s -> %s\n", String8(namespaceUri).string(), String8(appPackage).string())); - isPublic = true; - return appPackage; - } else if (namespaceUri.startsWith(RESOURCES_PREFIX)) { - prefixSize = RESOURCES_PREFIX.size(); - } else if (namespaceUri.startsWith(RESOURCES_PRV_PREFIX)) { - isPublic = false; - prefixSize = RESOURCES_PRV_PREFIX.size(); - } else { - if (outIsPublic) *outIsPublic = isPublic; // = true - return String16(); - } - - //printf("YES!\n"); - //printf("namespace: %s\n", String8(String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize)).string()); - if (outIsPublic) *outIsPublic = isPublic; - 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; - String16 curString; - String16 rawString; - const char* errorMsg; - int xliffDepth = 0; - bool firstTime = true; - - size_t len; - ResXMLTree::event_code_t code; - while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - - if (code == ResXMLTree::TEXT) { - String16 text(inXml->getText(&len)); - if (firstTime && text.size() > 0) { - firstTime = false; - if (text.string()[0] == '@') { - // If this is a resource reference, don't do the pseudoloc. - pseudolocalize = false; - } - } - if (xliffDepth == 0 && pseudolocalize) { - std::string orig(String8(text).string()); - std::string pseudo = pseudolocalize_string(orig); - curString.append(String16(String8(pseudo.c_str()))); - } else { - 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)); - const String8 element8(element16); - - size_t nslen; - const uint16_t* ns = inXml->getElementNamespace(&nslen); - if (ns == NULL) { - ns = (const uint16_t*)"\0\0"; - nslen = 0; - } - const String8 nspace(String16(ns, nslen)); - if (nspace == XLIFF_XMLNS) { - const int N = sizeof(ALLOWED_XLIFF_ELEMENTS)/sizeof(ALLOWED_XLIFF_ELEMENTS[0]); - for (int i=0; i<N; i++) { - if (element8 == ALLOWED_XLIFF_ELEMENTS[i]) { - xliffDepth++; - // in this case, treat it like it was just text, in other words, do nothing - // here and silently drop this element - goto moveon; - } - } - { - SourcePos(String8(fileName), inXml->getLineNumber()).error( - "Found unsupported XLIFF tag <%s>\n", - element8.string()); - return UNKNOWN_ERROR; - } -moveon: - continue; - } - - if (outSpans == NULL) { - SourcePos(String8(fileName), inXml->getLineNumber()).error( - "Found style tag <%s> where styles are not allowed\n", element8.string()); - return UNKNOWN_ERROR; - } - - if (!ResTable::collectString(outString, curString.string(), - curString.size(), false, &errorMsg, true)) { - SourcePos(String8(fileName), inXml->getLineNumber()).error("%s (in %s)\n", - errorMsg, String8(curString).string()); - return UNKNOWN_ERROR; - } - rawString.append(curString); - curString = String16(); - - StringPool::entry_style_span span; - span.name = element16; - for (size_t ai=0; ai<inXml->getAttributeCount(); ai++) { - span.name.append(String16(";")); - const char16_t* str = inXml->getAttributeName(ai, &len); - span.name.append(str, len); - span.name.append(String16("=")); - str = inXml->getAttributeStringValue(ai, &len); - span.name.append(str, len); - } - //printf("Span: %s\n", String8(span.name).string()); - span.span.firstChar = span.span.lastChar = outString->size(); - spanStack.push(span); - - } else if (code == ResXMLTree::END_TAG) { - size_t nslen; - const uint16_t* ns = inXml->getElementNamespace(&nslen); - if (ns == NULL) { - ns = (const uint16_t*)"\0\0"; - nslen = 0; - } - const String8 nspace(String16(ns, nslen)); - if (nspace == XLIFF_XMLNS) { - xliffDepth--; - continue; - } - if (!ResTable::collectString(outString, curString.string(), - curString.size(), false, &errorMsg, true)) { - SourcePos(String8(fileName), inXml->getLineNumber()).error("%s (in %s)\n", - errorMsg, String8(curString).string()); - return UNKNOWN_ERROR; - } - rawString.append(curString); - curString = String16(); - - if (spanStack.size() == 0) { - if (strcmp16(inXml->getElementName(&len), endTag.string()) != 0) { - SourcePos(String8(fileName), inXml->getLineNumber()).error( - "Found tag %s where <%s> close is expected\n", - String8(inXml->getElementName(&len)).string(), - String8(endTag).string()); - return UNKNOWN_ERROR; - } - break; - } - StringPool::entry_style_span span = spanStack.top(); - String16 spanTag; - ssize_t semi = span.name.findFirst(';'); - if (semi >= 0) { - spanTag.setTo(span.name.string(), semi); - } else { - spanTag.setTo(span.name); - } - if (strcmp16(inXml->getElementName(&len), spanTag.string()) != 0) { - SourcePos(String8(fileName), inXml->getLineNumber()).error( - "Found close tag %s where close tag %s is expected\n", - String8(inXml->getElementName(&len)).string(), - String8(spanTag).string()); - return UNKNOWN_ERROR; - } - bool empty = true; - if (outString->size() > 0) { - span.span.lastChar = outString->size()-1; - if (span.span.lastChar >= span.span.firstChar) { - empty = false; - outSpans->add(span); - } - } - spanStack.pop(); - - /* - * This warning seems to be just an irritation to most people, - * since it is typically introduced by translators who then never - * see the warning. - */ - if (0 && empty) { - fprintf(stderr, "%s:%d: warning: empty '%s' span found in text '%s'\n", - fileName, inXml->getLineNumber(), - String8(spanTag).string(), String8(*outString).string()); - - } - } else if (code == ResXMLTree::START_NAMESPACE) { - // nothing - } - } - - if (code == ResXMLTree::BAD_DOCUMENT) { - SourcePos(String8(fileName), inXml->getLineNumber()).error( - "Error parsing XML\n"); - } - - if (outSpans != NULL && outSpans->size() > 0) { - if (curString.size() > 0) { - if (!ResTable::collectString(outString, curString.string(), - curString.size(), false, &errorMsg, true)) { - SourcePos(String8(fileName), inXml->getLineNumber()).error( - "%s (in %s)\n", - errorMsg, String8(curString).string()); - return UNKNOWN_ERROR; - } - } - } else { - // There is no style information, so string processing will happen - // later as part of the overall type conversion. Return to the - // client the raw unprocessed text. - rawString.append(curString); - outString->setTo(rawString); - } - - return NO_ERROR; -} - -struct namespace_entry { - String8 prefix; - String8 uri; -}; - -static String8 make_prefix(int depth) -{ - String8 prefix; - int i; - for (i=0; i<depth; i++) { - prefix.append(" "); - } - return prefix; -} - -static String8 build_namespace(const Vector<namespace_entry>& namespaces, - const uint16_t* ns) -{ - String8 str; - if (ns != NULL) { - str = String8(ns); - const size_t N = namespaces.size(); - for (size_t i=0; i<N; i++) { - const namespace_entry& ne = namespaces.itemAt(i); - if (ne.uri == str) { - str = ne.prefix; - break; - } - } - str.append(":"); - } - return str; -} - -void printXMLBlock(ResXMLTree* block) -{ - block->restart(); - - Vector<namespace_entry> namespaces; - - ResXMLTree::event_code_t code; - int depth = 0; - while ((code=block->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - String8 prefix = make_prefix(depth); - int i; - if (code == ResXMLTree::START_TAG) { - size_t len; - const uint16_t* ns16 = block->getElementNamespace(&len); - String8 elemNs = build_namespace(namespaces, ns16); - const uint16_t* com16 = block->getComment(&len); - if (com16) { - printf("%s <!-- %s -->\n", prefix.string(), String8(com16).string()); - } - printf("%sE: %s%s (line=%d)\n", prefix.string(), elemNs.string(), - String8(block->getElementName(&len)).string(), - block->getLineNumber()); - int N = block->getAttributeCount(); - depth++; - prefix = make_prefix(depth); - for (i=0; i<N; i++) { - uint32_t res = block->getAttributeNameResID(i); - ns16 = block->getAttributeNamespace(i, &len); - String8 ns = build_namespace(namespaces, ns16); - String8 name(block->getAttributeName(i, &len)); - printf("%sA: ", prefix.string()); - if (res) { - printf("%s%s(0x%08x)", ns.string(), name.string(), res); - } else { - printf("%s%s", ns.string(), name.string()); - } - Res_value value; - block->getAttributeValue(i, &value); - if (value.dataType == Res_value::TYPE_NULL) { - printf("=(null)"); - } else if (value.dataType == Res_value::TYPE_REFERENCE) { - printf("=@0x%x", (int)value.data); - } else if (value.dataType == Res_value::TYPE_ATTRIBUTE) { - printf("=?0x%x", (int)value.data); - } else if (value.dataType == Res_value::TYPE_STRING) { - printf("=\"%s\"", - ResTable::normalizeForOutput(String8(block->getAttributeStringValue(i, - &len)).string()).string()); - } else { - printf("=(type 0x%x)0x%x", (int)value.dataType, (int)value.data); - } - const char16_t* val = block->getAttributeStringValue(i, &len); - if (val != NULL) { - printf(" (Raw: \"%s\")", ResTable::normalizeForOutput(String8(val).string()). - string()); - } - printf("\n"); - } - } else if (code == ResXMLTree::END_TAG) { - depth--; - } else if (code == ResXMLTree::START_NAMESPACE) { - namespace_entry ns; - size_t len; - const uint16_t* prefix16 = block->getNamespacePrefix(&len); - if (prefix16) { - ns.prefix = String8(prefix16); - } else { - ns.prefix = "<DEF>"; - } - ns.uri = String8(block->getNamespaceUri(&len)); - namespaces.push(ns); - printf("%sN: %s=%s\n", prefix.string(), ns.prefix.string(), - ns.uri.string()); - depth++; - } else if (code == ResXMLTree::END_NAMESPACE) { - depth--; - const namespace_entry& ns = namespaces.top(); - size_t len; - const uint16_t* prefix16 = block->getNamespacePrefix(&len); - String8 pr; - if (prefix16) { - pr = String8(prefix16); - } else { - pr = "<DEF>"; - } - if (ns.prefix != pr) { - prefix = make_prefix(depth); - printf("%s*** BAD END NS PREFIX: found=%s, expected=%s\n", - prefix.string(), pr.string(), ns.prefix.string()); - } - String8 uri = String8(block->getNamespaceUri(&len)); - if (ns.uri != uri) { - prefix = make_prefix(depth); - printf("%s *** BAD END NS URI: found=%s, expected=%s\n", - prefix.string(), uri.string(), ns.uri.string()); - } - namespaces.pop(); - } else if (code == ResXMLTree::TEXT) { - size_t len; - printf("%sC: \"%s\"\n", prefix.string(), - ResTable::normalizeForOutput(String8(block->getText(&len)).string()).string()); - } - } - - block->restart(); -} - -status_t parseXMLResource(const sp<AaptFile>& file, ResXMLTree* outTree, - bool stripAll, bool keepComments, - const char** cDataTags) -{ - sp<XMLNode> root = XMLNode::parse(file); - if (root == NULL) { - return UNKNOWN_ERROR; - } - root->removeWhitespace(stripAll, cDataTags); - - NOISY(printf("Input XML from %s:\n", (const char*)file->getPrintableSource())); - NOISY(root->print()); - sp<AaptFile> rsc = new AaptFile(String8(), AaptGroupEntry(), String8()); - status_t err = root->flatten(rsc, !keepComments, false); - if (err != NO_ERROR) { - return err; - } - err = outTree->setTo(rsc->getData(), rsc->getSize(), true); - if (err != NO_ERROR) { - return err; - } - - NOISY(printf("Output XML:\n")); - NOISY(printXMLBlock(outTree)); - - return NO_ERROR; -} - -sp<XMLNode> XMLNode::parse(const sp<AaptFile>& file) -{ - char buf[16384]; - int fd = open(file->getSourceFile().string(), O_RDONLY | O_BINARY); - if (fd < 0) { - SourcePos(file->getSourceFile(), -1).error("Unable to open file for read: %s", - strerror(errno)); - return NULL; - } - - XML_Parser parser = XML_ParserCreateNS(NULL, 1); - ParseState state; - state.filename = file->getPrintableSource(); - state.parser = parser; - XML_SetUserData(parser, &state); - XML_SetElementHandler(parser, startElement, endElement); - XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace); - XML_SetCharacterDataHandler(parser, characterData); - XML_SetCommentHandler(parser, commentData); - - ssize_t len; - bool done; - do { - len = read(fd, buf, sizeof(buf)); - done = len < (ssize_t)sizeof(buf); - if (len < 0) { - SourcePos(file->getSourceFile(), -1).error("Error reading file: %s\n", strerror(errno)); - close(fd); - return NULL; - } - if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) { - SourcePos(file->getSourceFile(), (int)XML_GetCurrentLineNumber(parser)).error( - "Error parsing XML: %s\n", XML_ErrorString(XML_GetErrorCode(parser))); - close(fd); - return NULL; - } - } while (!done); - - XML_ParserFree(parser); - if (state.root == NULL) { - SourcePos(file->getSourceFile(), -1).error("No XML data generated when parsing"); - } - close(fd); - return state.root; -} - -XMLNode::XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace) - : mNextAttributeIndex(0x80000000) - , mFilename(filename) - , mStartLineNumber(0) - , mEndLineNumber(0) - , mUTF8(false) -{ - if (isNamespace) { - mNamespacePrefix = s1; - mNamespaceUri = s2; - } else { - mNamespaceUri = s1; - mElementName = s2; - } -} - -XMLNode::XMLNode(const String8& filename) - : mFilename(filename) -{ - memset(&mCharsValue, 0, sizeof(mCharsValue)); -} - -XMLNode::type XMLNode::getType() const -{ - if (mElementName.size() != 0) { - return TYPE_ELEMENT; - } - if (mNamespaceUri.size() != 0) { - return TYPE_NAMESPACE; - } - return TYPE_CDATA; -} - -const String16& XMLNode::getNamespacePrefix() const -{ - return mNamespacePrefix; -} - -const String16& XMLNode::getNamespaceUri() const -{ - return mNamespaceUri; -} - -const String16& XMLNode::getElementNamespace() const -{ - return mNamespaceUri; -} - -const String16& XMLNode::getElementName() const -{ - return mElementName; -} - -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; -} - -XMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns, - const String16& name) -{ - for (size_t i=0; i<mAttributes.size(); i++) { - attribute_entry * ae = &mAttributes.editItemAt(i); - if (ae->ns == ns && ae->name == name) { - return ae; - } - } - - return NULL; -} - -const String16& XMLNode::getCData() const -{ - return mChars; -} - -const String16& XMLNode::getComment() const -{ - return mComment; -} - -int32_t XMLNode::getStartLineNumber() const -{ - return mStartLineNumber; -} - -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) { - SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node."); - return UNKNOWN_ERROR; - } - //printf("Adding child %p to parent %p\n", child.get(), this); - mChildren.add(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) -{ - if (getType() == TYPE_CDATA) { - SourcePos(mFilename, getStartLineNumber()).error("Child to CDATA node."); - return UNKNOWN_ERROR; - } - - if (ns != RESOURCES_TOOLS_NAMESPACE) { - attribute_entry e; - e.index = mNextAttributeIndex++; - e.ns = ns; - e.name = name; - e.string = value; - mAttributes.add(e); - mAttributeOrder.add(e.index, mAttributes.size()-1); - } - return NO_ERROR; -} - -void XMLNode::setAttributeResID(size_t attrIdx, uint32_t resId) -{ - attribute_entry& e = mAttributes.editItemAt(attrIdx); - if (e.nameResId) { - mAttributeOrder.removeItem(e.nameResId); - } else { - mAttributeOrder.removeItem(e.index); - } - NOISY(printf("Elem %s %s=\"%s\": set res id = 0x%08x\n", - String8(getElementName()).string(), - String8(mAttributes.itemAt(attrIdx).name).string(), - String8(mAttributes.itemAt(attrIdx).string).string(), - resId)); - mAttributes.editItemAt(attrIdx).nameResId = resId; - mAttributeOrder.add(resId, attrIdx); -} - -status_t XMLNode::appendChars(const String16& chars) -{ - if (getType() != TYPE_CDATA) { - SourcePos(mFilename, getStartLineNumber()).error("Adding characters to element node."); - return UNKNOWN_ERROR; - } - mChars.append(chars); - return NO_ERROR; -} - -status_t XMLNode::appendComment(const String16& comment) -{ - if (mComment.size() > 0) { - mComment.append(String16("\n")); - } - mComment.append(comment); - return NO_ERROR; -} - -void XMLNode::setStartLineNumber(int32_t line) -{ - mStartLineNumber = line; -} - -void XMLNode::setEndLineNumber(int32_t line) -{ - mEndLineNumber = line; -} - -void XMLNode::removeWhitespace(bool stripAll, const char** cDataTags) -{ - //printf("Removing whitespace in %s\n", String8(mElementName).string()); - size_t N = mChildren.size(); - if (cDataTags) { - String8 tag(mElementName); - const char** p = cDataTags; - while (*p) { - if (tag == *p) { - stripAll = false; - break; - } - } - } - for (size_t i=0; i<N; i++) { - sp<XMLNode> node = mChildren.itemAt(i); - if (node->getType() == TYPE_CDATA) { - // This is a CDATA node... - const char16_t* p = node->mChars.string(); - while (*p != 0 && *p < 128 && isspace(*p)) { - p++; - } - //printf("Space ends at %d in \"%s\"\n", - // (int)(p-node->mChars.string()), - // String8(node->mChars).string()); - if (*p == 0) { - if (stripAll) { - // Remove this node! - mChildren.removeAt(i); - N--; - i--; - } else { - node->mChars = String16(" "); - } - } else { - // Compact leading/trailing whitespace. - const char16_t* e = node->mChars.string()+node->mChars.size()-1; - while (e > p && *e < 128 && isspace(*e)) { - e--; - } - if (p > node->mChars.string()) { - p--; - } - if (e < (node->mChars.string()+node->mChars.size()-1)) { - e++; - } - if (p > node->mChars.string() || - e < (node->mChars.string()+node->mChars.size()-1)) { - String16 tmp(p, e-p+1); - node->mChars = tmp; - } - } - } else { - node->removeWhitespace(stripAll, cDataTags); - } - } -} - -status_t XMLNode::parseValues(const sp<AaptAssets>& assets, - ResourceTable* table) -{ - bool hasErrors = false; - - if (getType() == TYPE_ELEMENT) { - const size_t N = mAttributes.size(); - String16 defPackage(assets->getPackage()); - for (size_t i=0; i<N; i++) { - attribute_entry& e = mAttributes.editItemAt(i); - AccessorCookie ac(SourcePos(mFilename, getStartLineNumber()), String8(e.name), - String8(e.string)); - table->setCurrentXmlPos(SourcePos(mFilename, getStartLineNumber())); - if (!assets->getIncludedResources() - .stringToValue(&e.value, &e.string, - e.string.string(), e.string.size(), true, true, - e.nameResId, NULL, &defPackage, table, &ac)) { - hasErrors = true; - } - NOISY(printf("Attr %s: type=0x%x, str=%s\n", - String8(e.name).string(), e.value.dataType, - String8(e.string).string())); - } - } - const size_t N = mChildren.size(); - for (size_t i=0; i<N; i++) { - status_t err = mChildren.itemAt(i)->parseValues(assets, table); - if (err != NO_ERROR) { - hasErrors = true; - } - } - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -status_t XMLNode::assignResourceIds(const sp<AaptAssets>& assets, - const ResourceTable* table) -{ - bool hasErrors = false; - - if (getType() == TYPE_ELEMENT) { - String16 attr("attr"); - const char* errorMsg; - const size_t N = mAttributes.size(); - for (size_t i=0; i<N; i++) { - const attribute_entry& e = mAttributes.itemAt(i); - if (e.ns.size() <= 0) continue; - bool nsIsPublic; - String16 pkg(getNamespaceResourcePackage(String16(assets->getPackage()), e.ns, &nsIsPublic)); - NOISY(printf("Elem %s %s=\"%s\": namespace(%s) %s ===> %s\n", - String8(getElementName()).string(), - String8(e.name).string(), - String8(e.string).string(), - String8(e.ns).string(), - (nsIsPublic) ? "public" : "private", - String8(pkg).string())); - if (pkg.size() <= 0) continue; - uint32_t res = table != NULL - ? table->getResId(e.name, &attr, &pkg, &errorMsg, nsIsPublic) - : assets->getIncludedResources(). - identifierForName(e.name.string(), e.name.size(), - attr.string(), attr.size(), - pkg.string(), pkg.size()); - if (res != 0) { - NOISY(printf("XML attribute name %s: resid=0x%08x\n", - String8(e.name).string(), res)); - setAttributeResID(i, res); - } else { - SourcePos(mFilename, getStartLineNumber()).error( - "No resource identifier found for attribute '%s' in package '%s'\n", - String8(e.name).string(), String8(pkg).string()); - hasErrors = true; - } - } - } - const size_t N = mChildren.size(); - for (size_t i=0; i<N; i++) { - status_t err = mChildren.itemAt(i)->assignResourceIds(assets, table); - if (err < NO_ERROR) { - hasErrors = true; - } - } - - return hasErrors ? UNKNOWN_ERROR : NO_ERROR; -} - -status_t XMLNode::flatten(const sp<AaptFile>& dest, - bool stripComments, bool stripRawValues) const -{ - StringPool strings(mUTF8); - Vector<uint32_t> resids; - - // First collect just the strings for attribute names that have a - // resource ID assigned to them. This ensures that the resource ID - // array is compact, and makes it easier to deal with attribute names - // in different namespaces (and thus with different resource IDs). - collect_resid_strings(&strings, &resids); - - // Next collect all remainibng strings. - collect_strings(&strings, &resids, stripComments, stripRawValues); - -#if 0 // No longer compiles - NOISY(printf("Found strings:\n"); - const size_t N = strings.size(); - for (size_t i=0; i<N; i++) { - printf("%s\n", String8(strings.entryAt(i).string).string()); - } - ); -#endif - - sp<AaptFile> stringPool = strings.createStringBlock(); - NOISY(aout << "String pool:" - << HexDump(stringPool->getData(), stringPool->getSize()) << endl); - - ResXMLTree_header header; - memset(&header, 0, sizeof(header)); - header.header.type = htods(RES_XML_TYPE); - header.header.headerSize = htods(sizeof(header)); - - const size_t basePos = dest->getSize(); - dest->writeData(&header, sizeof(header)); - dest->writeData(stringPool->getData(), stringPool->getSize()); - - // If we have resource IDs, write them. - if (resids.size() > 0) { - const size_t resIdsPos = dest->getSize(); - const size_t resIdsSize = - sizeof(ResChunk_header)+(sizeof(uint32_t)*resids.size()); - ResChunk_header* idsHeader = (ResChunk_header*) - (((const uint8_t*)dest->editData(resIdsPos+resIdsSize))+resIdsPos); - idsHeader->type = htods(RES_XML_RESOURCE_MAP_TYPE); - idsHeader->headerSize = htods(sizeof(*idsHeader)); - idsHeader->size = htodl(resIdsSize); - uint32_t* ids = (uint32_t*)(idsHeader+1); - for (size_t i=0; i<resids.size(); i++) { - *ids++ = htodl(resids[i]); - } - } - - flatten_node(strings, dest, stripComments, stripRawValues); - - void* data = dest->editData(); - ResXMLTree_header* hd = (ResXMLTree_header*)(((uint8_t*)data)+basePos); - size_t size = dest->getSize()-basePos; - hd->header.size = htodl(dest->getSize()-basePos); - - NOISY(aout << "XML resource:" - << HexDump(dest->getData(), dest->getSize()) << endl); - - #if PRINT_STRING_METRICS - fprintf(stderr, "**** total xml size: %d / %d%% strings (in %s)\n", - dest->getSize(), (stringPool->getSize()*100)/dest->getSize(), - dest->getPath().string()); - #endif - - return NO_ERROR; -} - -void XMLNode::print(int indent) -{ - String8 prefix; - int i; - for (i=0; i<indent; i++) { - prefix.append(" "); - } - if (getType() == TYPE_ELEMENT) { - String8 elemNs(getNamespaceUri()); - if (elemNs.size() > 0) { - elemNs.append(":"); - } - printf("%s E: %s%s", prefix.string(), - elemNs.string(), String8(getElementName()).string()); - int N = mAttributes.size(); - for (i=0; i<N; i++) { - ssize_t idx = mAttributeOrder.valueAt(i); - if (i == 0) { - printf(" / "); - } else { - printf(", "); - } - const attribute_entry& attr = mAttributes.itemAt(idx); - String8 attrNs(attr.ns); - if (attrNs.size() > 0) { - attrNs.append(":"); - } - if (attr.nameResId) { - printf("%s%s(0x%08x)", attrNs.string(), - String8(attr.name).string(), attr.nameResId); - } else { - printf("%s%s", attrNs.string(), String8(attr.name).string()); - } - printf("=%s", String8(attr.string).string()); - } - printf("\n"); - } else if (getType() == TYPE_NAMESPACE) { - printf("%s N: %s=%s\n", prefix.string(), - getNamespacePrefix().size() > 0 - ? String8(getNamespacePrefix()).string() : "<DEF>", - String8(getNamespaceUri()).string()); - } else { - printf("%s C: \"%s\"\n", prefix.string(), String8(getCData()).string()); - } - int N = mChildren.size(); - for (i=0; i<N; i++) { - mChildren.itemAt(i)->print(indent+1); - } -} - -static void splitName(const char* name, String16* outNs, String16* outName) -{ - const char* p = name; - while (*p != 0 && *p != 1) { - p++; - } - if (*p == 0) { - *outNs = String16(); - *outName = String16(name); - } else { - *outNs = String16(name, (p-name)); - *outName = String16(p+1); - } -} - -void XMLCALL -XMLNode::startNamespace(void *userData, const char *prefix, const char *uri) -{ - NOISY_PARSE(printf("Start Namespace: %s %s\n", prefix, uri)); - ParseState* st = (ParseState*)userData; - sp<XMLNode> node = XMLNode::newNamespace(st->filename, - String16(prefix != NULL ? prefix : ""), String16(uri)); - node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser)); - if (st->stack.size() > 0) { - st->stack.itemAt(st->stack.size()-1)->addChild(node); - } else { - st->root = node; - } - st->stack.push(node); -} - -void XMLCALL -XMLNode::startElement(void *userData, const char *name, const char **atts) -{ - NOISY_PARSE(printf("Start Element: %s\n", name)); - ParseState* st = (ParseState*)userData; - String16 ns16, name16; - splitName(name, &ns16, &name16); - sp<XMLNode> node = XMLNode::newElement(st->filename, ns16, name16); - node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser)); - if (st->pendingComment.size() > 0) { - node->appendComment(st->pendingComment); - st->pendingComment = String16(); - } - if (st->stack.size() > 0) { - st->stack.itemAt(st->stack.size()-1)->addChild(node); - } else { - st->root = node; - } - st->stack.push(node); - - for (int i = 0; atts[i]; i += 2) { - splitName(atts[i], &ns16, &name16); - node->addAttribute(ns16, name16, String16(atts[i+1])); - } -} - -void XMLCALL -XMLNode::characterData(void *userData, const XML_Char *s, int len) -{ - NOISY_PARSE(printf("CDATA: \"%s\"\n", String8(s, len).string())); - ParseState* st = (ParseState*)userData; - sp<XMLNode> node = NULL; - if (st->stack.size() == 0) { - return; - } - sp<XMLNode> parent = st->stack.itemAt(st->stack.size()-1); - if (parent != NULL && parent->getChildren().size() > 0) { - node = parent->getChildren()[parent->getChildren().size()-1]; - if (node->getType() != TYPE_CDATA) { - // Last node is not CDATA, need to make a new node. - node = NULL; - } - } - - if (node == NULL) { - node = XMLNode::newCData(st->filename); - node->setStartLineNumber(XML_GetCurrentLineNumber(st->parser)); - parent->addChild(node); - } - - node->appendChars(String16(s, len)); -} - -void XMLCALL -XMLNode::endElement(void *userData, const char *name) -{ - NOISY_PARSE(printf("End Element: %s\n", name)); - ParseState* st = (ParseState*)userData; - sp<XMLNode> node = st->stack.itemAt(st->stack.size()-1); - node->setEndLineNumber(XML_GetCurrentLineNumber(st->parser)); - if (st->pendingComment.size() > 0) { - node->appendComment(st->pendingComment); - st->pendingComment = String16(); - } - String16 ns16, name16; - splitName(name, &ns16, &name16); - LOG_ALWAYS_FATAL_IF(node->getElementNamespace() != ns16 - || node->getElementName() != name16, - "Bad end element %s", name); - st->stack.pop(); -} - -void XMLCALL -XMLNode::endNamespace(void *userData, const char *prefix) -{ - const char* nonNullPrefix = prefix != NULL ? prefix : ""; - NOISY_PARSE(printf("End Namespace: %s\n", prefix)); - ParseState* st = (ParseState*)userData; - sp<XMLNode> node = st->stack.itemAt(st->stack.size()-1); - node->setEndLineNumber(XML_GetCurrentLineNumber(st->parser)); - LOG_ALWAYS_FATAL_IF(node->getNamespacePrefix() != String16(nonNullPrefix), - "Bad end namespace %s", prefix); - st->stack.pop(); -} - -void XMLCALL -XMLNode::commentData(void *userData, const char *comment) -{ - NOISY_PARSE(printf("Comment: %s\n", comment)); - ParseState* st = (ParseState*)userData; - if (st->pendingComment.size() > 0) { - st->pendingComment.append(String16("\n")); - } - st->pendingComment.append(String16(comment)); -} - -status_t XMLNode::collect_strings(StringPool* dest, Vector<uint32_t>* outResIds, - bool stripComments, bool stripRawValues) const -{ - collect_attr_strings(dest, outResIds, true); - - int i; - if (RESOURCES_TOOLS_NAMESPACE != mNamespaceUri) { - if (mNamespacePrefix.size() > 0) { - dest->add(mNamespacePrefix, true); - } - if (mNamespaceUri.size() > 0) { - dest->add(mNamespaceUri, true); - } - } - if (mElementName.size() > 0) { - dest->add(mElementName, true); - } - - if (!stripComments && mComment.size() > 0) { - dest->add(mComment, true); - } - - const int NA = mAttributes.size(); - - for (i=0; i<NA; i++) { - const attribute_entry& ae = mAttributes.itemAt(i); - if (ae.ns.size() > 0) { - dest->add(ae.ns, true); - } - if (!stripRawValues || ae.needStringValue()) { - dest->add(ae.string, true); - } - /* - if (ae.value.dataType == Res_value::TYPE_NULL - || ae.value.dataType == Res_value::TYPE_STRING) { - dest->add(ae.string, true); - } - */ - } - - if (mElementName.size() == 0) { - // If not an element, include the CDATA, even if it is empty. - dest->add(mChars, true); - } - - const int NC = mChildren.size(); - - for (i=0; i<NC; i++) { - mChildren.itemAt(i)->collect_strings(dest, outResIds, - stripComments, stripRawValues); - } - - return NO_ERROR; -} - -status_t XMLNode::collect_attr_strings(StringPool* outPool, - Vector<uint32_t>* outResIds, bool allAttrs) const { - const int NA = mAttributes.size(); - - for (int i=0; i<NA; i++) { - const attribute_entry& attr = mAttributes.itemAt(i); - uint32_t id = attr.nameResId; - if (id || allAttrs) { - // See if we have already assigned this resource ID to a pooled - // string... - const Vector<size_t>* indices = outPool->offsetsForString(attr.name); - ssize_t idx = -1; - if (indices != NULL) { - const int NJ = indices->size(); - const size_t NR = outResIds->size(); - for (int j=0; j<NJ; j++) { - size_t strIdx = indices->itemAt(j); - if (strIdx >= NR) { - if (id == 0) { - // We don't need to assign a resource ID for this one. - idx = strIdx; - break; - } - // Just ignore strings that are out of range of - // the currently assigned resource IDs... we add - // strings as we assign the first ID. - } else if (outResIds->itemAt(strIdx) == id) { - idx = strIdx; - break; - } - } - } - if (idx < 0) { - idx = outPool->add(attr.name); - NOISY(printf("Adding attr %s (resid 0x%08x) to pool: idx=%d\n", - String8(attr.name).string(), id, idx)); - if (id != 0) { - while ((ssize_t)outResIds->size() <= idx) { - outResIds->add(0); - } - outResIds->replaceAt(id, idx); - } - } - attr.namePoolIdx = idx; - NOISY(printf("String %s offset=0x%08x\n", - String8(attr.name).string(), idx)); - } - } - - return NO_ERROR; -} - -status_t XMLNode::collect_resid_strings(StringPool* outPool, - Vector<uint32_t>* outResIds) const -{ - collect_attr_strings(outPool, outResIds, false); - - const int NC = mChildren.size(); - - for (int i=0; i<NC; i++) { - mChildren.itemAt(i)->collect_resid_strings(outPool, outResIds); - } - - return NO_ERROR; -} - -status_t XMLNode::flatten_node(const StringPool& strings, const sp<AaptFile>& dest, - bool stripComments, bool stripRawValues) const -{ - ResXMLTree_node node; - ResXMLTree_cdataExt cdataExt; - ResXMLTree_namespaceExt namespaceExt; - ResXMLTree_attrExt attrExt; - const void* extData = NULL; - size_t extSize = 0; - ResXMLTree_attribute attr; - bool writeCurrentNode = true; - - const size_t NA = mAttributes.size(); - const size_t NC = mChildren.size(); - size_t i; - - LOG_ALWAYS_FATAL_IF(NA != mAttributeOrder.size(), "Attributes messed up!"); - - const String16 id16("id"); - const String16 class16("class"); - const String16 style16("style"); - - const type type = getType(); - - memset(&node, 0, sizeof(node)); - memset(&attr, 0, sizeof(attr)); - node.header.headerSize = htods(sizeof(node)); - node.lineNumber = htodl(getStartLineNumber()); - if (!stripComments) { - node.comment.index = htodl( - mComment.size() > 0 ? strings.offsetForString(mComment) : -1); - //if (mComment.size() > 0) { - // printf("Flattening comment: %s\n", String8(mComment).string()); - //} - } else { - node.comment.index = htodl((uint32_t)-1); - } - if (type == TYPE_ELEMENT) { - node.header.type = htods(RES_XML_START_ELEMENT_TYPE); - extData = &attrExt; - extSize = sizeof(attrExt); - memset(&attrExt, 0, sizeof(attrExt)); - if (mNamespaceUri.size() > 0) { - attrExt.ns.index = htodl(strings.offsetForString(mNamespaceUri)); - } else { - attrExt.ns.index = htodl((uint32_t)-1); - } - attrExt.name.index = htodl(strings.offsetForString(mElementName)); - attrExt.attributeStart = htods(sizeof(attrExt)); - attrExt.attributeSize = htods(sizeof(attr)); - attrExt.attributeCount = htods(NA); - attrExt.idIndex = htods(0); - attrExt.classIndex = htods(0); - attrExt.styleIndex = htods(0); - for (i=0; i<NA; i++) { - ssize_t idx = mAttributeOrder.valueAt(i); - const attribute_entry& ae = mAttributes.itemAt(idx); - if (ae.ns.size() == 0) { - if (ae.name == id16) { - attrExt.idIndex = htods(i+1); - } else if (ae.name == class16) { - attrExt.classIndex = htods(i+1); - } else if (ae.name == style16) { - attrExt.styleIndex = htods(i+1); - } - } - } - } else if (type == TYPE_NAMESPACE) { - if (mNamespaceUri == RESOURCES_TOOLS_NAMESPACE) { - writeCurrentNode = false; - } else { - node.header.type = htods(RES_XML_START_NAMESPACE_TYPE); - extData = &namespaceExt; - extSize = sizeof(namespaceExt); - memset(&namespaceExt, 0, sizeof(namespaceExt)); - if (mNamespacePrefix.size() > 0) { - namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix)); - } else { - namespaceExt.prefix.index = htodl((uint32_t)-1); - } - namespaceExt.prefix.index = htodl(strings.offsetForString(mNamespacePrefix)); - namespaceExt.uri.index = htodl(strings.offsetForString(mNamespaceUri)); - } - LOG_ALWAYS_FATAL_IF(NA != 0, "Namespace nodes can't have attributes!"); - } else if (type == TYPE_CDATA) { - node.header.type = htods(RES_XML_CDATA_TYPE); - extData = &cdataExt; - extSize = sizeof(cdataExt); - memset(&cdataExt, 0, sizeof(cdataExt)); - cdataExt.data.index = htodl(strings.offsetForString(mChars)); - cdataExt.typedData.size = htods(sizeof(cdataExt.typedData)); - cdataExt.typedData.res0 = 0; - cdataExt.typedData.dataType = mCharsValue.dataType; - cdataExt.typedData.data = htodl(mCharsValue.data); - LOG_ALWAYS_FATAL_IF(NA != 0, "CDATA nodes can't have attributes!"); - } - - node.header.size = htodl(sizeof(node) + extSize + (sizeof(attr)*NA)); - - if (writeCurrentNode) { - dest->writeData(&node, sizeof(node)); - if (extSize > 0) { - dest->writeData(extData, extSize); - } - } - - for (i=0; i<NA; i++) { - ssize_t idx = mAttributeOrder.valueAt(i); - const attribute_entry& ae = mAttributes.itemAt(idx); - if (ae.ns.size() > 0) { - attr.ns.index = htodl(strings.offsetForString(ae.ns)); - } else { - attr.ns.index = htodl((uint32_t)-1); - } - attr.name.index = htodl(ae.namePoolIdx); - - if (!stripRawValues || ae.needStringValue()) { - attr.rawValue.index = htodl(strings.offsetForString(ae.string)); - } else { - attr.rawValue.index = htodl((uint32_t)-1); - } - attr.typedValue.size = htods(sizeof(attr.typedValue)); - if (ae.value.dataType == Res_value::TYPE_NULL - || ae.value.dataType == Res_value::TYPE_STRING) { - attr.typedValue.res0 = 0; - attr.typedValue.dataType = Res_value::TYPE_STRING; - attr.typedValue.data = htodl(strings.offsetForString(ae.string)); - } else { - attr.typedValue.res0 = 0; - attr.typedValue.dataType = ae.value.dataType; - attr.typedValue.data = htodl(ae.value.data); - } - dest->writeData(&attr, sizeof(attr)); - } - - for (i=0; i<NC; i++) { - status_t err = mChildren.itemAt(i)->flatten_node(strings, dest, - stripComments, stripRawValues); - if (err != NO_ERROR) { - return err; - } - } - - if (type == TYPE_ELEMENT) { - ResXMLTree_endElementExt endElementExt; - memset(&endElementExt, 0, sizeof(endElementExt)); - node.header.type = htods(RES_XML_END_ELEMENT_TYPE); - node.header.size = htodl(sizeof(node)+sizeof(endElementExt)); - node.lineNumber = htodl(getEndLineNumber()); - node.comment.index = htodl((uint32_t)-1); - endElementExt.ns.index = attrExt.ns.index; - endElementExt.name.index = attrExt.name.index; - dest->writeData(&node, sizeof(node)); - dest->writeData(&endElementExt, sizeof(endElementExt)); - } else if (type == TYPE_NAMESPACE) { - if (writeCurrentNode) { - node.header.type = htods(RES_XML_END_NAMESPACE_TYPE); - node.lineNumber = htodl(getEndLineNumber()); - node.comment.index = htodl((uint32_t)-1); - node.header.size = htodl(sizeof(node)+extSize); - dest->writeData(&node, sizeof(node)); - dest->writeData(extData, extSize); - } - } - - return NO_ERROR; -} diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h deleted file mode 100644 index 05624b7..0000000 --- a/tools/aapt/XMLNode.h +++ /dev/null @@ -1,202 +0,0 @@ -// -// Copyright 2006 The Android Open Source Project -// -// Build resource files from raw assets. -// - -#ifndef XML_NODE_H -#define XML_NODE_H - -#include "StringPool.h" -#include "ResourceTable.h" - -class XMLNode; - -extern const char* const RESOURCES_ROOT_NAMESPACE; -extern const char* const RESOURCES_ANDROID_NAMESPACE; - -bool isWhitespace(const char16_t* str); - -String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic = NULL); - -status_t parseStyledString(Bundle* bundle, - const char* fileName, - ResXMLTree* inXml, - const String16& endTag, - String16* outString, - Vector<StringPool::entry_style_span>* outSpans, - bool isFormatted, - bool isPseudolocalizable); - -void printXMLBlock(ResXMLTree* block); - -status_t parseXMLResource(const sp<AaptFile>& file, ResXMLTree* outTree, - bool stripAll=true, bool keepComments=false, - const char** cDataTags=NULL); - -class XMLNode : public RefBase -{ -public: - static sp<XMLNode> parse(const sp<AaptFile>& file); - - static inline - sp<XMLNode> newNamespace(const String8& filename, const String16& prefix, const String16& uri) { - return new XMLNode(filename, prefix, uri, true); - } - - static inline - sp<XMLNode> newElement(const String8& filename, const String16& ns, const String16& name) { - return new XMLNode(filename, ns, name, false); - } - - static inline - sp<XMLNode> newCData(const String8& filename) { - return new XMLNode(filename); - } - - enum type { - TYPE_NAMESPACE, - TYPE_ELEMENT, - TYPE_CDATA - }; - - type getType() const; - - const String16& getNamespacePrefix() const; - const String16& getNamespaceUri() const; - - const String16& getElementNamespace() const; - 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) - { - value.dataType = Res_value::TYPE_NULL; - } - - bool needStringValue() const { - return nameResId == 0 - || value.dataType == Res_value::TYPE_NULL - || value.dataType == Res_value::TYPE_STRING; - } - - String16 ns; - String16 name; - String16 string; - Res_value value; - uint32_t index; - uint32_t nameResId; - mutable uint32_t namePoolIdx; - }; - - const Vector<attribute_entry>& getAttributes() const; - - const attribute_entry* getAttribute(const String16& ns, const String16& name) const; - - attribute_entry* editAttribute(const String16& ns, const String16& name); - - const String16& getCData() const; - - const String16& getComment() const; - - 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); - - void setAttributeResID(size_t attrIdx, uint32_t resId); - - status_t appendChars(const String16& chars); - - status_t appendComment(const String16& comment); - - void setStartLineNumber(int32_t line); - void setEndLineNumber(int32_t line); - - void removeWhitespace(bool stripAll=true, const char** cDataTags=NULL); - - void setUTF8(bool val) { mUTF8 = val; } - - status_t parseValues(const sp<AaptAssets>& assets, ResourceTable* table); - - status_t assignResourceIds(const sp<AaptAssets>& assets, - const ResourceTable* table = NULL); - - status_t flatten(const sp<AaptFile>& dest, bool stripComments, - bool stripRawValues) const; - - void print(int indent=0); - -private: - struct ParseState - { - String8 filename; - XML_Parser parser; - sp<XMLNode> root; - Vector<sp<XMLNode> > stack; - String16 pendingComment; - }; - - static void XMLCALL - startNamespace(void *userData, const char *prefix, const char *uri); - static void XMLCALL - startElement(void *userData, const char *name, const char **atts); - static void XMLCALL - characterData(void *userData, const XML_Char *s, int len); - static void XMLCALL - endElement(void *userData, const char *name); - static void XMLCALL - endNamespace(void *userData, const char *prefix); - - static void XMLCALL - commentData(void *userData, const char *comment); - - // Creating an element node. - XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace); - - // Creating a CDATA node. - XMLNode(const String8& filename); - - status_t collect_strings(StringPool* dest, Vector<uint32_t>* outResIds, - bool stripComments, bool stripRawValues) const; - - status_t collect_attr_strings(StringPool* outPool, - Vector<uint32_t>* outResIds, bool allAttrs) const; - - status_t collect_resid_strings(StringPool* outPool, - Vector<uint32_t>* outResIds) const; - - status_t flatten_node(const StringPool& strings, const sp<AaptFile>& dest, - bool stripComments, bool stripRawValues) const; - - String16 mNamespacePrefix; - String16 mNamespaceUri; - String16 mElementName; - Vector<sp<XMLNode> > mChildren; - Vector<attribute_entry> mAttributes; - KeyedVector<uint32_t, uint32_t> mAttributeOrder; - uint32_t mNextAttributeIndex; - String16 mChars; - Res_value mCharsValue; - String16 mComment; - String8 mFilename; - int32_t mStartLineNumber; - int32_t mEndLineNumber; - - // Encode compiled XML with UTF-8 StringPools? - bool mUTF8; -}; - -#endif diff --git a/tools/aapt/ZipEntry.cpp b/tools/aapt/ZipEntry.cpp deleted file mode 100644 index b575988..0000000 --- a/tools/aapt/ZipEntry.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (C) 2006 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. - */ - -// -// Access to entries in a Zip archive. -// - -#define LOG_TAG "zip" - -#include "ZipEntry.h" -#include <utils/Log.h> - -#include <stdio.h> -#include <string.h> -#include <assert.h> - -using namespace android; - -/* - * Initialize a new ZipEntry structure from a FILE* positioned at a - * CentralDirectoryEntry. - * - * On exit, the file pointer will be at the start of the next CDE or - * at the EOCD. - */ -status_t ZipEntry::initFromCDE(FILE* fp) -{ - status_t result; - long posn; - bool hasDD; - - //ALOGV("initFromCDE ---\n"); - - /* read the CDE */ - result = mCDE.read(fp); - if (result != NO_ERROR) { - ALOGD("mCDE.read failed\n"); - return result; - } - - //mCDE.dump(); - - /* using the info in the CDE, go load up the LFH */ - posn = ftell(fp); - if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) { - ALOGD("local header seek failed (%ld)\n", - mCDE.mLocalHeaderRelOffset); - return UNKNOWN_ERROR; - } - - result = mLFH.read(fp); - if (result != NO_ERROR) { - ALOGD("mLFH.read failed\n"); - return result; - } - - if (fseek(fp, posn, SEEK_SET) != 0) - return UNKNOWN_ERROR; - - //mLFH.dump(); - - /* - * We *might* need to read the Data Descriptor at this point and - * integrate it into the LFH. If this bit is set, the CRC-32, - * compressed size, and uncompressed size will be zero. In practice - * these seem to be rare. - */ - hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0; - if (hasDD) { - // do something clever - //ALOGD("+++ has data descriptor\n"); - } - - /* - * Sanity-check the LFH. Note that this will fail if the "kUsesDataDescr" - * flag is set, because the LFH is incomplete. (Not a problem, since we - * prefer the CDE values.) - */ - if (!hasDD && !compareHeaders()) { - ALOGW("warning: header mismatch\n"); - // keep going? - } - - /* - * If the mVersionToExtract is greater than 20, we may have an - * issue unpacking the record -- could be encrypted, compressed - * with something we don't support, or use Zip64 extensions. We - * can defer worrying about that to when we're extracting data. - */ - - return NO_ERROR; -} - -/* - * Initialize a new entry. Pass in the file name and an optional comment. - * - * Initializes the CDE and the LFH. - */ -void ZipEntry::initNew(const char* fileName, const char* comment) -{ - assert(fileName != NULL && *fileName != '\0'); // name required - - /* most fields are properly initialized by constructor */ - mCDE.mVersionMadeBy = kDefaultMadeBy; - mCDE.mVersionToExtract = kDefaultVersion; - mCDE.mCompressionMethod = kCompressStored; - mCDE.mFileNameLength = strlen(fileName); - if (comment != NULL) - mCDE.mFileCommentLength = strlen(comment); - mCDE.mExternalAttrs = 0x81b60020; // matches what WinZip does - - if (mCDE.mFileNameLength > 0) { - mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1]; - strcpy((char*) mCDE.mFileName, fileName); - } - if (mCDE.mFileCommentLength > 0) { - /* TODO: stop assuming null-terminated ASCII here? */ - mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1]; - strcpy((char*) mCDE.mFileComment, comment); - } - - copyCDEtoLFH(); -} - -/* - * Initialize a new entry, starting with the ZipEntry from a different - * archive. - * - * Initializes the CDE and the LFH. - */ -status_t ZipEntry::initFromExternal(const ZipFile* pZipFile, - const ZipEntry* pEntry) -{ - /* - * Copy everything in the CDE over, then fix up the hairy bits. - */ - memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE)); - - if (mCDE.mFileNameLength > 0) { - mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1]; - if (mCDE.mFileName == NULL) - return NO_MEMORY; - strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName); - } - if (mCDE.mFileCommentLength > 0) { - mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1]; - if (mCDE.mFileComment == NULL) - return NO_MEMORY; - strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment); - } - if (mCDE.mExtraFieldLength > 0) { - /* we null-terminate this, though it may not be a string */ - mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1]; - if (mCDE.mExtraField == NULL) - return NO_MEMORY; - memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField, - mCDE.mExtraFieldLength+1); - } - - /* construct the LFH from the CDE */ - copyCDEtoLFH(); - - /* - * The LFH "extra" field is independent of the CDE "extra", so we - * handle it here. - */ - assert(mLFH.mExtraField == NULL); - mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength; - if (mLFH.mExtraFieldLength > 0) { - mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1]; - if (mLFH.mExtraField == NULL) - return NO_MEMORY; - memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField, - mLFH.mExtraFieldLength+1); - } - - return NO_ERROR; -} - -/* - * Insert pad bytes in the LFH by tweaking the "extra" field. This will - * potentially confuse something that put "extra" data in here earlier, - * but I can't find an actual problem. - */ -status_t ZipEntry::addPadding(int padding) -{ - if (padding <= 0) - return INVALID_OPERATION; - - //ALOGI("HEY: adding %d pad bytes to existing %d in %s\n", - // padding, mLFH.mExtraFieldLength, mCDE.mFileName); - - if (mLFH.mExtraFieldLength > 0) { - /* extend existing field */ - unsigned char* newExtra; - - newExtra = new unsigned char[mLFH.mExtraFieldLength + padding]; - if (newExtra == NULL) - return NO_MEMORY; - memset(newExtra + mLFH.mExtraFieldLength, 0, padding); - memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength); - - delete[] mLFH.mExtraField; - mLFH.mExtraField = newExtra; - mLFH.mExtraFieldLength += padding; - } else { - /* create new field */ - mLFH.mExtraField = new unsigned char[padding]; - memset(mLFH.mExtraField, 0, padding); - mLFH.mExtraFieldLength = padding; - } - - return NO_ERROR; -} - -/* - * Set the fields in the LFH equal to the corresponding fields in the CDE. - * - * This does not touch the LFH "extra" field. - */ -void ZipEntry::copyCDEtoLFH(void) -{ - mLFH.mVersionToExtract = mCDE.mVersionToExtract; - mLFH.mGPBitFlag = mCDE.mGPBitFlag; - mLFH.mCompressionMethod = mCDE.mCompressionMethod; - mLFH.mLastModFileTime = mCDE.mLastModFileTime; - mLFH.mLastModFileDate = mCDE.mLastModFileDate; - mLFH.mCRC32 = mCDE.mCRC32; - mLFH.mCompressedSize = mCDE.mCompressedSize; - mLFH.mUncompressedSize = mCDE.mUncompressedSize; - mLFH.mFileNameLength = mCDE.mFileNameLength; - // the "extra field" is independent - - delete[] mLFH.mFileName; - if (mLFH.mFileNameLength > 0) { - mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1]; - strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName); - } else { - mLFH.mFileName = NULL; - } -} - -/* - * Set some information about a file after we add it. - */ -void ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32, - int compressionMethod) -{ - mCDE.mCompressionMethod = compressionMethod; - mCDE.mCRC32 = crc32; - mCDE.mCompressedSize = compLen; - mCDE.mUncompressedSize = uncompLen; - mCDE.mCompressionMethod = compressionMethod; - if (compressionMethod == kCompressDeflated) { - mCDE.mGPBitFlag |= 0x0002; // indicates maximum compression used - } - copyCDEtoLFH(); -} - -/* - * See if the data in mCDE and mLFH match up. This is mostly useful for - * debugging these classes, but it can be used to identify damaged - * archives. - * - * Returns "false" if they differ. - */ -bool ZipEntry::compareHeaders(void) const -{ - if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) { - ALOGV("cmp: VersionToExtract\n"); - return false; - } - if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) { - ALOGV("cmp: GPBitFlag\n"); - return false; - } - if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) { - ALOGV("cmp: CompressionMethod\n"); - return false; - } - if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) { - ALOGV("cmp: LastModFileTime\n"); - return false; - } - if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) { - ALOGV("cmp: LastModFileDate\n"); - return false; - } - if (mCDE.mCRC32 != mLFH.mCRC32) { - ALOGV("cmp: CRC32\n"); - return false; - } - if (mCDE.mCompressedSize != mLFH.mCompressedSize) { - ALOGV("cmp: CompressedSize\n"); - return false; - } - if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) { - ALOGV("cmp: UncompressedSize\n"); - return false; - } - if (mCDE.mFileNameLength != mLFH.mFileNameLength) { - ALOGV("cmp: FileNameLength\n"); - return false; - } -#if 0 // this seems to be used for padding, not real data - if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) { - ALOGV("cmp: ExtraFieldLength\n"); - return false; - } -#endif - if (mCDE.mFileName != NULL) { - if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) { - ALOGV("cmp: FileName\n"); - return false; - } - } - - return true; -} - - -/* - * Convert the DOS date/time stamp into a UNIX time stamp. - */ -time_t ZipEntry::getModWhen(void) const -{ - struct tm parts; - - parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1; - parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5; - parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11; - parts.tm_mday = (mCDE.mLastModFileDate & 0x001f); - parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1; - parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80; - parts.tm_wday = parts.tm_yday = 0; - parts.tm_isdst = -1; // DST info "not available" - - return mktime(&parts); -} - -/* - * Set the CDE/LFH timestamp from UNIX time. - */ -void ZipEntry::setModWhen(time_t when) -{ -#ifdef HAVE_LOCALTIME_R - struct tm tmResult; -#endif - time_t even; - unsigned short zdate, ztime; - - struct tm* ptm; - - /* round up to an even number of seconds */ - even = (time_t)(((unsigned long)(when) + 1) & (~1)); - - /* expand */ -#ifdef HAVE_LOCALTIME_R - ptm = localtime_r(&even, &tmResult); -#else - ptm = localtime(&even); -#endif - - int year; - year = ptm->tm_year; - if (year < 80) - year = 80; - - zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; - ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; - - mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime; - mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate; -} - - -/* - * =========================================================================== - * ZipEntry::LocalFileHeader - * =========================================================================== - */ - -/* - * Read a local file header. - * - * On entry, "fp" points to the signature at the start of the header. - * On exit, "fp" points to the start of data. - */ -status_t ZipEntry::LocalFileHeader::read(FILE* fp) -{ - status_t result = NO_ERROR; - unsigned char buf[kLFHLen]; - - assert(mFileName == NULL); - assert(mExtraField == NULL); - - if (fread(buf, 1, kLFHLen, fp) != kLFHLen) { - result = UNKNOWN_ERROR; - goto bail; - } - - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) { - ALOGD("whoops: didn't find expected signature\n"); - result = UNKNOWN_ERROR; - goto bail; - } - - mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]); - mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]); - mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]); - mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]); - mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]); - mCRC32 = ZipEntry::getLongLE(&buf[0x0e]); - mCompressedSize = ZipEntry::getLongLE(&buf[0x12]); - mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]); - mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]); - mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]); - - // TODO: validate sizes - - /* grab filename */ - if (mFileNameLength != 0) { - mFileName = new unsigned char[mFileNameLength+1]; - if (mFileName == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mFileName[mFileNameLength] = '\0'; - } - - /* grab extra field */ - if (mExtraFieldLength != 0) { - mExtraField = new unsigned char[mExtraFieldLength+1]; - if (mExtraField == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mExtraField[mExtraFieldLength] = '\0'; - } - -bail: - return result; -} - -/* - * Write a local file header. - */ -status_t ZipEntry::LocalFileHeader::write(FILE* fp) -{ - unsigned char buf[kLFHLen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mVersionToExtract); - ZipEntry::putShortLE(&buf[0x06], mGPBitFlag); - ZipEntry::putShortLE(&buf[0x08], mCompressionMethod); - ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime); - ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate); - ZipEntry::putLongLE(&buf[0x0e], mCRC32); - ZipEntry::putLongLE(&buf[0x12], mCompressedSize); - ZipEntry::putLongLE(&buf[0x16], mUncompressedSize); - ZipEntry::putShortLE(&buf[0x1a], mFileNameLength); - ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength); - - if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen) - return UNKNOWN_ERROR; - - /* write filename */ - if (mFileNameLength != 0) { - if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength) - return UNKNOWN_ERROR; - } - - /* write "extra field" */ - if (mExtraFieldLength != 0) { - if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - - -/* - * Dump the contents of a LocalFileHeader object. - */ -void ZipEntry::LocalFileHeader::dump(void) const -{ - ALOGD(" LocalFileHeader contents:\n"); - ALOGD(" versToExt=%u gpBits=0x%04x compression=%u\n", - mVersionToExtract, mGPBitFlag, mCompressionMethod); - ALOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - mLastModFileTime, mLastModFileDate, mCRC32); - ALOGD(" compressedSize=%lu uncompressedSize=%lu\n", - mCompressedSize, mUncompressedSize); - ALOGD(" filenameLen=%u extraLen=%u\n", - mFileNameLength, mExtraFieldLength); - if (mFileName != NULL) - ALOGD(" filename: '%s'\n", mFileName); -} - - -/* - * =========================================================================== - * ZipEntry::CentralDirEntry - * =========================================================================== - */ - -/* - * Read the central dir entry that appears next in the file. - * - * On entry, "fp" should be positioned on the signature bytes for the - * entry. On exit, "fp" will point at the signature word for the next - * entry or for the EOCD. - */ -status_t ZipEntry::CentralDirEntry::read(FILE* fp) -{ - status_t result = NO_ERROR; - unsigned char buf[kCDELen]; - - /* no re-use */ - assert(mFileName == NULL); - assert(mExtraField == NULL); - assert(mFileComment == NULL); - - if (fread(buf, 1, kCDELen, fp) != kCDELen) { - result = UNKNOWN_ERROR; - goto bail; - } - - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) { - ALOGD("Whoops: didn't find expected signature\n"); - result = UNKNOWN_ERROR; - goto bail; - } - - mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]); - mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]); - mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]); - mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]); - mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]); - mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]); - mCRC32 = ZipEntry::getLongLE(&buf[0x10]); - mCompressedSize = ZipEntry::getLongLE(&buf[0x14]); - mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]); - mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]); - mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]); - mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]); - mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]); - mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]); - mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]); - mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]); - - // TODO: validate sizes and offsets - - /* grab filename */ - if (mFileNameLength != 0) { - mFileName = new unsigned char[mFileNameLength+1]; - if (mFileName == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mFileName[mFileNameLength] = '\0'; - } - - /* read "extra field" */ - if (mExtraFieldLength != 0) { - mExtraField = new unsigned char[mExtraFieldLength+1]; - if (mExtraField == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mExtraField[mExtraFieldLength] = '\0'; - } - - - /* grab comment, if any */ - if (mFileCommentLength != 0) { - mFileComment = new unsigned char[mFileCommentLength+1]; - if (mFileComment == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength) - { - result = UNKNOWN_ERROR; - goto bail; - } - mFileComment[mFileCommentLength] = '\0'; - } - -bail: - return result; -} - -/* - * Write a central dir entry. - */ -status_t ZipEntry::CentralDirEntry::write(FILE* fp) -{ - unsigned char buf[kCDELen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy); - ZipEntry::putShortLE(&buf[0x06], mVersionToExtract); - ZipEntry::putShortLE(&buf[0x08], mGPBitFlag); - ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod); - ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime); - ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate); - ZipEntry::putLongLE(&buf[0x10], mCRC32); - ZipEntry::putLongLE(&buf[0x14], mCompressedSize); - ZipEntry::putLongLE(&buf[0x18], mUncompressedSize); - ZipEntry::putShortLE(&buf[0x1c], mFileNameLength); - ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength); - ZipEntry::putShortLE(&buf[0x20], mFileCommentLength); - ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart); - ZipEntry::putShortLE(&buf[0x24], mInternalAttrs); - ZipEntry::putLongLE(&buf[0x26], mExternalAttrs); - ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset); - - if (fwrite(buf, 1, kCDELen, fp) != kCDELen) - return UNKNOWN_ERROR; - - /* write filename */ - if (mFileNameLength != 0) { - if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength) - return UNKNOWN_ERROR; - } - - /* write "extra field" */ - if (mExtraFieldLength != 0) { - if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) - return UNKNOWN_ERROR; - } - - /* write comment */ - if (mFileCommentLength != 0) { - if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -/* - * Dump the contents of a CentralDirEntry object. - */ -void ZipEntry::CentralDirEntry::dump(void) const -{ - ALOGD(" CentralDirEntry contents:\n"); - ALOGD(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n", - mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod); - ALOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - mLastModFileTime, mLastModFileDate, mCRC32); - ALOGD(" compressedSize=%lu uncompressedSize=%lu\n", - mCompressedSize, mUncompressedSize); - ALOGD(" filenameLen=%u extraLen=%u commentLen=%u\n", - mFileNameLength, mExtraFieldLength, mFileCommentLength); - ALOGD(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n", - mDiskNumberStart, mInternalAttrs, mExternalAttrs, - mLocalHeaderRelOffset); - - if (mFileName != NULL) - ALOGD(" filename: '%s'\n", mFileName); - if (mFileComment != NULL) - ALOGD(" comment: '%s'\n", mFileComment); -} - diff --git a/tools/aapt/ZipEntry.h b/tools/aapt/ZipEntry.h deleted file mode 100644 index c2f3227..0000000 --- a/tools/aapt/ZipEntry.h +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (C) 2006 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. - */ - -// -// Zip archive entries. -// -// The ZipEntry class is tightly meshed with the ZipFile class. -// -#ifndef __LIBS_ZIPENTRY_H -#define __LIBS_ZIPENTRY_H - -#include <utils/Errors.h> - -#include <stdlib.h> -#include <stdio.h> - -namespace android { - -class ZipFile; - -/* - * ZipEntry objects represent a single entry in a Zip archive. - * - * You can use one of these to get or set information about an entry, but - * there are no functions here for accessing the data itself. (We could - * tuck a pointer to the ZipFile in here for convenience, but that raises - * the likelihood of using ZipEntry objects after discarding the ZipFile.) - * - * File information is stored in two places: next to the file data (the Local - * File Header, and possibly a Data Descriptor), and at the end of the file - * (the Central Directory Entry). The two must be kept in sync. - */ -class ZipEntry { -public: - friend class ZipFile; - - ZipEntry(void) - : mDeleted(false), mMarked(false) - {} - ~ZipEntry(void) {} - - /* - * Returns "true" if the data is compressed. - */ - bool isCompressed(void) const { - return mCDE.mCompressionMethod != kCompressStored; - } - int getCompressionMethod(void) const { return mCDE.mCompressionMethod; } - - /* - * Return the uncompressed length. - */ - off_t getUncompressedLen(void) const { return mCDE.mUncompressedSize; } - - /* - * Return the compressed length. For uncompressed data, this returns - * the same thing as getUncompresesdLen(). - */ - 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. - */ - off_t getFileOffset(void) const { - return mCDE.mLocalHeaderRelOffset + - LocalFileHeader::kLFHLen + - mLFH.mFileNameLength + - mLFH.mExtraFieldLength; - } - - /* - * Return the data CRC. - */ - unsigned long getCRC32(void) const { return mCDE.mCRC32; } - - /* - * Return file modification time in UNIX seconds-since-epoch. - */ - time_t getModWhen(void) const; - - /* - * Return the archived file name. - */ - const char* getFileName(void) const { return (const char*) mCDE.mFileName; } - - /* - * Application-defined "mark". Can be useful when synchronizing the - * contents of an archive with contents on disk. - */ - bool getMarked(void) const { return mMarked; } - void setMarked(bool val) { mMarked = val; } - - /* - * Some basic functions for raw data manipulation. "LE" means - * Little Endian. - */ - static inline unsigned short getShortLE(const unsigned char* buf) { - return buf[0] | (buf[1] << 8); - } - static inline unsigned long getLongLE(const unsigned char* buf) { - return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); - } - static inline void putShortLE(unsigned char* buf, short val) { - buf[0] = (unsigned char) val; - buf[1] = (unsigned char) (val >> 8); - } - static inline void putLongLE(unsigned char* buf, long val) { - buf[0] = (unsigned char) val; - buf[1] = (unsigned char) (val >> 8); - buf[2] = (unsigned char) (val >> 16); - buf[3] = (unsigned char) (val >> 24); - } - - /* defined for Zip archives */ - enum { - kCompressStored = 0, // no compression - // shrunk = 1, - // reduced 1 = 2, - // reduced 2 = 3, - // reduced 3 = 4, - // reduced 4 = 5, - // imploded = 6, - // tokenized = 7, - kCompressDeflated = 8, // standard deflate - // Deflate64 = 9, - // lib imploded = 10, - // reserved = 11, - // bzip2 = 12, - }; - - /* - * Deletion flag. If set, the entry will be removed on the next - * call to "flush". - */ - bool getDeleted(void) const { return mDeleted; } - -protected: - /* - * Initialize the structure from the file, which is pointing at - * our Central Directory entry. - */ - status_t initFromCDE(FILE* fp); - - /* - * Initialize the structure for a new file. We need the filename - * and comment so that we can properly size the LFH area. The - * filename is mandatory, the comment is optional. - */ - void initNew(const char* fileName, const char* comment); - - /* - * Initialize the structure with the contents of a ZipEntry from - * another file. - */ - status_t initFromExternal(const ZipFile* pZipFile, const ZipEntry* pEntry); - - /* - * Add some pad bytes to the LFH. We do this by adding or resizing - * the "extra" field. - */ - status_t addPadding(int padding); - - /* - * Set information about the data for this entry. - */ - void setDataInfo(long uncompLen, long compLen, unsigned long crc32, - int compressionMethod); - - /* - * Set the modification date. - */ - void setModWhen(time_t when); - - /* - * Set the offset of the local file header, relative to the start of - * the current file. - */ - void setLFHOffset(off_t offset) { - mCDE.mLocalHeaderRelOffset = (long) offset; - } - - /* mark for deletion; used by ZipFile::remove() */ - void setDeleted(void) { mDeleted = true; } - -private: - /* these are private and not defined */ - ZipEntry(const ZipEntry& src); - ZipEntry& operator=(const ZipEntry& src); - - /* returns "true" if the CDE and the LFH agree */ - bool compareHeaders(void) const; - void copyCDEtoLFH(void); - - bool mDeleted; // set if entry is pending deletion - bool mMarked; // app-defined marker - - /* - * Every entry in the Zip archive starts off with one of these. - */ - class LocalFileHeader { - public: - LocalFileHeader(void) : - mVersionToExtract(0), - mGPBitFlag(0), - mCompressionMethod(0), - mLastModFileTime(0), - mLastModFileDate(0), - mCRC32(0), - mCompressedSize(0), - mUncompressedSize(0), - mFileNameLength(0), - mExtraFieldLength(0), - mFileName(NULL), - mExtraField(NULL) - {} - virtual ~LocalFileHeader(void) { - delete[] mFileName; - delete[] mExtraField; - } - - status_t read(FILE* fp); - status_t write(FILE* fp); - - // unsigned long mSignature; - unsigned short mVersionToExtract; - unsigned short mGPBitFlag; - unsigned short mCompressionMethod; - unsigned short mLastModFileTime; - unsigned short mLastModFileDate; - unsigned long mCRC32; - unsigned long mCompressedSize; - unsigned long mUncompressedSize; - unsigned short mFileNameLength; - unsigned short mExtraFieldLength; - unsigned char* mFileName; - unsigned char* mExtraField; - - enum { - kSignature = 0x04034b50, - kLFHLen = 30, // LocalFileHdr len, excl. var fields - }; - - void dump(void) const; - }; - - /* - * Every entry in the Zip archive has one of these in the "central - * directory" at the end of the file. - */ - class CentralDirEntry { - public: - CentralDirEntry(void) : - mVersionMadeBy(0), - mVersionToExtract(0), - mGPBitFlag(0), - mCompressionMethod(0), - mLastModFileTime(0), - mLastModFileDate(0), - mCRC32(0), - mCompressedSize(0), - mUncompressedSize(0), - mFileNameLength(0), - mExtraFieldLength(0), - mFileCommentLength(0), - mDiskNumberStart(0), - mInternalAttrs(0), - mExternalAttrs(0), - mLocalHeaderRelOffset(0), - mFileName(NULL), - mExtraField(NULL), - mFileComment(NULL) - {} - virtual ~CentralDirEntry(void) { - delete[] mFileName; - delete[] mExtraField; - delete[] mFileComment; - } - - status_t read(FILE* fp); - status_t write(FILE* fp); - - // unsigned long mSignature; - unsigned short mVersionMadeBy; - unsigned short mVersionToExtract; - unsigned short mGPBitFlag; - unsigned short mCompressionMethod; - unsigned short mLastModFileTime; - unsigned short mLastModFileDate; - unsigned long mCRC32; - unsigned long mCompressedSize; - unsigned long mUncompressedSize; - unsigned short mFileNameLength; - unsigned short mExtraFieldLength; - unsigned short mFileCommentLength; - unsigned short mDiskNumberStart; - unsigned short mInternalAttrs; - unsigned long mExternalAttrs; - unsigned long mLocalHeaderRelOffset; - unsigned char* mFileName; - unsigned char* mExtraField; - unsigned char* mFileComment; - - void dump(void) const; - - enum { - kSignature = 0x02014b50, - kCDELen = 46, // CentralDirEnt len, excl. var fields - }; - }; - - enum { - //kDataDescriptorSignature = 0x08074b50, // currently unused - kDataDescriptorLen = 16, // four 32-bit fields - - kDefaultVersion = 20, // need deflate, nothing much else - kDefaultMadeBy = 0x0317, // 03=UNIX, 17=spec v2.3 - kUsesDataDescr = 0x0008, // GPBitFlag bit 3 - }; - - LocalFileHeader mLFH; - CentralDirEntry mCDE; -}; - -}; // namespace android - -#endif // __LIBS_ZIPENTRY_H diff --git a/tools/aapt/ZipFile.cpp b/tools/aapt/ZipFile.cpp deleted file mode 100644 index 8057068..0000000 --- a/tools/aapt/ZipFile.cpp +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * Copyright (C) 2006 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. - */ - -// -// Access to Zip archives. -// - -#define LOG_TAG "zip" - -#include <androidfw/ZipUtils.h> -#include <utils/Log.h> - -#include "ZipFile.h" - -#include <zlib.h> -#define DEF_MEM_LEVEL 8 // normally in zutil.h? - -#include <memory.h> -#include <sys/stat.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -/* - * Some environments require the "b", some choke on it. - */ -#define FILE_OPEN_RO "rb" -#define FILE_OPEN_RW "r+b" -#define FILE_OPEN_RW_CREATE "w+b" - -/* should live somewhere else? */ -static status_t errnoToStatus(int err) -{ - if (err == ENOENT) - return NAME_NOT_FOUND; - else if (err == EACCES) - return PERMISSION_DENIED; - else - return UNKNOWN_ERROR; -} - -/* - * Open a file and parse its guts. - */ -status_t ZipFile::open(const char* zipFileName, int flags) -{ - bool newArchive = false; - - assert(mZipFp == NULL); // no reopen - - if ((flags & kOpenTruncate)) - flags |= kOpenCreate; // trunc implies create - - if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite)) - return INVALID_OPERATION; // not both - if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite))) - return INVALID_OPERATION; // not neither - if ((flags & kOpenCreate) && !(flags & kOpenReadWrite)) - return INVALID_OPERATION; // create requires write - - if (flags & kOpenTruncate) { - newArchive = true; - } else { - newArchive = (access(zipFileName, F_OK) != 0); - if (!(flags & kOpenCreate) && newArchive) { - /* not creating, must already exist */ - ALOGD("File %s does not exist", zipFileName); - return NAME_NOT_FOUND; - } - } - - /* open the file */ - const char* openflags; - if (flags & kOpenReadWrite) { - if (newArchive) - openflags = FILE_OPEN_RW_CREATE; - else - openflags = FILE_OPEN_RW; - } else { - openflags = FILE_OPEN_RO; - } - mZipFp = fopen(zipFileName, openflags); - if (mZipFp == NULL) { - int err = errno; - ALOGD("fopen failed: %d\n", err); - return errnoToStatus(err); - } - - status_t result; - if (!newArchive) { - /* - * Load the central directory. If that fails, then this probably - * isn't a Zip archive. - */ - result = readCentralDir(); - } else { - /* - * Newly-created. The EndOfCentralDir constructor actually - * sets everything to be the way we want it (all zeroes). We - * set mNeedCDRewrite so that we create *something* if the - * caller doesn't add any files. (We could also just unlink - * the file if it's brand new and nothing was added, but that's - * probably doing more than we really should -- the user might - * have a need for empty zip files.) - */ - mNeedCDRewrite = true; - result = NO_ERROR; - } - - if (flags & kOpenReadOnly) - mReadOnly = true; - else - assert(!mReadOnly); - - return result; -} - -/* - * Return the Nth entry in the archive. - */ -ZipEntry* ZipFile::getEntryByIndex(int idx) const -{ - if (idx < 0 || idx >= (int) mEntries.size()) - return NULL; - - return mEntries[idx]; -} - -/* - * Find an entry by name. - */ -ZipEntry* ZipFile::getEntryByName(const char* fileName) const -{ - /* - * Do a stupid linear string-compare search. - * - * There are various ways to speed this up, especially since it's rare - * to intermingle changes to the archive with "get by name" calls. We - * don't want to sort the mEntries vector itself, however, because - * it's used to recreate the Central Directory. - * - * (Hash table works, parallel list of pointers in sorted order is good.) - */ - int idx; - - for (idx = mEntries.size()-1; idx >= 0; idx--) { - ZipEntry* pEntry = mEntries[idx]; - if (!pEntry->getDeleted() && - strcmp(fileName, pEntry->getFileName()) == 0) - { - return pEntry; - } - } - - return NULL; -} - -/* - * Empty the mEntries vector. - */ -void ZipFile::discardEntries(void) -{ - int count = mEntries.size(); - - while (--count >= 0) - delete mEntries[count]; - - mEntries.clear(); -} - - -/* - * Find the central directory and read the contents. - * - * The fun thing about ZIP archives is that they may or may not be - * readable from start to end. In some cases, notably for archives - * that were written to stdout, the only length information is in the - * central directory at the end of the file. - * - * Of course, the central directory can be followed by a variable-length - * comment field, so we have to scan through it backwards. The comment - * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff - * itself, plus apparently sometimes people throw random junk on the end - * just for the fun of it. - * - * This is all a little wobbly. If the wrong value ends up in the EOCD - * area, we're hosed. This appears to be the way that everbody handles - * it though, so we're in pretty good company if this fails. - */ -status_t ZipFile::readCentralDir(void) -{ - status_t result = NO_ERROR; - unsigned char* buf = NULL; - off_t fileLength, seekStart; - long readAmount; - int i; - - fseek(mZipFp, 0, SEEK_END); - fileLength = ftell(mZipFp); - rewind(mZipFp); - - /* too small to be a ZIP archive? */ - if (fileLength < EndOfCentralDir::kEOCDLen) { - ALOGD("Length is %ld -- too small\n", (long)fileLength); - result = INVALID_OPERATION; - goto bail; - } - - buf = new unsigned char[EndOfCentralDir::kMaxEOCDSearch]; - if (buf == NULL) { - ALOGD("Failure allocating %d bytes for EOCD search", - EndOfCentralDir::kMaxEOCDSearch); - result = NO_MEMORY; - goto bail; - } - - if (fileLength > EndOfCentralDir::kMaxEOCDSearch) { - seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch; - readAmount = EndOfCentralDir::kMaxEOCDSearch; - } else { - seekStart = 0; - readAmount = (long) fileLength; - } - if (fseek(mZipFp, seekStart, SEEK_SET) != 0) { - ALOGD("Failure seeking to end of zip at %ld", (long) seekStart); - result = UNKNOWN_ERROR; - goto bail; - } - - /* read the last part of the file into the buffer */ - if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) { - ALOGD("short file? wanted %ld\n", readAmount); - result = UNKNOWN_ERROR; - goto bail; - } - - /* find the end-of-central-dir magic */ - for (i = readAmount - 4; i >= 0; i--) { - if (buf[i] == 0x50 && - ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature) - { - ALOGV("+++ Found EOCD at buf+%d\n", i); - break; - } - } - if (i < 0) { - ALOGD("EOCD not found, not Zip\n"); - result = INVALID_OPERATION; - goto bail; - } - - /* extract eocd values */ - result = mEOCD.readBuf(buf + i, readAmount - i); - if (result != NO_ERROR) { - ALOGD("Failure reading %ld bytes of EOCD values", readAmount - i); - goto bail; - } - //mEOCD.dump(); - - if (mEOCD.mDiskNumber != 0 || mEOCD.mDiskWithCentralDir != 0 || - mEOCD.mNumEntries != mEOCD.mTotalNumEntries) - { - ALOGD("Archive spanning not supported\n"); - result = INVALID_OPERATION; - goto bail; - } - - /* - * So far so good. "mCentralDirSize" is the size in bytes of the - * central directory, so we can just seek back that far to find it. - * We can also seek forward mCentralDirOffset bytes from the - * start of the file. - * - * We're not guaranteed to have the rest of the central dir in the - * buffer, nor are we guaranteed that the central dir will have any - * sort of convenient size. We need to skip to the start of it and - * read the header, then the other goodies. - * - * The only thing we really need right now is the file comment, which - * we're hoping to preserve. - */ - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - ALOGD("Failure seeking to central dir offset %ld\n", - mEOCD.mCentralDirOffset); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * Loop through and read the central dir entries. - */ - ALOGV("Scanning %d entries...\n", mEOCD.mTotalNumEntries); - int entry; - for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) { - ZipEntry* pEntry = new ZipEntry; - - result = pEntry->initFromCDE(mZipFp); - if (result != NO_ERROR) { - ALOGD("initFromCDE failed\n"); - delete pEntry; - goto bail; - } - - mEntries.add(pEntry); - } - - - /* - * If all went well, we should now be back at the EOCD. - */ - { - unsigned char checkBuf[4]; - if (fread(checkBuf, 1, 4, mZipFp) != 4) { - ALOGD("EOCD check read failed\n"); - result = INVALID_OPERATION; - goto bail; - } - if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) { - ALOGD("EOCD read check failed\n"); - result = UNKNOWN_ERROR; - goto bail; - } - ALOGV("+++ EOCD read check passed\n"); - } - -bail: - delete[] buf; - return result; -} - - -/* - * Add a new file to the archive. - * - * This requires creating and populating a ZipEntry structure, and copying - * the data into the file at the appropriate position. The "appropriate - * position" is the current location of the central directory, which we - * casually overwrite (we can put it back later). - * - * If we were concerned about safety, we would want to make all changes - * in a temp file and then overwrite the original after everything was - * safely written. Not really a concern for us. - */ -status_t ZipFile::addCommon(const char* fileName, const void* data, size_t size, - const char* storageName, int sourceType, int compressionMethod, - ZipEntry** ppEntry) -{ - ZipEntry* pEntry = NULL; - status_t result = NO_ERROR; - long lfhPosn, startPosn, endPosn, uncompressedLen; - FILE* inputFp = NULL; - unsigned long crc; - time_t modWhen; - - if (mReadOnly) - return INVALID_OPERATION; - - assert(compressionMethod == ZipEntry::kCompressDeflated || - compressionMethod == ZipEntry::kCompressStored); - - /* make sure we're in a reasonable state */ - assert(mZipFp != NULL); - assert(mEntries.size() == mEOCD.mTotalNumEntries); - - /* make sure it doesn't already exist */ - if (getEntryByName(storageName) != NULL) - return ALREADY_EXISTS; - - if (!data) { - inputFp = fopen(fileName, FILE_OPEN_RO); - if (inputFp == NULL) - return errnoToStatus(errno); - } - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - - pEntry = new ZipEntry; - pEntry->initNew(storageName, NULL); - - /* - * From here on out, failures are more interesting. - */ - mNeedCDRewrite = true; - - /* - * Write the LFH, even though it's still mostly blank. We need it - * as a place-holder. In theory the LFH isn't necessary, but in - * practice some utilities demand it. - */ - lfhPosn = ftell(mZipFp); - pEntry->mLFH.write(mZipFp); - startPosn = ftell(mZipFp); - - /* - * Copy the data in, possibly compressing it as we go. - */ - if (sourceType == ZipEntry::kCompressStored) { - if (compressionMethod == ZipEntry::kCompressDeflated) { - bool failed = false; - result = compressFpToFp(mZipFp, inputFp, data, size, &crc); - if (result != NO_ERROR) { - ALOGD("compression failed, storing\n"); - failed = true; - } else { - /* - * Make sure it has compressed "enough". This probably ought - * to be set through an API call, but I don't expect our - * criteria to change over time. - */ - long src = inputFp ? ftell(inputFp) : size; - long dst = ftell(mZipFp) - startPosn; - if (dst + (dst / 10) > src) { - ALOGD("insufficient compression (src=%ld dst=%ld), storing\n", - src, dst); - failed = true; - } - } - - if (failed) { - compressionMethod = ZipEntry::kCompressStored; - if (inputFp) rewind(inputFp); - fseek(mZipFp, startPosn, SEEK_SET); - /* fall through to kCompressStored case */ - } - } - /* handle "no compression" request, or failed compression from above */ - if (compressionMethod == ZipEntry::kCompressStored) { - if (inputFp) { - result = copyFpToFp(mZipFp, inputFp, &crc); - } else { - result = copyDataToFp(mZipFp, data, size, &crc); - } - if (result != NO_ERROR) { - // don't need to truncate; happens in CDE rewrite - ALOGD("failed copying data in\n"); - goto bail; - } - } - - // currently seeked to end of file - uncompressedLen = inputFp ? ftell(inputFp) : size; - } else if (sourceType == ZipEntry::kCompressDeflated) { - /* we should support uncompressed-from-compressed, but it's not - * important right now */ - assert(compressionMethod == ZipEntry::kCompressDeflated); - - bool scanResult; - int method; - long compressedLen; - - scanResult = ZipUtils::examineGzip(inputFp, &method, &uncompressedLen, - &compressedLen, &crc); - if (!scanResult || method != ZipEntry::kCompressDeflated) { - ALOGD("this isn't a deflated gzip file?"); - result = UNKNOWN_ERROR; - goto bail; - } - - result = copyPartialFpToFp(mZipFp, inputFp, compressedLen, NULL); - if (result != NO_ERROR) { - ALOGD("failed copying gzip data in\n"); - goto bail; - } - } else { - assert(false); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * We could write the "Data Descriptor", but there doesn't seem to - * be any point since we're going to go back and write the LFH. - * - * Update file offsets. - */ - endPosn = ftell(mZipFp); // seeked to end of compressed data - - /* - * Success! Fill out new values. - */ - pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc, - compressionMethod); - modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp)); - pEntry->setModWhen(modWhen); - pEntry->setLFHOffset(lfhPosn); - mEOCD.mNumEntries++; - mEOCD.mTotalNumEntries++; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - mEOCD.mCentralDirOffset = endPosn; - - /* - * Go back and write the LFH. - */ - if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - pEntry->mLFH.write(mZipFp); - - /* - * Add pEntry to the list. - */ - mEntries.add(pEntry); - if (ppEntry != NULL) - *ppEntry = pEntry; - pEntry = NULL; - -bail: - if (inputFp != NULL) - fclose(inputFp); - delete pEntry; - return result; -} - -/* - * Add an entry by copying it from another zip file. If "padding" is - * nonzero, the specified number of bytes will be added to the "extra" - * field in the header. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ -status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, - int padding, ZipEntry** ppEntry) -{ - ZipEntry* pEntry = NULL; - status_t result; - long lfhPosn, endPosn; - - if (mReadOnly) - return INVALID_OPERATION; - - /* make sure we're in a reasonable state */ - assert(mZipFp != NULL); - assert(mEntries.size() == mEOCD.mTotalNumEntries); - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - - pEntry = new ZipEntry; - if (pEntry == NULL) { - result = NO_MEMORY; - goto bail; - } - - result = pEntry->initFromExternal(pSourceZip, pSourceEntry); - if (result != NO_ERROR) - goto bail; - if (padding != 0) { - result = pEntry->addPadding(padding); - if (result != NO_ERROR) - goto bail; - } - - /* - * From here on out, failures are more interesting. - */ - mNeedCDRewrite = true; - - /* - * Write the LFH. Since we're not recompressing the data, we already - * have all of the fields filled out. - */ - lfhPosn = ftell(mZipFp); - pEntry->mLFH.write(mZipFp); - - /* - * Copy the data over. - * - * If the "has data descriptor" flag is set, we want to copy the DD - * fields as well. This is a fixed-size area immediately following - * the data. - */ - if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0) - { - result = UNKNOWN_ERROR; - goto bail; - } - - off_t copyLen; - copyLen = pSourceEntry->getCompressedLen(); - if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0) - copyLen += ZipEntry::kDataDescriptorLen; - - if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL) - != NO_ERROR) - { - ALOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * Update file offsets. - */ - endPosn = ftell(mZipFp); - - /* - * Success! Fill out new values. - */ - pEntry->setLFHOffset(lfhPosn); // sets mCDE.mLocalHeaderRelOffset - mEOCD.mNumEntries++; - mEOCD.mTotalNumEntries++; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - mEOCD.mCentralDirOffset = endPosn; - - /* - * Add pEntry to the list. - */ - mEntries.add(pEntry); - if (ppEntry != NULL) - *ppEntry = pEntry; - pEntry = NULL; - - result = NO_ERROR; - -bail: - delete pEntry; - return result; -} - -/* - * Copy all of the bytes in "src" to "dst". - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the data. - */ -status_t ZipFile::copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32) -{ - unsigned char tmpBuf[32768]; - size_t count; - - *pCRC32 = crc32(0L, Z_NULL, 0); - - while (1) { - count = fread(tmpBuf, 1, sizeof(tmpBuf), srcFp); - if (ferror(srcFp) || ferror(dstFp)) - return errnoToStatus(errno); - if (count == 0) - break; - - *pCRC32 = crc32(*pCRC32, tmpBuf, count); - - if (fwrite(tmpBuf, 1, count, dstFp) != count) { - ALOGD("fwrite %d bytes failed\n", (int) count); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -/* - * Copy all of the bytes in "src" to "dst". - * - * On exit, "dstFp" will be seeked immediately past the data. - */ -status_t ZipFile::copyDataToFp(FILE* dstFp, - const void* data, size_t size, unsigned long* pCRC32) -{ - size_t count; - - *pCRC32 = crc32(0L, Z_NULL, 0); - if (size > 0) { - *pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size); - if (fwrite(data, 1, size, dstFp) != size) { - ALOGD("fwrite %d bytes failed\n", (int) size); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -/* - * Copy some of the bytes in "src" to "dst". - * - * If "pCRC32" is NULL, the CRC will not be computed. - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the data just written. - */ -status_t ZipFile::copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length, - unsigned long* pCRC32) -{ - unsigned char tmpBuf[32768]; - size_t count; - - if (pCRC32 != NULL) - *pCRC32 = crc32(0L, Z_NULL, 0); - - while (length) { - long readSize; - - readSize = sizeof(tmpBuf); - if (readSize > length) - readSize = length; - - count = fread(tmpBuf, 1, readSize, srcFp); - if ((long) count != readSize) { // error or unexpected EOF - ALOGD("fread %d bytes failed\n", (int) readSize); - return UNKNOWN_ERROR; - } - - if (pCRC32 != NULL) - *pCRC32 = crc32(*pCRC32, tmpBuf, count); - - if (fwrite(tmpBuf, 1, count, dstFp) != count) { - ALOGD("fwrite %d bytes failed\n", (int) count); - return UNKNOWN_ERROR; - } - - length -= readSize; - } - - return NO_ERROR; -} - -/* - * Compress all of the data in "srcFp" and write it to "dstFp". - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the compressed data. - */ -status_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, - const void* data, size_t size, unsigned long* pCRC32) -{ - status_t result = NO_ERROR; - const size_t kBufSize = 32768; - unsigned char* inBuf = NULL; - unsigned char* outBuf = NULL; - z_stream zstream; - bool atEof = false; // no feof() aviailable yet - unsigned long crc; - int zerr; - - /* - * Create an input buffer and an output buffer. - */ - inBuf = new unsigned char[kBufSize]; - outBuf = new unsigned char[kBufSize]; - if (inBuf == NULL || outBuf == NULL) { - result = NO_MEMORY; - goto bail; - } - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - zstream.data_type = Z_UNKNOWN; - - zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (zerr != Z_OK) { - result = UNKNOWN_ERROR; - if (zerr == Z_VERSION_ERROR) { - ALOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - ALOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - crc = crc32(0L, Z_NULL, 0); - - /* - * Loop while we have data. - */ - do { - size_t getSize; - int flush; - - /* only read if the input buffer is empty */ - if (zstream.avail_in == 0 && !atEof) { - ALOGV("+++ reading %d bytes\n", (int)kBufSize); - if (data) { - getSize = size > kBufSize ? kBufSize : size; - memcpy(inBuf, data, getSize); - data = ((const char*)data) + getSize; - size -= getSize; - } else { - getSize = fread(inBuf, 1, kBufSize, srcFp); - if (ferror(srcFp)) { - ALOGD("deflate read failed (errno=%d)\n", errno); - goto z_bail; - } - } - if (getSize < kBufSize) { - ALOGV("+++ got %d bytes, EOF reached\n", - (int)getSize); - atEof = true; - } - - crc = crc32(crc, inBuf, getSize); - - zstream.next_in = inBuf; - zstream.avail_in = getSize; - } - - if (atEof) - flush = Z_FINISH; /* tell zlib that we're done */ - else - flush = Z_NO_FLUSH; /* more to come! */ - - zerr = deflate(&zstream, flush); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - ALOGD("zlib deflate call failed (zerr=%d)\n", zerr); - result = UNKNOWN_ERROR; - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize)) - { - ALOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf)); - if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) != - (size_t)(zstream.next_out - outBuf)) - { - ALOGD("write %d failed in deflate\n", - (int) (zstream.next_out - outBuf)); - goto z_bail; - } - - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - *pCRC32 = crc; - -z_bail: - deflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] inBuf; - delete[] outBuf; - - return result; -} - -/* - * Mark an entry as deleted. - * - * We will eventually need to crunch the file down, but if several files - * are being removed (perhaps as part of an "update" process) we can make - * things considerably faster by deferring the removal to "flush" time. - */ -status_t ZipFile::remove(ZipEntry* pEntry) -{ - /* - * Should verify that pEntry is actually part of this archive, and - * not some stray ZipEntry from a different file. - */ - - /* mark entry as deleted, and mark archive as dirty */ - pEntry->setDeleted(); - mNeedCDRewrite = true; - return NO_ERROR; -} - -/* - * Flush any pending writes. - * - * In particular, this will crunch out deleted entries, and write the - * Central Directory and EOCD if we have stomped on them. - */ -status_t ZipFile::flush(void) -{ - status_t result = NO_ERROR; - long eocdPosn; - int i, count; - - if (mReadOnly) - return INVALID_OPERATION; - if (!mNeedCDRewrite) - return NO_ERROR; - - assert(mZipFp != NULL); - - result = crunchArchive(); - if (result != NO_ERROR) - return result; - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) - return UNKNOWN_ERROR; - - count = mEntries.size(); - for (i = 0; i < count; i++) { - ZipEntry* pEntry = mEntries[i]; - pEntry->mCDE.write(mZipFp); - } - - eocdPosn = ftell(mZipFp); - mEOCD.mCentralDirSize = eocdPosn - mEOCD.mCentralDirOffset; - - mEOCD.write(mZipFp); - - /* - * If we had some stuff bloat up during compression and get replaced - * with plain files, or if we deleted some entries, there's a lot - * of wasted space at the end of the file. Remove it now. - */ - if (ftruncate(fileno(mZipFp), ftell(mZipFp)) != 0) { - ALOGW("ftruncate failed %ld: %s\n", ftell(mZipFp), strerror(errno)); - // not fatal - } - - /* should we clear the "newly added" flag in all entries now? */ - - mNeedCDRewrite = false; - return NO_ERROR; -} - -/* - * Crunch deleted files out of an archive by shifting the later files down. - * - * Because we're not using a temp file, we do the operation inside the - * current file. - */ -status_t ZipFile::crunchArchive(void) -{ - status_t result = NO_ERROR; - int i, count; - long delCount, adjust; - -#if 0 - printf("CONTENTS:\n"); - for (i = 0; i < (int) mEntries.size(); i++) { - printf(" %d: lfhOff=%ld del=%d\n", - i, mEntries[i]->getLFHOffset(), mEntries[i]->getDeleted()); - } - printf(" END is %ld\n", (long) mEOCD.mCentralDirOffset); -#endif - - /* - * Roll through the set of files, shifting them as appropriate. We - * could probably get a slight performance improvement by sliding - * multiple files down at once (because we could use larger reads - * when operating on batches of small files), but it's not that useful. - */ - count = mEntries.size(); - delCount = adjust = 0; - for (i = 0; i < count; i++) { - ZipEntry* pEntry = mEntries[i]; - long span; - - if (pEntry->getLFHOffset() != 0) { - long nextOffset; - - /* Get the length of this entry by finding the offset - * of the next entry. Directory entries don't have - * file offsets, so we need to find the next non-directory - * entry. - */ - nextOffset = 0; - for (int ii = i+1; nextOffset == 0 && ii < count; ii++) - nextOffset = mEntries[ii]->getLFHOffset(); - if (nextOffset == 0) - nextOffset = mEOCD.mCentralDirOffset; - span = nextOffset - pEntry->getLFHOffset(); - - assert(span >= ZipEntry::LocalFileHeader::kLFHLen); - } else { - /* This is a directory entry. It doesn't have - * any actual file contents, so there's no need to - * move anything. - */ - span = 0; - } - - //printf("+++ %d: off=%ld span=%ld del=%d [count=%d]\n", - // i, pEntry->getLFHOffset(), span, pEntry->getDeleted(), count); - - if (pEntry->getDeleted()) { - adjust += span; - delCount++; - - delete pEntry; - mEntries.removeAt(i); - - /* adjust loop control */ - count--; - i--; - } else if (span != 0 && adjust > 0) { - /* shuffle this entry back */ - //printf("+++ Shuffling '%s' back %ld\n", - // pEntry->getFileName(), adjust); - result = filemove(mZipFp, pEntry->getLFHOffset() - adjust, - pEntry->getLFHOffset(), span); - if (result != NO_ERROR) { - /* this is why you use a temp file */ - ALOGE("error during crunch - archive is toast\n"); - return result; - } - - pEntry->setLFHOffset(pEntry->getLFHOffset() - adjust); - } - } - - /* - * Fix EOCD info. We have to wait until the end to do some of this - * because we use mCentralDirOffset to determine "span" for the - * last entry. - */ - mEOCD.mCentralDirOffset -= adjust; - mEOCD.mNumEntries -= delCount; - mEOCD.mTotalNumEntries -= delCount; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - - assert(mEOCD.mNumEntries == mEOCD.mTotalNumEntries); - assert(mEOCD.mNumEntries == count); - - return result; -} - -/* - * Works like memmove(), but on pieces of a file. - */ -status_t ZipFile::filemove(FILE* fp, off_t dst, off_t src, size_t n) -{ - if (dst == src || n <= 0) - return NO_ERROR; - - unsigned char readBuf[32768]; - - if (dst < src) { - /* shift stuff toward start of file; must read from start */ - while (n != 0) { - size_t getSize = sizeof(readBuf); - if (getSize > n) - getSize = n; - - if (fseek(fp, (long) src, SEEK_SET) != 0) { - ALOGD("filemove src seek %ld failed\n", (long) src); - return UNKNOWN_ERROR; - } - - if (fread(readBuf, 1, getSize, fp) != getSize) { - ALOGD("filemove read %ld off=%ld failed\n", - (long) getSize, (long) src); - return UNKNOWN_ERROR; - } - - if (fseek(fp, (long) dst, SEEK_SET) != 0) { - ALOGD("filemove dst seek %ld failed\n", (long) dst); - return UNKNOWN_ERROR; - } - - if (fwrite(readBuf, 1, getSize, fp) != getSize) { - ALOGD("filemove write %ld off=%ld failed\n", - (long) getSize, (long) dst); - return UNKNOWN_ERROR; - } - - src += getSize; - dst += getSize; - n -= getSize; - } - } else { - /* shift stuff toward end of file; must read from end */ - assert(false); // write this someday, maybe - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - - -/* - * Get the modification time from a file descriptor. - */ -time_t ZipFile::getModTime(int fd) -{ - struct stat sb; - - if (fstat(fd, &sb) < 0) { - ALOGD("HEY: fstat on fd %d failed\n", fd); - return (time_t) -1; - } - - return sb.st_mtime; -} - - -#if 0 /* this is a bad idea */ -/* - * Get a copy of the Zip file descriptor. - * - * We don't allow this if the file was opened read-write because we tend - * to leave the file contents in an uncertain state between calls to - * flush(). The duplicated file descriptor should only be valid for reads. - */ -int ZipFile::getZipFd(void) const -{ - if (!mReadOnly) - return INVALID_OPERATION; - assert(mZipFp != NULL); - - int fd; - fd = dup(fileno(mZipFp)); - if (fd < 0) { - ALOGD("didn't work, errno=%d\n", errno); - } - - return fd; -} -#endif - - -#if 0 -/* - * Expand data. - */ -bool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const -{ - return false; -} -#endif - -// free the memory when you're done -void* ZipFile::uncompress(const ZipEntry* entry) -{ - size_t unlen = entry->getUncompressedLen(); - size_t clen = entry->getCompressedLen(); - - void* buf = malloc(unlen); - if (buf == NULL) { - return NULL; - } - - fseek(mZipFp, 0, SEEK_SET); - - off_t offset = entry->getFileOffset(); - if (fseek(mZipFp, offset, SEEK_SET) != 0) { - goto bail; - } - - switch (entry->getCompressionMethod()) - { - case ZipEntry::kCompressStored: { - ssize_t amt = fread(buf, 1, unlen, mZipFp); - if (amt != (ssize_t)unlen) { - goto bail; - } -#if 0 - printf("data...\n"); - const unsigned char* p = (unsigned char*)buf; - const unsigned char* end = p+unlen; - for (int i=0; i<32 && p < end; i++) { - printf("0x%08x ", (int)(offset+(i*0x10))); - for (int j=0; j<0x10 && p < end; j++) { - printf(" %02x", *p); - p++; - } - printf("\n"); - } -#endif - - } - break; - case ZipEntry::kCompressDeflated: { - if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) { - goto bail; - } - } - break; - default: - goto bail; - } - return buf; - -bail: - free(buf); - return NULL; -} - - -/* - * =========================================================================== - * ZipFile::EndOfCentralDir - * =========================================================================== - */ - -/* - * Read the end-of-central-dir fields. - * - * "buf" should be positioned at the EOCD signature, and should contain - * the entire EOCD area including the comment. - */ -status_t ZipFile::EndOfCentralDir::readBuf(const unsigned char* buf, int len) -{ - /* don't allow re-use */ - assert(mComment == NULL); - - if (len < kEOCDLen) { - /* looks like ZIP file got truncated */ - ALOGD(" Zip EOCD: expected >= %d bytes, found %d\n", - kEOCDLen, len); - return INVALID_OPERATION; - } - - /* this should probably be an assert() */ - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) - return UNKNOWN_ERROR; - - mDiskNumber = ZipEntry::getShortLE(&buf[0x04]); - mDiskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]); - mNumEntries = ZipEntry::getShortLE(&buf[0x08]); - mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]); - mCentralDirSize = ZipEntry::getLongLE(&buf[0x0c]); - mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]); - mCommentLen = ZipEntry::getShortLE(&buf[0x14]); - - // TODO: validate mCentralDirOffset - - if (mCommentLen > 0) { - if (kEOCDLen + mCommentLen > len) { - ALOGD("EOCD(%d) + comment(%d) exceeds len (%d)\n", - kEOCDLen, mCommentLen, len); - return UNKNOWN_ERROR; - } - mComment = new unsigned char[mCommentLen]; - memcpy(mComment, buf + kEOCDLen, mCommentLen); - } - - return NO_ERROR; -} - -/* - * Write an end-of-central-directory section. - */ -status_t ZipFile::EndOfCentralDir::write(FILE* fp) -{ - unsigned char buf[kEOCDLen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mDiskNumber); - ZipEntry::putShortLE(&buf[0x06], mDiskWithCentralDir); - ZipEntry::putShortLE(&buf[0x08], mNumEntries); - ZipEntry::putShortLE(&buf[0x0a], mTotalNumEntries); - ZipEntry::putLongLE(&buf[0x0c], mCentralDirSize); - ZipEntry::putLongLE(&buf[0x10], mCentralDirOffset); - ZipEntry::putShortLE(&buf[0x14], mCommentLen); - - if (fwrite(buf, 1, kEOCDLen, fp) != kEOCDLen) - return UNKNOWN_ERROR; - if (mCommentLen > 0) { - assert(mComment != NULL); - if (fwrite(mComment, mCommentLen, 1, fp) != mCommentLen) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -/* - * Dump the contents of an EndOfCentralDir object. - */ -void ZipFile::EndOfCentralDir::dump(void) const -{ - ALOGD(" EndOfCentralDir contents:\n"); - ALOGD(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", - mDiskNumber, mDiskWithCentralDir, mNumEntries, mTotalNumEntries); - ALOGD(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", - mCentralDirSize, mCentralDirOffset, mCommentLen); -} - diff --git a/tools/aapt/ZipFile.h b/tools/aapt/ZipFile.h deleted file mode 100644 index 7877550..0000000 --- a/tools/aapt/ZipFile.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2006 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. - */ - -// -// General-purpose Zip archive access. This class allows both reading and -// writing to Zip archives, including deletion of existing entries. -// -#ifndef __LIBS_ZIPFILE_H -#define __LIBS_ZIPFILE_H - -#include <utils/Vector.h> -#include <utils/Errors.h> -#include <stdio.h> - -#include "ZipEntry.h" - -namespace android { - -/* - * Manipulate a Zip archive. - * - * Some changes will not be visible in the until until "flush" is called. - * - * The correct way to update a file archive is to make all changes to a - * copy of the archive in a temporary file, and then unlink/rename over - * the original after everything completes. Because we're only interested - * in using this for packaging, we don't worry about such things. Crashing - * after making changes and before flush() completes could leave us with - * an unusable Zip archive. - */ -class ZipFile { -public: - ZipFile(void) - : mZipFp(NULL), mReadOnly(false), mNeedCDRewrite(false) - {} - ~ZipFile(void) { - if (!mReadOnly) - flush(); - if (mZipFp != NULL) - fclose(mZipFp); - discardEntries(); - } - - /* - * Open a new or existing archive. - */ - enum { - kOpenReadOnly = 0x01, - kOpenReadWrite = 0x02, - kOpenCreate = 0x04, // create if it doesn't exist - kOpenTruncate = 0x08, // if it exists, empty it - }; - status_t open(const char* zipFileName, int flags); - - /* - * Add a file to the end of the archive. Specify whether you want the - * library to try to store it compressed. - * - * If "storageName" is specified, the archive will use that instead - * of "fileName". - * - * If there is already an entry with the same name, the call fails. - * Existing entries with the same name must be removed first. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ - status_t add(const char* fileName, int compressionMethod, - ZipEntry** ppEntry) - { - return add(fileName, fileName, compressionMethod, ppEntry); - } - status_t add(const char* fileName, const char* storageName, - int compressionMethod, ZipEntry** ppEntry) - { - return addCommon(fileName, NULL, 0, storageName, - ZipEntry::kCompressStored, - compressionMethod, ppEntry); - } - - /* - * Add a file that is already compressed with gzip. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ - status_t addGzip(const char* fileName, const char* storageName, - ZipEntry** ppEntry) - { - return addCommon(fileName, NULL, 0, storageName, - ZipEntry::kCompressDeflated, - ZipEntry::kCompressDeflated, ppEntry); - } - - /* - * Add a file from an in-memory data buffer. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ - status_t add(const void* data, size_t size, const char* storageName, - int compressionMethod, ZipEntry** ppEntry) - { - return addCommon(NULL, data, size, storageName, - ZipEntry::kCompressStored, - compressionMethod, ppEntry); - } - - /* - * Add an entry by copying it from another zip file. If "padding" is - * nonzero, the specified number of bytes will be added to the "extra" - * field in the header. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ - status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, - int padding, ZipEntry** ppEntry); - - /* - * Mark an entry as having been removed. It is not actually deleted - * from the archive or our internal data structures until flush() is - * called. - */ - status_t remove(ZipEntry* pEntry); - - /* - * Flush changes. If mNeedCDRewrite is set, this writes the central dir. - */ - status_t flush(void); - - /* - * Expand the data into the buffer provided. The buffer must hold - * at least <uncompressed len> bytes. Variation expands directly - * to a file. - * - * Returns "false" if an error was encountered in the compressed data. - */ - //bool uncompress(const ZipEntry* pEntry, void* buf) const; - //bool uncompress(const ZipEntry* pEntry, FILE* fp) const; - void* uncompress(const ZipEntry* pEntry); - - /* - * Get an entry, by name. Returns NULL if not found. - * - * Does not return entries pending deletion. - */ - ZipEntry* getEntryByName(const char* fileName) const; - - /* - * Get the Nth entry in the archive. - * - * This will return an entry that is pending deletion. - */ - int getNumEntries(void) const { return mEntries.size(); } - ZipEntry* getEntryByIndex(int idx) const; - -private: - /* these are private and not defined */ - ZipFile(const ZipFile& src); - ZipFile& operator=(const ZipFile& src); - - class EndOfCentralDir { - public: - EndOfCentralDir(void) : - mDiskNumber(0), - mDiskWithCentralDir(0), - mNumEntries(0), - mTotalNumEntries(0), - mCentralDirSize(0), - mCentralDirOffset(0), - mCommentLen(0), - mComment(NULL) - {} - virtual ~EndOfCentralDir(void) { - delete[] mComment; - } - - status_t readBuf(const unsigned char* buf, int len); - status_t write(FILE* fp); - - //unsigned long mSignature; - unsigned short mDiskNumber; - unsigned short mDiskWithCentralDir; - unsigned short mNumEntries; - unsigned short mTotalNumEntries; - unsigned long mCentralDirSize; - unsigned long mCentralDirOffset; // offset from first disk - unsigned short mCommentLen; - unsigned char* mComment; - - enum { - kSignature = 0x06054b50, - kEOCDLen = 22, // EndOfCentralDir len, excl. comment - - kMaxCommentLen = 65535, // longest possible in ushort - kMaxEOCDSearch = kMaxCommentLen + EndOfCentralDir::kEOCDLen, - - }; - - void dump(void) const; - }; - - - /* read all entries in the central dir */ - status_t readCentralDir(void); - - /* crunch deleted entries out */ - status_t crunchArchive(void); - - /* clean up mEntries */ - void discardEntries(void); - - /* common handler for all "add" functions */ - status_t addCommon(const char* fileName, const void* data, size_t size, - const char* storageName, int sourceType, int compressionMethod, - ZipEntry** ppEntry); - - /* copy all of "srcFp" into "dstFp" */ - status_t copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32); - /* copy all of "data" into "dstFp" */ - status_t copyDataToFp(FILE* dstFp, - const void* data, size_t size, unsigned long* pCRC32); - /* copy some of "srcFp" into "dstFp" */ - status_t copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length, - unsigned long* pCRC32); - /* like memmove(), but on parts of a single file */ - status_t filemove(FILE* fp, off_t dest, off_t src, size_t n); - /* compress all of "srcFp" into "dstFp", using Deflate */ - status_t compressFpToFp(FILE* dstFp, FILE* srcFp, - const void* data, size_t size, unsigned long* pCRC32); - - /* get modification date from a file descriptor */ - time_t getModTime(int fd); - - /* - * We use stdio FILE*, which gives us buffering but makes dealing - * with files >2GB awkward. Until we support Zip64, we're fine. - */ - FILE* mZipFp; // Zip file pointer - - /* one of these per file */ - EndOfCentralDir mEOCD; - - /* did we open this read-only? */ - bool mReadOnly; - - /* set this when we trash the central dir */ - bool mNeedCDRewrite; - - /* - * One ZipEntry per entry in the zip file. I'm using pointers instead - * of objects because it's easier than making operator= work for the - * classes and sub-classes. - */ - Vector<ZipEntry*> mEntries; -}; - -}; // namespace android - -#endif // __LIBS_ZIPFILE_H diff --git a/tools/aapt/printapk.cpp b/tools/aapt/printapk.cpp deleted file mode 100644 index 4cf73d8..0000000 --- a/tools/aapt/printapk.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include <utils/ResourceTypes.h> -#include <utils/String8.h> -#include <utils/String16.h> -#include <zipfile/zipfile.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> - -using namespace android; - -static int -usage() -{ - fprintf(stderr, - "usage: apk APKFILE\n" - "\n" - "APKFILE an android packge file produced by aapt.\n" - ); - return 1; -} - - -int -main(int argc, char** argv) -{ - const char* filename; - int fd; - ssize_t amt; - off_t size; - void* buf; - zipfile_t zip; - zipentry_t entry; - void* cookie; - void* resfile; - int bufsize; - int err; - - if (argc != 2) { - return usage(); - } - - filename = argv[1]; - fd = open(filename, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "apk: couldn't open file for read: %s\n", filename); - return 1; - } - - size = lseek(fd, 0, SEEK_END); - amt = lseek(fd, 0, SEEK_SET); - - if (size < 0 || amt < 0) { - fprintf(stderr, "apk: error determining file size: %s\n", filename); - return 1; - } - - buf = malloc(size); - if (buf == NULL) { - fprintf(stderr, "apk: file too big: %s\n", filename); - return 1; - } - - amt = read(fd, buf, size); - if (amt != size) { - fprintf(stderr, "apk: error reading file: %s\n", filename); - return 1; - } - - close(fd); - - zip = init_zipfile(buf, size); - if (zip == NULL) { - fprintf(stderr, "apk: file doesn't seem to be a zip file: %s\n", - filename); - return 1; - } - - printf("files:\n"); - cookie = NULL; - while ((entry = iterate_zipfile(zip, &cookie))) { - char* name = get_zipentry_name(entry); - printf(" %s\n", name); - free(name); - } - - entry = lookup_zipentry(zip, "resources.arsc"); - if (entry != NULL) { - size = get_zipentry_size(entry); - bufsize = size + (size / 1000) + 1; - resfile = malloc(bufsize); - - err = decompress_zipentry(entry, resfile, bufsize); - if (err != 0) { - fprintf(stderr, "apk: error decompressing resources.arsc"); - return 1; - } - - ResTable res(resfile, size, resfile); - res.print(); -#if 0 - size_t tableCount = res.getTableCount(); - printf("Tables: %d\n", (int)tableCount); - for (size_t tableIndex=0; tableIndex<tableCount; tableIndex++) { - const ResStringPool* strings = res.getTableStringBlock(tableIndex); - size_t stringCount = strings->size(); - for (size_t stringIndex=0; stringIndex<stringCount; stringIndex++) { - size_t len; - const char16_t* ch = strings->stringAt(stringIndex, &len); - String8 s(String16(ch, len)); - printf(" [%3d] %s\n", (int)stringIndex, s.string()); - } - } - - size_t basePackageCount = res.getBasePackageCount(); - printf("Base Packages: %d\n", (int)basePackageCount); - for (size_t bpIndex=0; bpIndex<basePackageCount; bpIndex++) { - const char16_t* ch = res.getBasePackageName(bpIndex); - String8 s = String8(String16(ch)); - printf(" [%3d] %s\n", (int)bpIndex, s.string()); - } -#endif - } - - - return 0; -} diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp deleted file mode 100644 index 9e50c5a..0000000 --- a/tools/aapt/pseudolocalize.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "pseudolocalize.h" - -using namespace std; - -static const char* -pseudolocalize_char(char c) -{ - switch (c) { - case 'a': return "\xc4\x83"; - case 'b': return "\xcf\x84"; - case 'c': return "\xc4\x8b"; - case 'd': return "\xc4\x8f"; - case 'e': return "\xc4\x99"; - case 'f': return "\xc6\x92"; - case 'g': return "\xc4\x9d"; - case 'h': return "\xd1\x9b"; - case 'i': return "\xcf\x8a"; - case 'j': return "\xc4\xb5"; - case 'k': return "\xc4\xb8"; - case 'l': return "\xc4\xba"; - case 'm': return "\xe1\xb8\xbf"; - case 'n': return "\xd0\xb8"; - case 'o': return "\xcf\x8c"; - case 'p': return "\xcf\x81"; - case 'q': return "\x51"; - case 'r': return "\xd2\x91"; - case 's': return "\xc5\xa1"; - case 't': return "\xd1\x82"; - case 'u': return "\xce\xb0"; - case 'v': return "\x56"; - case 'w': return "\xe1\xba\x85"; - case 'x': return "\xd1\x85"; - case 'y': return "\xe1\xbb\xb3"; - case 'z': return "\xc5\xba"; - case 'A': return "\xc3\x85"; - case 'B': return "\xce\xb2"; - case 'C': return "\xc4\x88"; - case 'D': return "\xc4\x90"; - case 'E': return "\xd0\x84"; - case 'F': return "\xce\x93"; - case 'G': return "\xc4\x9e"; - case 'H': return "\xc4\xa6"; - case 'I': return "\xd0\x87"; - case 'J': return "\xc4\xb5"; - case 'K': return "\xc4\xb6"; - case 'L': return "\xc5\x81"; - case 'M': return "\xe1\xb8\xbe"; - case 'N': return "\xc5\x83"; - case 'O': return "\xce\x98"; - case 'P': return "\xcf\x81"; - case 'Q': return "\x71"; - case 'R': return "\xd0\xaf"; - case 'S': return "\xc8\x98"; - case 'T': return "\xc5\xa6"; - case 'U': return "\xc5\xa8"; - case 'V': return "\xce\xbd"; - case 'W': return "\xe1\xba\x84"; - case 'X': return "\xc3\x97"; - case 'Y': return "\xc2\xa5"; - case 'Z': return "\xc5\xbd"; - default: return NULL; - } -} - -/** - * Converts characters so they look like they've been localized. - * - * Note: This leaves escape sequences untouched so they can later be - * processed by ResTable::collectString in the normal way. - */ -string -pseudolocalize_string(const string& source) -{ - const char* s = source.c_str(); - string result; - const size_t I = source.length(); - for (size_t i=0; i<I; i++) { - char c = s[i]; - if (c == '\\') { - if (i<I-1) { - result += '\\'; - i++; - c = s[i]; - switch (c) { - case 'u': - // this one takes up 5 chars - result += string(s+i, 5); - i += 4; - break; - case 't': - case 'n': - case '#': - case '@': - case '?': - case '"': - case '\'': - case '\\': - default: - result += c; - break; - } - } else { - result += c; - } - } else { - const char* p = pseudolocalize_char(c); - if (p != NULL) { - result += p; - } else { - result += c; - } - } - } - - //printf("result=\'%s\'\n", result.c_str()); - return result; -} - - diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h deleted file mode 100644 index 94cb034..0000000 --- a/tools/aapt/pseudolocalize.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef HOST_PSEUDOLOCALIZE_H -#define HOST_PSEUDOLOCALIZE_H - -#include <string> - -std::string pseudolocalize_string(const std::string& source); - -#endif // HOST_PSEUDOLOCALIZE_H - diff --git a/tools/aapt/qsort_r_compat.c b/tools/aapt/qsort_r_compat.c deleted file mode 100644 index 2a8dbe8..0000000 --- a/tools/aapt/qsort_r_compat.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2012 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 <stdlib.h> -#include "qsort_r_compat.h" - -/* - * Note: This code is only used on the host, and is primarily here for - * Mac OS compatibility. Apparently, glibc and Apple's libc disagree on - * the parameter order for qsort_r. - */ - -#if HAVE_BSD_QSORT_R - -/* - * BSD qsort_r parameter order is as we have defined here. - */ - -void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, - int (*compar)(void*, const void* , const void*)) { - qsort_r(base, nel, width, thunk, compar); -} - -#elif HAVE_GNU_QSORT_R - -/* - * GNU qsort_r parameter order places the thunk parameter last. - */ - -struct compar_data { - void* thunk; - int (*compar)(void*, const void* , const void*); -}; - -static int compar_wrapper(const void* a, const void* b, void* data) { - struct compar_data* compar_data = (struct compar_data*)data; - return compar_data->compar(compar_data->thunk, a, b); -} - -void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, - int (*compar)(void*, const void* , const void*)) { - struct compar_data compar_data; - compar_data.thunk = thunk; - compar_data.compar = compar; - qsort_r(base, nel, width, compar_wrapper, &compar_data); -} - -#else - -/* - * Emulate qsort_r using thread local storage to access the thunk data. - */ - -#include <cutils/threads.h> - -static thread_store_t compar_data_key = THREAD_STORE_INITIALIZER; - -struct compar_data { - void* thunk; - int (*compar)(void*, const void* , const void*); -}; - -static int compar_wrapper(const void* a, const void* b) { - struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key); - return compar_data->compar(compar_data->thunk, a, b); -} - -void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, - int (*compar)(void*, const void* , const void*)) { - struct compar_data compar_data; - compar_data.thunk = thunk; - compar_data.compar = compar; - thread_store_set(&compar_data_key, &compar_data, NULL); - qsort(base, nel, width, compar_wrapper); -} - -#endif diff --git a/tools/aapt/qsort_r_compat.h b/tools/aapt/qsort_r_compat.h deleted file mode 100644 index e14f999..0000000 --- a/tools/aapt/qsort_r_compat.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -/* - * Provides a portable version of qsort_r, called qsort_r_compat, which is a - * reentrant variant of qsort that passes a user data pointer to its comparator. - * This implementation follows the BSD parameter convention. - */ - -#ifndef ___QSORT_R_COMPAT_H -#define ___QSORT_R_COMPAT_H - -#include <stdlib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, - int (*compar)(void*, const void* , const void* )); - -#ifdef __cplusplus -} -#endif - -#endif // ___QSORT_R_COMPAT_H diff --git a/tools/aapt/tests/CrunchCache_test.cpp b/tools/aapt/tests/CrunchCache_test.cpp deleted file mode 100644 index 20b5022..0000000 --- a/tools/aapt/tests/CrunchCache_test.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -#include <utils/String8.h> -#include <iostream> -#include <errno.h> - -#include "CrunchCache.h" -#include "FileFinder.h" -#include "MockFileFinder.h" -#include "CacheUpdater.h" -#include "MockCacheUpdater.h" - -using namespace android; -using std::cout; -using std::endl; - -void expectEqual(int got, int expected, const char* desc) { - cout << "Checking " << desc << ": "; - cout << "Got " << got << ", expected " << expected << "..."; - cout << ( (got == expected) ? "PASSED" : "FAILED") << endl; - errno += ((got == expected) ? 0 : 1); -} - -int main() { - - errno = 0; - - String8 source("res"); - String8 dest("res2"); - - // Create data for MockFileFinder to feed to the cache - KeyedVector<String8, time_t> sourceData; - // This shouldn't be updated - sourceData.add(String8("res/drawable/hello.png"),3); - // This should be updated - sourceData.add(String8("res/drawable/world.png"),5); - // This should cause make directory to be called - sourceData.add(String8("res/drawable-cool/hello.png"),3); - - KeyedVector<String8, time_t> destData; - destData.add(String8("res2/drawable/hello.png"),3); - destData.add(String8("res2/drawable/world.png"),3); - // this should call delete - destData.add(String8("res2/drawable/dead.png"),3); - - // Package up data and create mock file finder - KeyedVector<String8, KeyedVector<String8,time_t> > data; - data.add(source,sourceData); - data.add(dest,destData); - FileFinder* ff = new MockFileFinder(data); - CrunchCache cc(source,dest,ff); - - MockCacheUpdater* mcu = new MockCacheUpdater(); - CacheUpdater* cu(mcu); - - cout << "Running Crunch..."; - int result = cc.crunch(cu); - cout << ((result > 0) ? "PASSED" : "FAILED") << endl; - errno += ((result > 0) ? 0 : 1); - - const int EXPECTED_RESULT = 2; - expectEqual(result, EXPECTED_RESULT, "number of files touched"); - - cout << "Checking calls to deleteFile and processImage:" << endl; - const int EXPECTED_DELETES = 1; - const int EXPECTED_PROCESSED = 2; - // Deletes - expectEqual(mcu->deleteCount, EXPECTED_DELETES, "deleteFile"); - // processImage - expectEqual(mcu->processCount, EXPECTED_PROCESSED, "processImage"); - - const int EXPECTED_OVERWRITES = 3; - result = cc.crunch(cu, true); - expectEqual(result, EXPECTED_OVERWRITES, "number of files touched with overwrite"); - \ - - if (errno == 0) - cout << "ALL TESTS PASSED!" << endl; - else - cout << errno << " TESTS FAILED" << endl; - - delete ff; - delete cu; - - // TESTS BELOW WILL GO AWAY SOON - - String8 source2("ApiDemos/res"); - String8 dest2("ApiDemos/res2"); - - FileFinder* sff = new SystemFileFinder(); - CacheUpdater* scu = new SystemCacheUpdater(); - - CrunchCache scc(source2,dest2,sff); - - scc.crunch(scu); -}
\ No newline at end of file diff --git a/tools/aapt/tests/FileFinder_test.cpp b/tools/aapt/tests/FileFinder_test.cpp deleted file mode 100644 index 07bd665..0000000 --- a/tools/aapt/tests/FileFinder_test.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -#include <utils/Vector.h> -#include <utils/KeyedVector.h> -#include <iostream> -#include <cassert> -#include <utils/String8.h> -#include <utility> - -#include "DirectoryWalker.h" -#include "MockDirectoryWalker.h" -#include "FileFinder.h" - -using namespace android; - -using std::pair; -using std::cout; -using std::endl; - - - -int main() -{ - - cout << "\n\n STARTING FILE FINDER TESTS" << endl; - String8 path("ApiDemos"); - - // Storage to pass to findFiles() - KeyedVector<String8,time_t> testStorage; - - // Mock Directory Walker initialization. First data, then sdw - Vector< pair<String8,time_t> > data; - data.push( pair<String8,time_t>(String8("hello.png"),3) ); - data.push( pair<String8,time_t>(String8("world.PNG"),3) ); - data.push( pair<String8,time_t>(String8("foo.pNg"),3) ); - // Neither of these should be found - data.push( pair<String8,time_t>(String8("hello.jpg"),3) ); - data.push( pair<String8,time_t>(String8(".hidden.png"),3)); - - DirectoryWalker* sdw = new StringDirectoryWalker(path,data); - - // Extensions to look for - Vector<String8> exts; - exts.push(String8(".png")); - - errno = 0; - - // Make sure we get a valid mock directory walker - // Make sure we finish without errors - cout << "Checking DirectoryWalker..."; - assert(sdw != NULL); - cout << "PASSED" << endl; - - // Make sure we finish without errors - cout << "Running findFiles()..."; - bool findStatus = FileFinder::findFiles(path,exts, testStorage, sdw); - assert(findStatus); - cout << "PASSED" << endl; - - const size_t SIZE_EXPECTED = 3; - // Check to make sure we have the right number of things in our storage - cout << "Running size comparison: Size is " << testStorage.size() << ", "; - cout << "Expected " << SIZE_EXPECTED << "..."; - if(testStorage.size() == SIZE_EXPECTED) - cout << "PASSED" << endl; - else { - cout << "FAILED" << endl; - errno++; - } - - // Check to make sure that each of our found items has the right extension - cout << "Checking Returned Extensions..."; - bool extsOkay = true; - String8 wrongExts; - for (size_t i = 0; i < SIZE_EXPECTED; ++i) { - String8 testExt(testStorage.keyAt(i).getPathExtension()); - testExt.toLower(); - if (testExt != ".png") { - wrongExts += testStorage.keyAt(i); - wrongExts += "\n"; - extsOkay = false; - } - } - if (extsOkay) - cout << "PASSED" << endl; - else { - cout << "FAILED" << endl; - cout << "The following extensions didn't check out" << endl << wrongExts; - } - - // Clean up - delete sdw; - - if(errno == 0) { - cout << "ALL TESTS PASSED" << endl; - } else { - cout << errno << " TESTS FAILED" << endl; - } - return errno; -}
\ No newline at end of file diff --git a/tools/aapt/tests/MockCacheUpdater.h b/tools/aapt/tests/MockCacheUpdater.h deleted file mode 100644 index c7f4bd7..0000000 --- a/tools/aapt/tests/MockCacheUpdater.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -#ifndef MOCKCACHEUPDATER_H -#define MOCKCACHEUPDATER_H - -#include <utils/String8.h> -#include "CacheUpdater.h" - -using namespace android; - -class MockCacheUpdater : public CacheUpdater { -public: - - MockCacheUpdater() - : deleteCount(0), processCount(0) { }; - - // Make sure all the directories along this path exist - virtual void ensureDirectoriesExist(String8 path) - { - // Nothing to do - }; - - // Delete a file - virtual void deleteFile(String8 path) { - deleteCount++; - }; - - // Process an image from source out to dest - virtual void processImage(String8 source, String8 dest) { - processCount++; - }; - - // DATA MEMBERS - int deleteCount; - int processCount; -private: -}; - -#endif // MOCKCACHEUPDATER_H
\ No newline at end of file diff --git a/tools/aapt/tests/MockDirectoryWalker.h b/tools/aapt/tests/MockDirectoryWalker.h deleted file mode 100644 index 5900cf3..0000000 --- a/tools/aapt/tests/MockDirectoryWalker.h +++ /dev/null @@ -1,85 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// -#ifndef MOCKDIRECTORYWALKER_H -#define MOCKDIRECTORYWALKER_H - -#include <utils/Vector.h> -#include <utils/String8.h> -#include <utility> -#include "DirectoryWalker.h" - -using namespace android; -using std::pair; - -// String8 Directory Walker -// This is an implementation of the Directory Walker abstraction that is built -// for testing. -// Instead of system calls it queries a private data structure for the directory -// entries. It takes a path and a map of filenames and their modification times. -// functions are inlined since they are short and simple - -class StringDirectoryWalker : public DirectoryWalker { -public: - StringDirectoryWalker(String8& path, Vector< pair<String8,time_t> >& data) - : mPos(0), mBasePath(path), mData(data) { - //fprintf(stdout,"StringDW built to mimic %s with %d files\n", - // mBasePath.string()); - }; - // Default copy constructor, and destructor are fine - - virtual bool openDir(String8 path) { - // If the user is trying to query the "directory" that this - // walker was initialized with, then return success. Else fail. - return path == mBasePath; - }; - virtual bool openDir(const char* path) { - String8 p(path); - openDir(p); - return true; - }; - // Advance to next entry in the Vector - virtual struct dirent* nextEntry() { - // Advance position and check to see if we're done - if (mPos >= mData.size()) - return NULL; - - // Place data in the entry descriptor. This class only returns files. - mEntry.d_type = DT_REG; - mEntry.d_ino = mPos; - // Copy chars from the string name to the entry name - size_t i = 0; - for (i; i < mData[mPos].first.size(); ++i) - mEntry.d_name[i] = mData[mPos].first[i]; - mEntry.d_name[i] = '\0'; - - // Place data in stats - mStats.st_ino = mPos; - mStats.st_mtime = mData[mPos].second; - - // Get ready to move to the next entry - mPos++; - - return &mEntry; - }; - // Get the stats for the current entry - virtual struct stat* entryStats() { - return &mStats; - }; - // Nothing to do in clean up - virtual void closeDir() { - // Nothing to do - }; - virtual DirectoryWalker* clone() { - return new StringDirectoryWalker(*this); - }; -private: - // Current position in the Vector - size_t mPos; - // Base path - String8 mBasePath; - // Data to simulate a directory full of files. - Vector< pair<String8,time_t> > mData; -}; - -#endif // MOCKDIRECTORYWALKER_H
\ No newline at end of file diff --git a/tools/aapt/tests/MockFileFinder.h b/tools/aapt/tests/MockFileFinder.h deleted file mode 100644 index da5ea4f..0000000 --- a/tools/aapt/tests/MockFileFinder.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2011 The Android Open Source Project -// - -#ifndef MOCKFILEFINDER_H -#define MOCKFILEFINDER_H - -#include <utils/Vector.h> -#include <utils/KeyedVector.h> -#include <utils/String8.h> - -#include "DirectoryWalker.h" - -using namespace android; - -class MockFileFinder : public FileFinder { -public: - MockFileFinder (KeyedVector<String8, KeyedVector<String8,time_t> >& files) - : mFiles(files) - { - // Nothing left to do - }; - - /** - * findFiles implementation for the abstraction. - * PRECONDITIONS: - * No checking is done, so there MUST be an entry in mFiles with - * path matching basePath. - * - * POSTCONDITIONS: - * fileStore is filled with a copy of the data in mFiles corresponding - * to the basePath. - */ - - virtual bool findFiles(String8 basePath, Vector<String8>& extensions, - KeyedVector<String8,time_t>& fileStore, - DirectoryWalker* dw) - { - const KeyedVector<String8,time_t>* payload(&mFiles.valueFor(basePath)); - // Since KeyedVector doesn't implement swap - // (who doesn't use swap??) we loop and add one at a time. - for (size_t i = 0; i < payload->size(); ++i) { - fileStore.add(payload->keyAt(i),payload->valueAt(i)); - } - return true; - } - -private: - // Virtual mapping between "directories" and the "files" contained - // in them - KeyedVector<String8, KeyedVector<String8,time_t> > mFiles; -}; - - -#endif // MOCKFILEFINDER_H
\ No newline at end of file diff --git a/tools/aapt/tests/plurals/AndroidManifest.xml b/tools/aapt/tests/plurals/AndroidManifest.xml deleted file mode 100644 index c721dee..0000000 --- a/tools/aapt/tests/plurals/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.aapt.test.plurals"> - -</manifest> diff --git a/tools/aapt/tests/plurals/res/values/strings.xml b/tools/aapt/tests/plurals/res/values/strings.xml deleted file mode 100644 index 1c1fc19..0000000 --- a/tools/aapt/tests/plurals/res/values/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="ok">OK</string> - <plurals name="a_plural"> - <item quantity="one">A dog</item> - <item quantity="other">Some dogs</item> - </plurals> -</resources> diff --git a/tools/aapt/tests/plurals/run.sh b/tools/aapt/tests/plurals/run.sh deleted file mode 100755 index 4d39e10..0000000 --- a/tools/aapt/tests/plurals/run.sh +++ /dev/null @@ -1,16 +0,0 @@ -TEST_DIR=tools/aapt/tests/plurals -TEST_OUT_DIR=out/plurals_test - -rm -rf $TEST_OUT_DIR -mkdir -p $TEST_OUT_DIR -mkdir -p $TEST_OUT_DIR/java - -#gdb --args \ -aapt package -v -x -m -z -J $TEST_OUT_DIR/java -M $TEST_DIR/AndroidManifest.xml \ - -I out/target/common/obj/APPS/framework-res_intermediates/package-export.apk \ - -P $TEST_OUT_DIR/public_resources.xml \ - -S $TEST_DIR/res - -echo -echo "==================== FILES CREATED ==================== " -find $TEST_OUT_DIR -type f diff --git a/tools/aidl/AST.cpp b/tools/aidl/AST.cpp deleted file mode 100644 index bfa6765..0000000 --- a/tools/aidl/AST.cpp +++ /dev/null @@ -1,912 +0,0 @@ -#include "AST.h" -#include "Type.h" - -void -WriteModifiers(FILE* to, int mod, int mask) -{ - int m = mod & mask; - - if (m & OVERRIDE) { - fprintf(to, "@Override "); - } - - if ((m & SCOPE_MASK) == PUBLIC) { - fprintf(to, "public "); - } - else if ((m & SCOPE_MASK) == PRIVATE) { - fprintf(to, "private "); - } - else if ((m & SCOPE_MASK) == PROTECTED) { - fprintf(to, "protected "); - } - - if (m & STATIC) { - fprintf(to, "static "); - } - - if (m & FINAL) { - fprintf(to, "final "); - } - - if (m & ABSTRACT) { - fprintf(to, "abstract "); - } -} - -void -WriteArgumentList(FILE* to, const vector<Expression*>& arguments) -{ - size_t N = arguments.size(); - for (size_t i=0; i<N; i++) { - arguments[i]->Write(to); - if (i != N-1) { - fprintf(to, ", "); - } - } -} - -ClassElement::ClassElement() -{ -} - -ClassElement::~ClassElement() -{ -} - -Field::Field() - :ClassElement(), - modifiers(0), - variable(NULL) -{ -} - -Field::Field(int m, Variable* v) - :ClassElement(), - modifiers(m), - variable(v) -{ -} - -Field::~Field() -{ -} - -void -Field::GatherTypes(set<Type*>* types) const -{ - types->insert(this->variable->type); -} - -void -Field::Write(FILE* to) -{ - if (this->comment.length() != 0) { - fprintf(to, "%s\n", this->comment.c_str()); - } - WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL | OVERRIDE); - fprintf(to, "%s %s", this->variable->type->QualifiedName().c_str(), - this->variable->name.c_str()); - if (this->value.length() != 0) { - fprintf(to, " = %s", this->value.c_str()); - } - fprintf(to, ";\n"); -} - -Expression::~Expression() -{ -} - -LiteralExpression::LiteralExpression(const string& v) - :value(v) -{ -} - -LiteralExpression::~LiteralExpression() -{ -} - -void -LiteralExpression::Write(FILE* to) -{ - fprintf(to, "%s", this->value.c_str()); -} - -StringLiteralExpression::StringLiteralExpression(const string& v) - :value(v) -{ -} - -StringLiteralExpression::~StringLiteralExpression() -{ -} - -void -StringLiteralExpression::Write(FILE* to) -{ - fprintf(to, "\"%s\"", this->value.c_str()); -} - -Variable::Variable() - :type(NULL), - name(), - dimension(0) -{ -} - -Variable::Variable(Type* t, const string& n) - :type(t), - name(n), - dimension(0) -{ -} - -Variable::Variable(Type* t, const string& n, int d) - :type(t), - name(n), - dimension(d) -{ -} - -Variable::~Variable() -{ -} - -void -Variable::GatherTypes(set<Type*>* types) const -{ - types->insert(this->type); -} - -void -Variable::WriteDeclaration(FILE* to) -{ - string dim; - for (int i=0; i<this->dimension; i++) { - dim += "[]"; - } - fprintf(to, "%s%s %s", this->type->QualifiedName().c_str(), dim.c_str(), - this->name.c_str()); -} - -void -Variable::Write(FILE* to) -{ - fprintf(to, "%s", name.c_str()); -} - -FieldVariable::FieldVariable(Expression* o, const string& n) - :object(o), - clazz(NULL), - name(n) -{ -} - -FieldVariable::FieldVariable(Type* c, const string& n) - :object(NULL), - clazz(c), - name(n) -{ -} - -FieldVariable::~FieldVariable() -{ -} - -void -FieldVariable::Write(FILE* to) -{ - if (this->object != NULL) { - this->object->Write(to); - } - else if (this->clazz != NULL) { - fprintf(to, "%s", this->clazz->QualifiedName().c_str()); - } - fprintf(to, ".%s", name.c_str()); -} - - -Statement::~Statement() -{ -} - -StatementBlock::StatementBlock() -{ -} - -StatementBlock::~StatementBlock() -{ -} - -void -StatementBlock::Write(FILE* to) -{ - fprintf(to, "{\n"); - int N = this->statements.size(); - for (int i=0; i<N; i++) { - this->statements[i]->Write(to); - } - fprintf(to, "}\n"); -} - -void -StatementBlock::Add(Statement* statement) -{ - this->statements.push_back(statement); -} - -void -StatementBlock::Add(Expression* expression) -{ - this->statements.push_back(new ExpressionStatement(expression)); -} - -ExpressionStatement::ExpressionStatement(Expression* e) - :expression(e) -{ -} - -ExpressionStatement::~ExpressionStatement() -{ -} - -void -ExpressionStatement::Write(FILE* to) -{ - this->expression->Write(to); - fprintf(to, ";\n"); -} - -Assignment::Assignment(Variable* l, Expression* r) - :lvalue(l), - rvalue(r), - cast(NULL) -{ -} - -Assignment::Assignment(Variable* l, Expression* r, Type* c) - :lvalue(l), - rvalue(r), - cast(c) -{ -} - -Assignment::~Assignment() -{ -} - -void -Assignment::Write(FILE* to) -{ - this->lvalue->Write(to); - fprintf(to, " = "); - if (this->cast != NULL) { - fprintf(to, "(%s)", this->cast->QualifiedName().c_str()); - } - this->rvalue->Write(to); -} - -MethodCall::MethodCall(const string& n) - :obj(NULL), - clazz(NULL), - name(n) -{ -} - -MethodCall::MethodCall(const string& n, int argc = 0, ...) - :obj(NULL), - clazz(NULL), - name(n) -{ - va_list args; - va_start(args, argc); - init(argc, args); - va_end(args); -} - -MethodCall::MethodCall(Expression* o, const string& n) - :obj(o), - clazz(NULL), - name(n) -{ -} - -MethodCall::MethodCall(Type* t, const string& n) - :obj(NULL), - clazz(t), - name(n) -{ -} - -MethodCall::MethodCall(Expression* o, const string& n, int argc = 0, ...) - :obj(o), - clazz(NULL), - name(n) -{ - va_list args; - va_start(args, argc); - init(argc, args); - va_end(args); -} - -MethodCall::MethodCall(Type* t, const string& n, int argc = 0, ...) - :obj(NULL), - clazz(t), - name(n) -{ - va_list args; - va_start(args, argc); - init(argc, args); - va_end(args); -} - -MethodCall::~MethodCall() -{ -} - -void -MethodCall::init(int n, va_list args) -{ - for (int i=0; i<n; i++) { - Expression* expression = (Expression*)va_arg(args, void*); - this->arguments.push_back(expression); - } -} - -void -MethodCall::Write(FILE* to) -{ - if (this->obj != NULL) { - this->obj->Write(to); - fprintf(to, "."); - } - else if (this->clazz != NULL) { - fprintf(to, "%s.", this->clazz->QualifiedName().c_str()); - } - fprintf(to, "%s(", this->name.c_str()); - WriteArgumentList(to, this->arguments); - fprintf(to, ")"); -} - -Comparison::Comparison(Expression* l, const string& o, Expression* r) - :lvalue(l), - op(o), - rvalue(r) -{ -} - -Comparison::~Comparison() -{ -} - -void -Comparison::Write(FILE* to) -{ - fprintf(to, "("); - this->lvalue->Write(to); - fprintf(to, "%s", this->op.c_str()); - this->rvalue->Write(to); - fprintf(to, ")"); -} - -NewExpression::NewExpression(Type* t) - :type(t) -{ -} - -NewExpression::NewExpression(Type* t, int argc = 0, ...) - :type(t) -{ - va_list args; - va_start(args, argc); - init(argc, args); - va_end(args); -} - -NewExpression::~NewExpression() -{ -} - -void -NewExpression::init(int n, va_list args) -{ - for (int i=0; i<n; i++) { - Expression* expression = (Expression*)va_arg(args, void*); - this->arguments.push_back(expression); - } -} - -void -NewExpression::Write(FILE* to) -{ - fprintf(to, "new %s(", this->type->InstantiableName().c_str()); - WriteArgumentList(to, this->arguments); - fprintf(to, ")"); -} - -NewArrayExpression::NewArrayExpression(Type* t, Expression* s) - :type(t), - size(s) -{ -} - -NewArrayExpression::~NewArrayExpression() -{ -} - -void -NewArrayExpression::Write(FILE* to) -{ - fprintf(to, "new %s[", this->type->QualifiedName().c_str()); - size->Write(to); - fprintf(to, "]"); -} - -Ternary::Ternary() - :condition(NULL), - ifpart(NULL), - elsepart(NULL) -{ -} - -Ternary::Ternary(Expression* a, Expression* b, Expression* c) - :condition(a), - ifpart(b), - elsepart(c) -{ -} - -Ternary::~Ternary() -{ -} - -void -Ternary::Write(FILE* to) -{ - fprintf(to, "(("); - this->condition->Write(to); - fprintf(to, ")?("); - this->ifpart->Write(to); - fprintf(to, "):("); - this->elsepart->Write(to); - fprintf(to, "))"); -} - -Cast::Cast() - :type(NULL), - expression(NULL) -{ -} - -Cast::Cast(Type* t, Expression* e) - :type(t), - expression(e) -{ -} - -Cast::~Cast() -{ -} - -void -Cast::Write(FILE* to) -{ - fprintf(to, "((%s)", this->type->QualifiedName().c_str()); - expression->Write(to); - fprintf(to, ")"); -} - -VariableDeclaration::VariableDeclaration(Variable* l, Expression* r, Type* c) - :lvalue(l), - cast(c), - rvalue(r) -{ -} - -VariableDeclaration::VariableDeclaration(Variable* l) - :lvalue(l), - cast(NULL), - rvalue(NULL) -{ -} - -VariableDeclaration::~VariableDeclaration() -{ -} - -void -VariableDeclaration::Write(FILE* to) -{ - this->lvalue->WriteDeclaration(to); - if (this->rvalue != NULL) { - fprintf(to, " = "); - if (this->cast != NULL) { - fprintf(to, "(%s)", this->cast->QualifiedName().c_str()); - } - this->rvalue->Write(to); - } - fprintf(to, ";\n"); -} - -IfStatement::IfStatement() - :expression(NULL), - statements(new StatementBlock), - elseif(NULL) -{ -} - -IfStatement::~IfStatement() -{ -} - -void -IfStatement::Write(FILE* to) -{ - if (this->expression != NULL) { - fprintf(to, "if ("); - this->expression->Write(to); - fprintf(to, ") "); - } - this->statements->Write(to); - if (this->elseif != NULL) { - fprintf(to, "else "); - this->elseif->Write(to); - } -} - -ReturnStatement::ReturnStatement(Expression* e) - :expression(e) -{ -} - -ReturnStatement::~ReturnStatement() -{ -} - -void -ReturnStatement::Write(FILE* to) -{ - fprintf(to, "return "); - this->expression->Write(to); - fprintf(to, ";\n"); -} - -TryStatement::TryStatement() - :statements(new StatementBlock) -{ -} - -TryStatement::~TryStatement() -{ -} - -void -TryStatement::Write(FILE* to) -{ - fprintf(to, "try "); - this->statements->Write(to); -} - -CatchStatement::CatchStatement(Variable* e) - :statements(new StatementBlock), - exception(e) -{ -} - -CatchStatement::~CatchStatement() -{ -} - -void -CatchStatement::Write(FILE* to) -{ - fprintf(to, "catch "); - if (this->exception != NULL) { - fprintf(to, "("); - this->exception->WriteDeclaration(to); - fprintf(to, ") "); - } - this->statements->Write(to); -} - -FinallyStatement::FinallyStatement() - :statements(new StatementBlock) -{ -} - -FinallyStatement::~FinallyStatement() -{ -} - -void -FinallyStatement::Write(FILE* to) -{ - fprintf(to, "finally "); - this->statements->Write(to); -} - -Case::Case() - :statements(new StatementBlock) -{ -} - -Case::Case(const string& c) - :statements(new StatementBlock) -{ - cases.push_back(c); -} - -Case::~Case() -{ -} - -void -Case::Write(FILE* to) -{ - int N = this->cases.size(); - if (N > 0) { - for (int i=0; i<N; i++) { - string s = this->cases[i]; - if (s.length() != 0) { - fprintf(to, "case %s:\n", s.c_str()); - } else { - fprintf(to, "default:\n"); - } - } - } else { - fprintf(to, "default:\n"); - } - statements->Write(to); -} - -SwitchStatement::SwitchStatement(Expression* e) - :expression(e) -{ -} - -SwitchStatement::~SwitchStatement() -{ -} - -void -SwitchStatement::Write(FILE* to) -{ - fprintf(to, "switch ("); - this->expression->Write(to); - fprintf(to, ")\n{\n"); - int N = this->cases.size(); - for (int i=0; i<N; i++) { - this->cases[i]->Write(to); - } - fprintf(to, "}\n"); -} - -Break::Break() -{ -} - -Break::~Break() -{ -} - -void -Break::Write(FILE* to) -{ - fprintf(to, "break;\n"); -} - -Method::Method() - :ClassElement(), - modifiers(0), - returnType(NULL), // (NULL means constructor) - returnTypeDimension(0), - statements(NULL) -{ -} - -Method::~Method() -{ -} - -void -Method::GatherTypes(set<Type*>* types) const -{ - size_t N, i; - - if (this->returnType) { - types->insert(this->returnType); - } - - N = this->parameters.size(); - for (i=0; i<N; i++) { - this->parameters[i]->GatherTypes(types); - } - - N = this->exceptions.size(); - for (i=0; i<N; i++) { - types->insert(this->exceptions[i]); - } -} - -void -Method::Write(FILE* to) -{ - size_t N, i; - - if (this->comment.length() != 0) { - fprintf(to, "%s\n", this->comment.c_str()); - } - - WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | ABSTRACT | FINAL | OVERRIDE); - - if (this->returnType != NULL) { - string dim; - for (i=0; i<this->returnTypeDimension; i++) { - dim += "[]"; - } - fprintf(to, "%s%s ", this->returnType->QualifiedName().c_str(), - dim.c_str()); - } - - fprintf(to, "%s(", this->name.c_str()); - - N = this->parameters.size(); - for (i=0; i<N; i++) { - this->parameters[i]->WriteDeclaration(to); - if (i != N-1) { - fprintf(to, ", "); - } - } - - fprintf(to, ")"); - - N = this->exceptions.size(); - for (i=0; i<N; i++) { - if (i == 0) { - fprintf(to, " throws "); - } else { - fprintf(to, ", "); - } - fprintf(to, "%s", this->exceptions[i]->QualifiedName().c_str()); - } - - if (this->statements == NULL) { - fprintf(to, ";\n"); - } else { - fprintf(to, "\n"); - this->statements->Write(to); - } -} - -Class::Class() - :modifiers(0), - what(CLASS), - type(NULL), - extends(NULL) -{ -} - -Class::~Class() -{ -} - -void -Class::GatherTypes(set<Type*>* types) const -{ - int N, i; - - types->insert(this->type); - if (this->extends != NULL) { - types->insert(this->extends); - } - - N = this->interfaces.size(); - for (i=0; i<N; i++) { - types->insert(this->interfaces[i]); - } - - N = this->elements.size(); - for (i=0; i<N; i++) { - this->elements[i]->GatherTypes(types); - } -} - -void -Class::Write(FILE* to) -{ - size_t N, i; - - if (this->comment.length() != 0) { - fprintf(to, "%s\n", this->comment.c_str()); - } - - WriteModifiers(to, this->modifiers, ALL_MODIFIERS); - - if (this->what == Class::CLASS) { - fprintf(to, "class "); - } else { - fprintf(to, "interface "); - } - - string name = this->type->Name(); - size_t pos = name.rfind('.'); - if (pos != string::npos) { - name = name.c_str() + pos + 1; - } - - fprintf(to, "%s", name.c_str()); - - if (this->extends != NULL) { - fprintf(to, " extends %s", this->extends->QualifiedName().c_str()); - } - - N = this->interfaces.size(); - if (N != 0) { - if (this->what == Class::CLASS) { - fprintf(to, " implements"); - } else { - fprintf(to, " extends"); - } - for (i=0; i<N; i++) { - fprintf(to, " %s", this->interfaces[i]->QualifiedName().c_str()); - } - } - - fprintf(to, "\n"); - fprintf(to, "{\n"); - - N = this->elements.size(); - for (i=0; i<N; i++) { - this->elements[i]->Write(to); - } - - fprintf(to, "}\n"); - -} - -Document::Document() -{ -} - -Document::~Document() -{ -} - -static string -escape_backslashes(const string& str) -{ - string result; - const size_t I=str.length(); - for (size_t i=0; i<I; i++) { - char c = str[i]; - if (c == '\\') { - result += "\\\\"; - } else { - result += c; - } - } - return result; -} - -void -Document::Write(FILE* to) -{ - size_t N, i; - - if (this->comment.length() != 0) { - fprintf(to, "%s\n", this->comment.c_str()); - } - fprintf(to, "/*\n" - " * This file is auto-generated. DO NOT MODIFY.\n" - " * Original file: %s\n" - " */\n", escape_backslashes(this->originalSrc).c_str()); - if (this->package.length() != 0) { - fprintf(to, "package %s;\n", this->package.c_str()); - } - - N = this->classes.size(); - for (i=0; i<N; i++) { - Class* c = this->classes[i]; - c->Write(to); - } -} - diff --git a/tools/aidl/AST.h b/tools/aidl/AST.h deleted file mode 100644 index ead5e7a..0000000 --- a/tools/aidl/AST.h +++ /dev/null @@ -1,371 +0,0 @@ -#ifndef AIDL_AST_H -#define AIDL_AST_H - -#include <string> -#include <vector> -#include <set> -#include <stdarg.h> -#include <stdio.h> - -using namespace std; - -class Type; - -enum { - PACKAGE_PRIVATE = 0x00000000, - PUBLIC = 0x00000001, - PRIVATE = 0x00000002, - PROTECTED = 0x00000003, - SCOPE_MASK = 0x00000003, - - STATIC = 0x00000010, - FINAL = 0x00000020, - ABSTRACT = 0x00000040, - - OVERRIDE = 0x00000100, - - ALL_MODIFIERS = 0xffffffff -}; - -// Write the modifiers that are set in both mod and mask -void WriteModifiers(FILE* to, int mod, int mask); - -struct ClassElement -{ - ClassElement(); - virtual ~ClassElement(); - - virtual void GatherTypes(set<Type*>* types) const = 0; - virtual void Write(FILE* to) = 0; -}; - -struct Expression -{ - virtual ~Expression(); - virtual void Write(FILE* to) = 0; -}; - -struct LiteralExpression : public Expression -{ - string value; - - LiteralExpression(const string& value); - virtual ~LiteralExpression(); - virtual void Write(FILE* to); -}; - -// TODO: also escape the contents. not needed for now -struct StringLiteralExpression : public Expression -{ - string value; - - StringLiteralExpression(const string& value); - virtual ~StringLiteralExpression(); - virtual void Write(FILE* to); -}; - -struct Variable : public Expression -{ - Type* type; - string name; - int dimension; - - Variable(); - Variable(Type* type, const string& name); - Variable(Type* type, const string& name, int dimension); - virtual ~Variable(); - - virtual void GatherTypes(set<Type*>* types) const; - void WriteDeclaration(FILE* to); - void Write(FILE* to); -}; - -struct FieldVariable : public Expression -{ - Expression* object; - Type* clazz; - string name; - - FieldVariable(Expression* object, const string& name); - FieldVariable(Type* clazz, const string& name); - virtual ~FieldVariable(); - - void Write(FILE* to); -}; - -struct Field : public ClassElement -{ - string comment; - int modifiers; - Variable *variable; - string value; - - Field(); - Field(int modifiers, Variable* variable); - virtual ~Field(); - - virtual void GatherTypes(set<Type*>* types) const; - virtual void Write(FILE* to); -}; - -struct Statement -{ - virtual ~Statement(); - virtual void Write(FILE* to) = 0; -}; - -struct StatementBlock : public Statement -{ - vector<Statement*> statements; - - StatementBlock(); - virtual ~StatementBlock(); - virtual void Write(FILE* to); - - void Add(Statement* statement); - void Add(Expression* expression); -}; - -struct ExpressionStatement : public Statement -{ - Expression* expression; - - ExpressionStatement(Expression* expression); - virtual ~ExpressionStatement(); - virtual void Write(FILE* to); -}; - -struct Assignment : public Expression -{ - Variable* lvalue; - Expression* rvalue; - Type* cast; - - Assignment(Variable* lvalue, Expression* rvalue); - Assignment(Variable* lvalue, Expression* rvalue, Type* cast); - virtual ~Assignment(); - virtual void Write(FILE* to); -}; - -struct MethodCall : public Expression -{ - Expression* obj; - Type* clazz; - string name; - vector<Expression*> arguments; - vector<string> exceptions; - - MethodCall(const string& name); - MethodCall(const string& name, int argc, ...); - MethodCall(Expression* obj, const string& name); - MethodCall(Type* clazz, const string& name); - MethodCall(Expression* obj, const string& name, int argc, ...); - MethodCall(Type* clazz, const string& name, int argc, ...); - virtual ~MethodCall(); - virtual void Write(FILE* to); - -private: - void init(int n, va_list args); -}; - -struct Comparison : public Expression -{ - Expression* lvalue; - string op; - Expression* rvalue; - - Comparison(Expression* lvalue, const string& op, Expression* rvalue); - virtual ~Comparison(); - virtual void Write(FILE* to); -}; - -struct NewExpression : public Expression -{ - Type* type; - vector<Expression*> arguments; - - NewExpression(Type* type); - NewExpression(Type* type, int argc, ...); - virtual ~NewExpression(); - virtual void Write(FILE* to); - -private: - void init(int n, va_list args); -}; - -struct NewArrayExpression : public Expression -{ - Type* type; - Expression* size; - - NewArrayExpression(Type* type, Expression* size); - virtual ~NewArrayExpression(); - virtual void Write(FILE* to); -}; - -struct Ternary : public Expression -{ - Expression* condition; - Expression* ifpart; - Expression* elsepart; - - Ternary(); - Ternary(Expression* condition, Expression* ifpart, Expression* elsepart); - virtual ~Ternary(); - virtual void Write(FILE* to); -}; - -struct Cast : public Expression -{ - Type* type; - Expression* expression; - - Cast(); - Cast(Type* type, Expression* expression); - virtual ~Cast(); - virtual void Write(FILE* to); -}; - -struct VariableDeclaration : public Statement -{ - Variable* lvalue; - Type* cast; - Expression* rvalue; - - VariableDeclaration(Variable* lvalue); - VariableDeclaration(Variable* lvalue, Expression* rvalue, Type* cast = NULL); - virtual ~VariableDeclaration(); - virtual void Write(FILE* to); -}; - -struct IfStatement : public Statement -{ - Expression* expression; - StatementBlock* statements; - IfStatement* elseif; - - IfStatement(); - virtual ~IfStatement(); - virtual void Write(FILE* to); -}; - -struct ReturnStatement : public Statement -{ - Expression* expression; - - ReturnStatement(Expression* expression); - virtual ~ReturnStatement(); - virtual void Write(FILE* to); -}; - -struct TryStatement : public Statement -{ - StatementBlock* statements; - - TryStatement(); - virtual ~TryStatement(); - virtual void Write(FILE* to); -}; - -struct CatchStatement : public Statement -{ - StatementBlock* statements; - Variable* exception; - - CatchStatement(Variable* exception); - virtual ~CatchStatement(); - virtual void Write(FILE* to); -}; - -struct FinallyStatement : public Statement -{ - StatementBlock* statements; - - FinallyStatement(); - virtual ~FinallyStatement(); - virtual void Write(FILE* to); -}; - -struct Case -{ - vector<string> cases; - StatementBlock* statements; - - Case(); - Case(const string& c); - virtual ~Case(); - virtual void Write(FILE* to); -}; - -struct SwitchStatement : public Statement -{ - Expression* expression; - vector<Case*> cases; - - SwitchStatement(Expression* expression); - virtual ~SwitchStatement(); - virtual void Write(FILE* to); -}; - -struct Break : public Statement -{ - Break(); - virtual ~Break(); - virtual void Write(FILE* to); -}; - -struct Method : public ClassElement -{ - string comment; - int modifiers; - Type* returnType; - size_t returnTypeDimension; - string name; - vector<Variable*> parameters; - vector<Type*> exceptions; - StatementBlock* statements; - - Method(); - virtual ~Method(); - - virtual void GatherTypes(set<Type*>* types) const; - virtual void Write(FILE* to); -}; - -struct Class : public ClassElement -{ - enum { - CLASS, - INTERFACE - }; - - string comment; - int modifiers; - int what; // CLASS or INTERFACE - Type* type; - Type* extends; - vector<Type*> interfaces; - vector<ClassElement*> elements; - - Class(); - virtual ~Class(); - - virtual void GatherTypes(set<Type*>* types) const; - virtual void Write(FILE* to); -}; - -struct Document -{ - string comment; - string package; - string originalSrc; - set<Type*> imports; - vector<Class*> classes; - - Document(); - virtual ~Document(); - - virtual void Write(FILE* to); -}; - -#endif // AIDL_AST_H diff --git a/tools/aidl/Android.mk b/tools/aidl/Android.mk deleted file mode 100644 index 77d46ab..0000000 --- a/tools/aidl/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2007 The Android Open Source Project -# -# Copies files into the directory structure described by a manifest - -# 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 := \ - aidl_language_l.l \ - aidl_language_y.y \ - aidl.cpp \ - aidl_language.cpp \ - options.cpp \ - search_path.cpp \ - AST.cpp \ - Type.cpp \ - generate_java.cpp \ - generate_java_binder.cpp \ - generate_java_rpc.cpp - -LOCAL_CFLAGS := -g -LOCAL_MODULE := aidl - -include $(BUILD_HOST_EXECUTABLE) - -endif # TARGET_BUILD_APPS diff --git a/tools/aidl/NOTICE b/tools/aidl/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/tools/aidl/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp deleted file mode 100644 index d572af6..0000000 --- a/tools/aidl/Type.cpp +++ /dev/null @@ -1,1440 +0,0 @@ -#include "Type.h" - -Namespace NAMES; - -Type* VOID_TYPE; -Type* BOOLEAN_TYPE; -Type* BYTE_TYPE; -Type* CHAR_TYPE; -Type* INT_TYPE; -Type* LONG_TYPE; -Type* FLOAT_TYPE; -Type* DOUBLE_TYPE; -Type* STRING_TYPE; -Type* OBJECT_TYPE; -Type* CHAR_SEQUENCE_TYPE; -Type* TEXT_UTILS_TYPE; -Type* REMOTE_EXCEPTION_TYPE; -Type* RUNTIME_EXCEPTION_TYPE; -Type* IBINDER_TYPE; -Type* IINTERFACE_TYPE; -Type* BINDER_NATIVE_TYPE; -Type* BINDER_PROXY_TYPE; -Type* PARCEL_TYPE; -Type* PARCELABLE_INTERFACE_TYPE; -Type* CONTEXT_TYPE; -Type* MAP_TYPE; -Type* LIST_TYPE; -Type* CLASSLOADER_TYPE; -Type* RPC_DATA_TYPE; -Type* RPC_ERROR_TYPE; -Type* EVENT_FAKE_TYPE; - -Expression* NULL_VALUE; -Expression* THIS_VALUE; -Expression* SUPER_VALUE; -Expression* TRUE_VALUE; -Expression* FALSE_VALUE; - -void -register_base_types() -{ - VOID_TYPE = new BasicType("void", - "XXX", "XXX", "XXX", "XXX", "XXX", - "XXX", "XXX", "XXX", "XXX", "XXX"); - NAMES.Add(VOID_TYPE); - - BOOLEAN_TYPE = new BooleanType(); - NAMES.Add(BOOLEAN_TYPE); - - BYTE_TYPE = new BasicType("byte", - "writeByte", "readByte", "writeByteArray", "createByteArray", "readByteArray", - "putByte", "getByte", "putByteArray", "createByteArray", "getByteArray"); - NAMES.Add(BYTE_TYPE); - - CHAR_TYPE = new CharType(); - NAMES.Add(CHAR_TYPE); - - INT_TYPE = new BasicType("int", - "writeInt", "readInt", "writeIntArray", "createIntArray", "readIntArray", - "putInteger", "getInteger", "putIntegerArray", "createIntegerArray", "getIntegerArray"); - NAMES.Add(INT_TYPE); - - LONG_TYPE = new BasicType("long", - "writeLong", "readLong", "writeLongArray", "createLongArray", "readLongArray", - "putLong", "getLong", "putLongArray", "createLongArray", "getLongArray"); - NAMES.Add(LONG_TYPE); - - FLOAT_TYPE = new BasicType("float", - "writeFloat", "readFloat", "writeFloatArray", "createFloatArray", "readFloatArray", - "putFloat", "getFloat", "putFloatArray", "createFloatArray", "getFloatArray"); - NAMES.Add(FLOAT_TYPE); - - DOUBLE_TYPE = new BasicType("double", - "writeDouble", "readDouble", "writeDoubleArray", "createDoubleArray", "readDoubleArray", - "putDouble", "getDouble", "putDoubleArray", "createDoubleArray", "getDoubleArray"); - NAMES.Add(DOUBLE_TYPE); - - STRING_TYPE = new StringType(); - NAMES.Add(STRING_TYPE); - - OBJECT_TYPE = new Type("java.lang", "Object", Type::BUILT_IN, false, false, false); - NAMES.Add(OBJECT_TYPE); - - CHAR_SEQUENCE_TYPE = new CharSequenceType(); - NAMES.Add(CHAR_SEQUENCE_TYPE); - - MAP_TYPE = new MapType(); - NAMES.Add(MAP_TYPE); - - LIST_TYPE = new ListType(); - NAMES.Add(LIST_TYPE); - - TEXT_UTILS_TYPE = new Type("android.text", "TextUtils", Type::BUILT_IN, false, false, false); - NAMES.Add(TEXT_UTILS_TYPE); - - REMOTE_EXCEPTION_TYPE = new RemoteExceptionType(); - NAMES.Add(REMOTE_EXCEPTION_TYPE); - - RUNTIME_EXCEPTION_TYPE = new RuntimeExceptionType(); - NAMES.Add(RUNTIME_EXCEPTION_TYPE); - - IBINDER_TYPE = new IBinderType(); - NAMES.Add(IBINDER_TYPE); - - IINTERFACE_TYPE = new IInterfaceType(); - NAMES.Add(IINTERFACE_TYPE); - - BINDER_NATIVE_TYPE = new BinderType(); - NAMES.Add(BINDER_NATIVE_TYPE); - - BINDER_PROXY_TYPE = new BinderProxyType(); - NAMES.Add(BINDER_PROXY_TYPE); - - PARCEL_TYPE = new ParcelType(); - NAMES.Add(PARCEL_TYPE); - - PARCELABLE_INTERFACE_TYPE = new ParcelableInterfaceType(); - NAMES.Add(PARCELABLE_INTERFACE_TYPE); - - CONTEXT_TYPE = new Type("android.content", "Context", Type::BUILT_IN, false, false, false); - NAMES.Add(CONTEXT_TYPE); - - RPC_DATA_TYPE = new RpcDataType(); - NAMES.Add(RPC_DATA_TYPE); - - RPC_ERROR_TYPE = new UserDataType("android.support.place.rpc", "RpcError", - true, __FILE__, __LINE__); - NAMES.Add(RPC_ERROR_TYPE); - - EVENT_FAKE_TYPE = new Type("event", Type::BUILT_IN, false, false, false); - NAMES.Add(EVENT_FAKE_TYPE); - - CLASSLOADER_TYPE = new ClassLoaderType(); - NAMES.Add(CLASSLOADER_TYPE); - - NULL_VALUE = new LiteralExpression("null"); - THIS_VALUE = new LiteralExpression("this"); - SUPER_VALUE = new LiteralExpression("super"); - TRUE_VALUE = new LiteralExpression("true"); - FALSE_VALUE = new LiteralExpression("false"); - - NAMES.AddGenericType("java.util", "List", 1); - NAMES.AddGenericType("java.util", "Map", 2); -} - -static Type* -make_generic_type(const string& package, const string& name, - const vector<Type*>& args) -{ - if (package == "java.util" && name == "List") { - return new GenericListType("java.util", "List", args); - } - return NULL; - //return new GenericType(package, name, args); -} - -// ================================================================ - -Type::Type(const string& name, int kind, bool canWriteToParcel, bool canWriteToRpcData, - bool canBeOut) - :m_package(), - m_name(name), - m_declFile(""), - m_declLine(-1), - m_kind(kind), - m_canWriteToParcel(canWriteToParcel), - m_canWriteToRpcData(canWriteToRpcData), - m_canBeOut(canBeOut) -{ - m_qualifiedName = name; -} - -Type::Type(const string& package, const string& name, - int kind, bool canWriteToParcel, bool canWriteToRpcData, - bool canBeOut, const string& declFile, int declLine) - :m_package(package), - m_name(name), - m_declFile(declFile), - m_declLine(declLine), - m_kind(kind), - m_canWriteToParcel(canWriteToParcel), - m_canWriteToRpcData(canWriteToRpcData), - m_canBeOut(canBeOut) -{ - if (package.length() > 0) { - m_qualifiedName = package; - m_qualifiedName += '.'; - } - m_qualifiedName += name; -} - -Type::~Type() -{ -} - -bool -Type::CanBeArray() const -{ - return false; -} - -string -Type::ImportType() const -{ - return m_qualifiedName; -} - -string -Type::CreatorName() const -{ - return ""; -} - -string -Type::RpcCreatorName() const -{ - return ""; -} - -string -Type::InstantiableName() const -{ - return QualifiedName(); -} - - -void -Type::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%sn", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* WriteToParcel error " - + m_qualifiedName + " */")); -} - -void -Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* CreateFromParcel error " - + m_qualifiedName + " */")); -} - -void -Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* ReadFromParcel error " - + m_qualifiedName + " */")); -} - -void -Type::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* WriteArrayToParcel error " - + m_qualifiedName + " */")); -} - -void -Type::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* CreateArrayFromParcel error " - + m_qualifiedName + " */")); -} - -void -Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* ReadArrayFromParcel error " - + m_qualifiedName + " */")); -} - -void -Type::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* WriteToRpcData error " - + m_qualifiedName + " */")); -} - -void -Type::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data, - Variable** cl) -{ - fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", - __FILE__, __LINE__, m_qualifiedName.c_str()); - addTo->Add(new LiteralExpression("/* ReadFromRpcData error " - + m_qualifiedName + " */")); -} - -void -Type::SetQualifiedName(const string& qualified) -{ - m_qualifiedName = qualified; -} - -Expression* -Type::BuildWriteToParcelFlags(int flags) -{ - if (flags == 0) { - return new LiteralExpression("0"); - } - if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0) { - return new FieldVariable(PARCELABLE_INTERFACE_TYPE, - "PARCELABLE_WRITE_RETURN_VALUE"); - } - return new LiteralExpression("0"); -} - -// ================================================================ - -BasicType::BasicType(const string& name, const string& marshallParcel, - const string& unmarshallParcel, const string& writeArrayParcel, - const string& createArrayParcel, const string& readArrayParcel, - const string& marshallRpc, const string& unmarshallRpc, - const string& writeArrayRpc, const string& createArrayRpc, const string& readArrayRpc) - :Type(name, BUILT_IN, true, true, false), - m_marshallParcel(marshallParcel), - m_unmarshallParcel(unmarshallParcel), - m_writeArrayParcel(writeArrayParcel), - m_createArrayParcel(createArrayParcel), - m_readArrayParcel(readArrayParcel), - m_marshallRpc(marshallRpc), - m_unmarshallRpc(unmarshallRpc), - m_writeArrayRpc(writeArrayRpc), - m_createArrayRpc(createArrayRpc), - m_readArrayRpc(readArrayRpc) -{ -} - -void -BasicType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, m_marshallParcel, 1, v)); -} - -void -BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, m_unmarshallParcel))); -} - -bool -BasicType::CanBeArray() const -{ - return true; -} - -void -BasicType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, m_writeArrayParcel, 1, v)); -} - -void -BasicType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, m_createArrayParcel))); -} - -void -BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new MethodCall(parcel, m_readArrayParcel, 1, v)); -} - -void -BasicType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - addTo->Add(new MethodCall(data, m_marshallRpc, 2, k, v)); -} - -void -BasicType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data, - Variable** cl) -{ - addTo->Add(new Assignment(v, new MethodCall(data, m_unmarshallRpc, 1, k))); -} - -// ================================================================ - -BooleanType::BooleanType() - :Type("boolean", BUILT_IN, true, true, false) -{ -} - -void -BooleanType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeInt", 1, - new Ternary(v, new LiteralExpression("1"), - new LiteralExpression("0")))); -} - -void -BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new Comparison(new LiteralExpression("0"), - "!=", new MethodCall(parcel, "readInt")))); -} - -bool -BooleanType::CanBeArray() const -{ - return true; -} - -void -BooleanType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeBooleanArray", 1, v)); -} - -void -BooleanType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "createBooleanArray"))); -} - -void -BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new MethodCall(parcel, "readBooleanArray", 1, v)); -} - -void -BooleanType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - addTo->Add(new MethodCall(data, "putBoolean", 2, k, v)); -} - -void -BooleanType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data, - Variable** cl) -{ - addTo->Add(new Assignment(v, new MethodCall(data, "getBoolean", 1, k))); -} - -// ================================================================ - -CharType::CharType() - :Type("char", BUILT_IN, true, true, false) -{ -} - -void -CharType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeInt", 1, - new Cast(INT_TYPE, v))); -} - -void -CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "readInt"), this)); -} - -bool -CharType::CanBeArray() const -{ - return true; -} - -void -CharType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeCharArray", 1, v)); -} - -void -CharType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "createCharArray"))); -} - -void -CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new MethodCall(parcel, "readCharArray", 1, v)); -} - -void -CharType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - addTo->Add(new MethodCall(data, "putChar", 2, k, v)); -} - -void -CharType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data, - Variable** cl) -{ - addTo->Add(new Assignment(v, new MethodCall(data, "getChar", 1, k))); -} - -// ================================================================ - -StringType::StringType() - :Type("java.lang", "String", BUILT_IN, true, true, false) -{ -} - -string -StringType::CreatorName() const -{ - return "android.os.Parcel.STRING_CREATOR"; -} - -void -StringType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeString", 1, v)); -} - -void -StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "readString"))); -} - -bool -StringType::CanBeArray() const -{ - return true; -} - -void -StringType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeStringArray", 1, v)); -} - -void -StringType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "createStringArray"))); -} - -void -StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new MethodCall(parcel, "readStringArray", 1, v)); -} - -void -StringType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - addTo->Add(new MethodCall(data, "putString", 2, k, v)); -} - -void -StringType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(data, "getString", 1, k))); -} - -// ================================================================ - -CharSequenceType::CharSequenceType() - :Type("java.lang", "CharSequence", BUILT_IN, true, true, false) -{ -} - -string -CharSequenceType::CreatorName() const -{ - return "android.os.Parcel.STRING_CREATOR"; -} - -void -CharSequenceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - // if (v != null) { - // parcel.writeInt(1); - // v.writeToParcel(parcel); - // } else { - // parcel.writeInt(0); - // } - IfStatement* elsepart = new IfStatement(); - elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1, - new LiteralExpression("0"))); - IfStatement* ifpart = new IfStatement; - ifpart->expression = new Comparison(v, "!=", NULL_VALUE); - ifpart->elseif = elsepart; - ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1, - new LiteralExpression("1"))); - ifpart->statements->Add(new MethodCall(TEXT_UTILS_TYPE, "writeToParcel", - 3, v, parcel, BuildWriteToParcelFlags(flags))); - - addTo->Add(ifpart); -} - -void -CharSequenceType::CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - // if (0 != parcel.readInt()) { - // v = TextUtils.createFromParcel(parcel) - // } else { - // v = null; - // } - IfStatement* elsepart = new IfStatement(); - elsepart->statements->Add(new Assignment(v, NULL_VALUE)); - - IfStatement* ifpart = new IfStatement(); - ifpart->expression = new Comparison(new LiteralExpression("0"), "!=", - new MethodCall(parcel, "readInt")); - ifpart->elseif = elsepart; - ifpart->statements->Add(new Assignment(v, - new MethodCall(TEXT_UTILS_TYPE, - "CHAR_SEQUENCE_CREATOR.createFromParcel", 1, parcel))); - - addTo->Add(ifpart); -} - - -// ================================================================ - -RemoteExceptionType::RemoteExceptionType() - :Type("android.os", "RemoteException", BUILT_IN, false, false, false) -{ -} - -void -RemoteExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -// ================================================================ - -RuntimeExceptionType::RuntimeExceptionType() - :Type("java.lang", "RuntimeException", BUILT_IN, false, false, false) -{ -} - -void -RuntimeExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - - -// ================================================================ - -IBinderType::IBinderType() - :Type("android.os", "IBinder", BUILT_IN, true, false, false) -{ -} - -void -IBinderType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1, v)); -} - -void -IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "readStrongBinder"))); -} - -void -IBinderType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeBinderArray", 1, v)); -} - -void -IBinderType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - addTo->Add(new Assignment(v, new MethodCall(parcel, "createBinderArray"))); -} - -void -IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - addTo->Add(new MethodCall(parcel, "readBinderArray", 1, v)); -} - - -// ================================================================ - -IInterfaceType::IInterfaceType() - :Type("android.os", "IInterface", BUILT_IN, false, false, false) -{ -} - -void -IInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - - -// ================================================================ - -BinderType::BinderType() - :Type("android.os", "Binder", BUILT_IN, false, false, false) -{ -} - -void -BinderType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -BinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - - -// ================================================================ - -BinderProxyType::BinderProxyType() - :Type("android.os", "BinderProxy", BUILT_IN, false, false, false) -{ -} - -void -BinderProxyType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -BinderProxyType::CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - - -// ================================================================ - -ParcelType::ParcelType() - :Type("android.os", "Parcel", BUILT_IN, false, false, false) -{ -} - -void -ParcelType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -// ================================================================ - -ParcelableInterfaceType::ParcelableInterfaceType() - :Type("android.os", "Parcelable", BUILT_IN, false, false, false) -{ -} - -void -ParcelableInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -void -ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); -} - -// ================================================================ - -MapType::MapType() - :Type("java.util", "Map", BUILT_IN, true, false, true) -{ -} - -void -MapType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeMap", 1, v)); -} - -static void EnsureClassLoader(StatementBlock* addTo, Variable** cl) -{ - // We don't want to look up the class loader once for every - // collection argument, so ensure we do it at most once per method. - if (*cl == NULL) { - *cl = new Variable(CLASSLOADER_TYPE, "cl"); - addTo->Add(new VariableDeclaration(*cl, - new LiteralExpression("this.getClass().getClassLoader()"), - CLASSLOADER_TYPE)); - } -} - -void -MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl) -{ - EnsureClassLoader(addTo, cl); - addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, *cl))); -} - -void -MapType::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl) -{ - EnsureClassLoader(addTo, cl); - addTo->Add(new MethodCall(parcel, "readMap", 2, v, *cl)); -} - - -// ================================================================ - -ListType::ListType() - :Type("java.util", "List", BUILT_IN, true, true, true) -{ -} - -string -ListType::InstantiableName() const -{ - return "java.util.ArrayList"; -} - -void -ListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeList", 1, v)); -} - -void -ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl) -{ - EnsureClassLoader(addTo, cl); - addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, *cl))); -} - -void -ListType::ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl) -{ - EnsureClassLoader(addTo, cl); - addTo->Add(new MethodCall(parcel, "readList", 2, v, *cl)); -} - -void -ListType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - addTo->Add(new MethodCall(data, "putList", 2, k, v)); -} - -void -ListType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data, - Variable** cl) -{ - addTo->Add(new Assignment(v, new MethodCall(data, "getList", 1, k))); -} - -// ================================================================ - -UserDataType::UserDataType(const string& package, const string& name, - bool builtIn, bool canWriteToParcel, bool canWriteToRpcData, - const string& declFile, int declLine) - :Type(package, name, builtIn ? BUILT_IN : USERDATA, canWriteToParcel, canWriteToRpcData, - true, declFile, declLine) -{ -} - -string -UserDataType::CreatorName() const -{ - return QualifiedName() + ".CREATOR"; -} - -string -UserDataType::RpcCreatorName() const -{ - return QualifiedName() + ".RPC_CREATOR"; -} - -void -UserDataType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - // if (v != null) { - // parcel.writeInt(1); - // v.writeToParcel(parcel); - // } else { - // parcel.writeInt(0); - // } - IfStatement* elsepart = new IfStatement(); - elsepart->statements->Add(new MethodCall(parcel, "writeInt", 1, - new LiteralExpression("0"))); - IfStatement* ifpart = new IfStatement; - ifpart->expression = new Comparison(v, "!=", NULL_VALUE); - ifpart->elseif = elsepart; - ifpart->statements->Add(new MethodCall(parcel, "writeInt", 1, - new LiteralExpression("1"))); - ifpart->statements->Add(new MethodCall(v, "writeToParcel", 2, - parcel, BuildWriteToParcelFlags(flags))); - - addTo->Add(ifpart); -} - -void -UserDataType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - // if (0 != parcel.readInt()) { - // v = CLASS.CREATOR.createFromParcel(parcel) - // } else { - // v = null; - // } - IfStatement* elsepart = new IfStatement(); - elsepart->statements->Add(new Assignment(v, NULL_VALUE)); - - IfStatement* ifpart = new IfStatement(); - ifpart->expression = new Comparison(new LiteralExpression("0"), "!=", - new MethodCall(parcel, "readInt")); - ifpart->elseif = elsepart; - ifpart->statements->Add(new Assignment(v, - new MethodCall(v->type, "CREATOR.createFromParcel", 1, parcel))); - - addTo->Add(ifpart); -} - -void -UserDataType::ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - // TODO: really, we don't need to have this extra check, but we - // don't have two separate marshalling code paths - // if (0 != parcel.readInt()) { - // v.readFromParcel(parcel) - // } - IfStatement* ifpart = new IfStatement(); - ifpart->expression = new Comparison(new LiteralExpression("0"), "!=", - new MethodCall(parcel, "readInt")); - ifpart->statements->Add(new MethodCall(v, "readFromParcel", 1, parcel)); - addTo->Add(ifpart); -} - -bool -UserDataType::CanBeArray() const -{ - return true; -} - -void -UserDataType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - addTo->Add(new MethodCall(parcel, "writeTypedArray", 2, v, - BuildWriteToParcelFlags(flags))); -} - -void -UserDataType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - string creator = v->type->QualifiedName() + ".CREATOR"; - addTo->Add(new Assignment(v, new MethodCall(parcel, - "createTypedArray", 1, new LiteralExpression(creator)))); -} - -void -UserDataType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - string creator = v->type->QualifiedName() + ".CREATOR"; - addTo->Add(new MethodCall(parcel, "readTypedArray", 2, - v, new LiteralExpression(creator))); -} - -void -UserDataType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - // data.putFlattenable(k, v); - addTo->Add(new MethodCall(data, "putFlattenable", 2, k, v)); -} - -void -UserDataType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl) -{ - // data.getFlattenable(k, CLASS.RPC_CREATOR); - addTo->Add(new Assignment(v, new MethodCall(data, "getFlattenable", 2, k, - new FieldVariable(v->type, "RPC_CREATOR")))); -} - -// ================================================================ - -InterfaceType::InterfaceType(const string& package, const string& name, - bool builtIn, bool oneway, - const string& declFile, int declLine) - :Type(package, name, builtIn ? BUILT_IN : INTERFACE, true, false, false, - declFile, declLine) - ,m_oneway(oneway) -{ -} - -bool -InterfaceType::OneWay() const -{ - return m_oneway; -} - -void -InterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - // parcel.writeStrongBinder(v != null ? v.asBinder() : null); - addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1, - new Ternary( - new Comparison(v, "!=", NULL_VALUE), - new MethodCall(v, "asBinder"), - NULL_VALUE))); -} - -void -InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - // v = Interface.asInterface(parcel.readStrongBinder()); - string type = v->type->QualifiedName(); - type += ".Stub"; - addTo->Add(new Assignment(v, - new MethodCall( NAMES.Find(type), "asInterface", 1, - new MethodCall(parcel, "readStrongBinder")))); -} - - -// ================================================================ - -GenericType::GenericType(const string& package, const string& name, - const vector<Type*>& args) - :Type(package, name, BUILT_IN, true, true, true) -{ - m_args = args; - - m_importName = package + '.' + name; - - string gen = "<"; - int N = args.size(); - for (int i=0; i<N; i++) { - Type* t = args[i]; - gen += t->QualifiedName(); - if (i != N-1) { - gen += ','; - } - } - gen += '>'; - m_genericArguments = gen; - SetQualifiedName(m_importName + gen); -} - -const vector<Type*>& -GenericType::GenericArgumentTypes() const -{ - return m_args; -} - -string -GenericType::GenericArguments() const -{ - return m_genericArguments; -} - -string -GenericType::ImportType() const -{ - return m_importName; -} - -void -GenericType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - fprintf(stderr, "implement GenericType::WriteToParcel\n"); -} - -void -GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - fprintf(stderr, "implement GenericType::CreateFromParcel\n"); -} - -void -GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - fprintf(stderr, "implement GenericType::ReadFromParcel\n"); -} - - -// ================================================================ - -GenericListType::GenericListType(const string& package, const string& name, - const vector<Type*>& args) - :GenericType(package, name, args), - m_creator(args[0]->CreatorName()) -{ -} - -string -GenericListType::CreatorName() const -{ - return "android.os.Parcel.arrayListCreator"; -} - -string -GenericListType::InstantiableName() const -{ - return "java.util.ArrayList" + GenericArguments(); -} - -void -GenericListType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags) -{ - if (m_creator == STRING_TYPE->CreatorName()) { - addTo->Add(new MethodCall(parcel, "writeStringList", 1, v)); - } else if (m_creator == IBINDER_TYPE->CreatorName()) { - addTo->Add(new MethodCall(parcel, "writeBinderList", 1, v)); - } else { - // parcel.writeTypedListXX(arg); - addTo->Add(new MethodCall(parcel, "writeTypedList", 1, v)); - } -} - -void -GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**) -{ - if (m_creator == STRING_TYPE->CreatorName()) { - addTo->Add(new Assignment(v, - new MethodCall(parcel, "createStringArrayList", 0))); - } else if (m_creator == IBINDER_TYPE->CreatorName()) { - addTo->Add(new Assignment(v, - new MethodCall(parcel, "createBinderArrayList", 0))); - } else { - // v = _data.readTypedArrayList(XXX.creator); - addTo->Add(new Assignment(v, - new MethodCall(parcel, "createTypedArrayList", 1, - new LiteralExpression(m_creator)))); - } -} - -void -GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable**) -{ - if (m_creator == STRING_TYPE->CreatorName()) { - addTo->Add(new MethodCall(parcel, "readStringList", 1, v)); - } else if (m_creator == IBINDER_TYPE->CreatorName()) { - addTo->Add(new MethodCall(parcel, "readBinderList", 1, v)); - } else { - // v = _data.readTypedList(v, XXX.creator); - addTo->Add(new MethodCall(parcel, "readTypedList", 2, - v, - new LiteralExpression(m_creator))); - } -} - -void -GenericListType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - Type* generic = GenericArgumentTypes()[0]; - if (generic == RPC_DATA_TYPE) { - addTo->Add(new MethodCall(data, "putRpcDataList", 2, k, v)); - } else if (generic->RpcCreatorName() != "") { - addTo->Add(new MethodCall(data, "putFlattenableList", 2, k, v)); - } else { - addTo->Add(new MethodCall(data, "putList", 2, k, v)); - } -} - -void -GenericListType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl) -{ - Type* generic = GenericArgumentTypes()[0]; - if (generic == RPC_DATA_TYPE) { - addTo->Add(new Assignment(v, new MethodCall(data, "getRpcDataList", 2, k))); - } else if (generic->RpcCreatorName() != "") { - addTo->Add(new Assignment(v, new MethodCall(data, "getFlattenableList", 2, k, - new LiteralExpression(generic->RpcCreatorName())))); - } else { - string classArg = GenericArgumentTypes()[0]->QualifiedName(); - classArg += ".class"; - addTo->Add(new Assignment(v, new MethodCall(data, "getList", 2, k, - new LiteralExpression(classArg)))); - } -} - - -// ================================================================ - -RpcDataType::RpcDataType() - :UserDataType("android.support.place.rpc", "RpcData", true, true, true) -{ -} - -void -RpcDataType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags) -{ - addTo->Add(new MethodCall(data, "putRpcData", 2, k, v)); -} - -void -RpcDataType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, Variable* data, - Variable** cl) -{ - addTo->Add(new Assignment(v, new MethodCall(data, "getRpcData", 1, k))); -} - - -// ================================================================ - -ClassLoaderType::ClassLoaderType() - :Type("java.lang", "ClassLoader", BUILT_IN, false, false, false) -{ -} - - -// ================================================================ - -Namespace::Namespace() -{ -} - -Namespace::~Namespace() -{ - int N = m_types.size(); - for (int i=0; i<N; i++) { - delete m_types[i]; - } -} - -void -Namespace::Add(Type* type) -{ - Type* t = Find(type->QualifiedName()); - if (t == NULL) { - m_types.push_back(type); - } -} - -void -Namespace::AddGenericType(const string& package, const string& name, int args) -{ - Generic g; - g.package = package; - g.name = name; - g.qualified = package + '.' + name; - g.args = args; - m_generics.push_back(g); -} - -Type* -Namespace::Find(const string& name) const -{ - int N = m_types.size(); - for (int i=0; i<N; i++) { - if (m_types[i]->QualifiedName() == name) { - return m_types[i]; - } - } - return NULL; -} - -Type* -Namespace::Find(const char* package, const char* name) const -{ - string s; - if (package != NULL) { - s += package; - s += '.'; - } - s += name; - return Find(s); -} - -static string -normalize_generic(const string& s) -{ - string r; - int N = s.size(); - for (int i=0; i<N; i++) { - char c = s[i]; - if (!isspace(c)) { - r += c; - } - } - return r; -} - -Type* -Namespace::Search(const string& name) -{ - // an exact match wins - Type* result = Find(name); - if (result != NULL) { - return result; - } - - // try the class names - // our language doesn't allow you to not specify outer classes - // when referencing an inner class. that could be changed, and this - // would be the place to do it, but I don't think the complexity in - // scoping rules is worth it. - int N = m_types.size(); - for (int i=0; i<N; i++) { - if (m_types[i]->Name() == name) { - return m_types[i]; - } - } - - // we got to here and it's not a generic, give up - if (name.find('<') == name.npos) { - return NULL; - } - - // remove any whitespace - string normalized = normalize_generic(name); - - // find the part before the '<', find a generic for it - ssize_t baseIndex = normalized.find('<'); - string base(normalized.c_str(), baseIndex); - const Generic* g = search_generic(base); - if (g == NULL) { - return NULL; - } - - // For each of the args, do a recursive search on it. We don't allow - // generics within generics like Java does, because we're really limiting - // them to just built-in container classes, at least for now. Our syntax - // ensures this right now as well. - vector<Type*> args; - size_t start = baseIndex + 1; - size_t end = start; - while (normalized[start] != '\0') { - end = normalized.find(',', start); - if (end == normalized.npos) { - end = normalized.find('>', start); - } - string s(normalized.c_str()+start, end-start); - Type* t = this->Search(s); - if (t == NULL) { - // maybe we should print a warning here? - return NULL; - } - args.push_back(t); - start = end+1; - } - - // construct a GenericType, add it to our name set so they always get - // the same object, and return it. - result = make_generic_type(g->package, g->name, args); - if (result == NULL) { - return NULL; - } - - this->Add(result); - return this->Find(result->QualifiedName()); -} - -const Namespace::Generic* -Namespace::search_generic(const string& name) const -{ - int N = m_generics.size(); - - // first exact match - for (int i=0; i<N; i++) { - const Generic& g = m_generics[i]; - if (g.qualified == name) { - return &g; - } - } - - // then name match - for (int i=0; i<N; i++) { - const Generic& g = m_generics[i]; - if (g.name == name) { - return &g; - } - } - - return NULL; -} - -void -Namespace::Dump() const -{ - int n = m_types.size(); - for (int i=0; i<n; i++) { - Type* t = m_types[i]; - printf("type: package=%s name=%s qualifiedName=%s\n", - t->Package().c_str(), t->Name().c_str(), - t->QualifiedName().c_str()); - } -} diff --git a/tools/aidl/Type.h b/tools/aidl/Type.h deleted file mode 100644 index ae12720..0000000 --- a/tools/aidl/Type.h +++ /dev/null @@ -1,542 +0,0 @@ -#ifndef AIDL_TYPE_H -#define AIDL_TYPE_H - -#include "AST.h" -#include <string> -#include <vector> - -using namespace std; - -class Type -{ -public: - // kinds - enum { - BUILT_IN, - USERDATA, - INTERFACE, - GENERATED - }; - - // WriteToParcel flags - enum { - PARCELABLE_WRITE_RETURN_VALUE = 0x0001 - }; - - Type(const string& name, int kind, bool canWriteToParcel, - bool canWriteToRpcData, bool canBeOut); - Type(const string& package, const string& name, - int kind, bool canWriteToParcel, bool canWriteToRpcData, bool canBeOut, - const string& declFile = "", int declLine = -1); - virtual ~Type(); - - inline string Package() const { return m_package; } - inline string Name() const { return m_name; } - inline string QualifiedName() const { return m_qualifiedName; } - inline int Kind() const { return m_kind; } - inline string DeclFile() const { return m_declFile; } - inline int DeclLine() const { return m_declLine; } - inline bool CanWriteToParcel() const { return m_canWriteToParcel; } - inline bool CanWriteToRpcData() const { return m_canWriteToRpcData; } - inline bool CanBeOutParameter() const { return m_canBeOut; } - - virtual string ImportType() const; - virtual string CreatorName() const; - virtual string RpcCreatorName() const; - virtual string InstantiableName() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual bool CanBeArray() const; - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); - -protected: - void SetQualifiedName(const string& qualified); - Expression* BuildWriteToParcelFlags(int flags); - -private: - Type(); - Type(const Type&); - - string m_package; - string m_name; - string m_qualifiedName; - string m_declFile; - int m_declLine; - int m_kind; - bool m_canWriteToParcel; - bool m_canWriteToRpcData; - bool m_canBeOut; -}; - -class BasicType : public Type -{ -public: - BasicType(const string& name, - const string& marshallParcel, - const string& unmarshallParcel, - const string& writeArrayParcel, - const string& createArrayParcel, - const string& readArrayParcel, - const string& marshallRpc, - const string& unmarshallRpc, - const string& writeArrayRpc, - const string& createArrayRpc, - const string& readArrayRpc); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual bool CanBeArray() const; - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); - -private: - string m_marshallParcel; - string m_unmarshallParcel; - string m_writeArrayParcel; - string m_createArrayParcel; - string m_readArrayParcel; - string m_marshallRpc; - string m_unmarshallRpc; - string m_writeArrayRpc; - string m_createArrayRpc; - string m_readArrayRpc; -}; - -class BooleanType : public Type -{ -public: - BooleanType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual bool CanBeArray() const; - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); -}; - -class CharType : public Type -{ -public: - CharType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual bool CanBeArray() const; - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); -}; - - -class StringType : public Type -{ -public: - StringType(); - - virtual string CreatorName() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual bool CanBeArray() const; - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); -}; - -class CharSequenceType : public Type -{ -public: - CharSequenceType(); - - virtual string CreatorName() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class RemoteExceptionType : public Type -{ -public: - RemoteExceptionType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class RuntimeExceptionType : public Type -{ -public: - RuntimeExceptionType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class IBinderType : public Type -{ -public: - IBinderType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class IInterfaceType : public Type -{ -public: - IInterfaceType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class BinderType : public Type -{ -public: - BinderType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class BinderProxyType : public Type -{ -public: - BinderProxyType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class ParcelType : public Type -{ -public: - ParcelType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class ParcelableInterfaceType : public Type -{ -public: - ParcelableInterfaceType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class MapType : public Type -{ -public: - MapType(); - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); -}; - -class ListType : public Type -{ -public: - ListType(); - - virtual string InstantiableName() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); -}; - -class UserDataType : public Type -{ -public: - UserDataType(const string& package, const string& name, - bool builtIn, bool canWriteToParcel, bool canWriteToRpcData, - const string& declFile = "", int declLine = -1); - - virtual string CreatorName() const; - virtual string RpcCreatorName() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual bool CanBeArray() const; - - virtual void WriteArrayToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadArrayFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); -}; - -class InterfaceType : public Type -{ -public: - InterfaceType(const string& package, const string& name, - bool builtIn, bool oneway, - const string& declFile, int declLine); - - bool OneWay() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - -private: - bool m_oneway; -}; - - -class GenericType : public Type -{ -public: - GenericType(const string& package, const string& name, - const vector<Type*>& args); - - const vector<Type*>& GenericArgumentTypes() const; - string GenericArguments() const; - - virtual string ImportType() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - -private: - string m_genericArguments; - string m_importName; - vector<Type*> m_args; -}; - -class RpcDataType : public UserDataType -{ -public: - RpcDataType(); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); -}; - -class ClassLoaderType : public Type -{ -public: - ClassLoaderType(); -}; - -class GenericListType : public GenericType -{ -public: - GenericListType(const string& package, const string& name, - const vector<Type*>& args); - - virtual string CreatorName() const; - virtual string InstantiableName() const; - - virtual void WriteToParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, int flags); - virtual void CreateFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - virtual void ReadFromParcel(StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl); - - virtual void WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, int flags); - virtual void CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v, - Variable* data, Variable** cl); - -private: - string m_creator; -}; - -class Namespace -{ -public: - Namespace(); - ~Namespace(); - void Add(Type* type); - - // args is the number of template types (what is this called?) - void AddGenericType(const string& package, const string& name, int args); - - // lookup a specific class name - Type* Find(const string& name) const; - Type* Find(const char* package, const char* name) const; - - // try to search by either a full name or a partial name - Type* Search(const string& name); - - void Dump() const; - -private: - struct Generic { - string package; - string name; - string qualified; - int args; - }; - - const Generic* search_generic(const string& name) const; - - vector<Type*> m_types; - vector<Generic> m_generics; -}; - -extern Namespace NAMES; - -extern Type* VOID_TYPE; -extern Type* BOOLEAN_TYPE; -extern Type* BYTE_TYPE; -extern Type* CHAR_TYPE; -extern Type* INT_TYPE; -extern Type* LONG_TYPE; -extern Type* FLOAT_TYPE; -extern Type* DOUBLE_TYPE; -extern Type* OBJECT_TYPE; -extern Type* STRING_TYPE; -extern Type* CHAR_SEQUENCE_TYPE; -extern Type* TEXT_UTILS_TYPE; -extern Type* REMOTE_EXCEPTION_TYPE; -extern Type* RUNTIME_EXCEPTION_TYPE; -extern Type* IBINDER_TYPE; -extern Type* IINTERFACE_TYPE; -extern Type* BINDER_NATIVE_TYPE; -extern Type* BINDER_PROXY_TYPE; -extern Type* PARCEL_TYPE; -extern Type* PARCELABLE_INTERFACE_TYPE; - -extern Type* CONTEXT_TYPE; - -extern Type* RPC_DATA_TYPE; -extern Type* RPC_ERROR_TYPE; -extern Type* RPC_CONTEXT_TYPE; -extern Type* EVENT_FAKE_TYPE; - -extern Expression* NULL_VALUE; -extern Expression* THIS_VALUE; -extern Expression* SUPER_VALUE; -extern Expression* TRUE_VALUE; -extern Expression* FALSE_VALUE; - -void register_base_types(); - -#endif // AIDL_TYPE_H diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp deleted file mode 100644 index b8a4803..0000000 --- a/tools/aidl/aidl.cpp +++ /dev/null @@ -1,1155 +0,0 @@ - -#include "aidl_language.h" -#include "options.h" -#include "search_path.h" -#include "Type.h" -#include "generate_java.h" -#include <unistd.h> -#include <fcntl.h> -#include <sys/param.h> -#include <sys/stat.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <map> - -#ifdef HAVE_MS_C_RUNTIME -#include <io.h> -#include <sys/stat.h> -#endif - -#ifndef O_BINARY -# define O_BINARY 0 -#endif - -// The following are gotten as the offset from the allowable id's between -// android.os.IBinder.FIRST_CALL_TRANSACTION=1 and -// android.os.IBinder.LAST_CALL_TRANSACTION=16777215 -#define MIN_USER_SET_METHOD_ID 0 -#define MAX_USER_SET_METHOD_ID 16777214 - -using namespace std; - -static void -test_document(document_item_type* d) -{ - while (d) { - if (d->item_type == INTERFACE_TYPE_BINDER) { - interface_type* c = (interface_type*)d; - printf("interface %s %s {\n", c->package, c->name.data); - interface_item_type *q = (interface_item_type*)c->interface_items; - while (q) { - if (q->item_type == METHOD_TYPE) { - method_type *m = (method_type*)q; - printf(" %s %s(", m->type.type.data, m->name.data); - arg_type *p = m->args; - while (p) { - printf("%s %s",p->type.type.data,p->name.data); - if (p->next) printf(", "); - p=p->next; - } - printf(")"); - printf(";\n"); - } - q=q->next; - } - printf("}\n"); - } - else if (d->item_type == USER_DATA_TYPE) { - user_data_type* b = (user_data_type*)d; - if ((b->flattening_methods & PARCELABLE_DATA) != 0) { - printf("parcelable %s %s;\n", b->package, b->name.data); - } - if ((b->flattening_methods & RPC_DATA) != 0) { - printf("flattenable %s %s;\n", b->package, b->name.data); - } - } - else { - printf("UNKNOWN d=0x%08lx d->item_type=%d\n", (long)d, d->item_type); - } - d = d->next; - } -} - -// ========================================================== -int -convert_direction(const char* direction) -{ - if (direction == NULL) { - return IN_PARAMETER; - } - if (0 == strcmp(direction, "in")) { - return IN_PARAMETER; - } - if (0 == strcmp(direction, "out")) { - return OUT_PARAMETER; - } - return INOUT_PARAMETER; -} - -// ========================================================== -struct import_info { - const char* from; - const char* filename; - buffer_type statement; - const char* neededClass; - document_item_type* doc; - struct import_info* next; -}; - -document_item_type* g_document = NULL; -import_info* g_imports = NULL; - -static void -main_document_parsed(document_item_type* d) -{ - g_document = d; -} - -static void -main_import_parsed(buffer_type* statement) -{ - import_info* import = (import_info*)malloc(sizeof(import_info)); - memset(import, 0, sizeof(import_info)); - import->from = strdup(g_currentFilename); - import->statement.lineno = statement->lineno; - import->statement.data = strdup(statement->data); - import->statement.extra = NULL; - import->next = g_imports; - import->neededClass = parse_import_statement(statement->data); - g_imports = import; -} - -static ParserCallbacks g_mainCallbacks = { - &main_document_parsed, - &main_import_parsed -}; - -char* -parse_import_statement(const char* text) -{ - const char* end; - int len; - - while (isspace(*text)) { - text++; - } - while (!isspace(*text)) { - text++; - } - while (isspace(*text)) { - text++; - } - end = text; - while (!isspace(*end) && *end != ';') { - end++; - } - len = end-text; - - char* rv = (char*)malloc(len+1); - memcpy(rv, text, len); - rv[len] = '\0'; - - return rv; -} - -// ========================================================== -static void -import_import_parsed(buffer_type* statement) -{ -} - -static ParserCallbacks g_importCallbacks = { - &main_document_parsed, - &import_import_parsed -}; - -// ========================================================== -static int -check_filename(const char* filename, const char* package, buffer_type* name) -{ - const char* p; - string expected; - string fn; - size_t len; - char cwd[MAXPATHLEN]; - bool valid = false; - -#ifdef HAVE_WINDOWS_PATHS - if (isalpha(filename[0]) && filename[1] == ':' - && filename[2] == OS_PATH_SEPARATOR) { -#else - if (filename[0] == OS_PATH_SEPARATOR) { -#endif - fn = filename; - } else { - fn = getcwd(cwd, sizeof(cwd)); - len = fn.length(); - if (fn[len-1] != OS_PATH_SEPARATOR) { - fn += OS_PATH_SEPARATOR; - } - fn += filename; - } - - if (package) { - expected = package; - expected += '.'; - } - - len = expected.length(); - for (size_t i=0; i<len; i++) { - if (expected[i] == '.') { - expected[i] = OS_PATH_SEPARATOR; - } - } - - p = strchr(name->data, '.'); - len = p ? p-name->data : strlen(name->data); - expected.append(name->data, len); - - expected += ".aidl"; - - len = fn.length(); - valid = (len >= expected.length()); - - if (valid) { - p = fn.c_str() + (len - expected.length()); - -#ifdef HAVE_WINDOWS_PATHS - if (OS_PATH_SEPARATOR != '/') { - // Input filename under cygwin most likely has / separators - // whereas the expected string uses \\ separators. Adjust - // them accordingly. - for (char *c = const_cast<char *>(p); *c; ++c) { - if (*c == '/') *c = OS_PATH_SEPARATOR; - } - } -#endif - -#ifdef OS_CASE_SENSITIVE - valid = (expected == p); -#else - valid = !strcasecmp(expected.c_str(), p); -#endif - } - - if (!valid) { - fprintf(stderr, "%s:%d interface %s should be declared in a file" - " called %s.\n", - filename, name->lineno, name->data, expected.c_str()); - return 1; - } - - return 0; -} - -static int -check_filenames(const char* filename, document_item_type* items) -{ - int err = 0; - while (items) { - if (items->item_type == USER_DATA_TYPE) { - user_data_type* p = (user_data_type*)items; - err |= check_filename(filename, p->package, &p->name); - } - else if (items->item_type == INTERFACE_TYPE_BINDER - || items->item_type == INTERFACE_TYPE_RPC) { - interface_type* c = (interface_type*)items; - err |= check_filename(filename, c->package, &c->name); - } - else { - fprintf(stderr, "aidl: internal error unkown document type %d.\n", - items->item_type); - return 1; - } - items = items->next; - } - return err; -} - -// ========================================================== -static const char* -kind_to_string(int kind) -{ - switch (kind) - { - case Type::INTERFACE: - return "an interface"; - case Type::USERDATA: - return "a user data"; - default: - return "ERROR"; - } -} - -static char* -rfind(char* str, char c) -{ - char* p = str + strlen(str) - 1; - while (p >= str) { - if (*p == c) { - return p; - } - p--; - } - return NULL; -} - -static int -gather_types(const char* filename, document_item_type* items) -{ - int err = 0; - while (items) { - Type* type; - if (items->item_type == USER_DATA_TYPE) { - user_data_type* p = (user_data_type*)items; - type = new UserDataType(p->package ? p->package : "", p->name.data, - false, ((p->flattening_methods & PARCELABLE_DATA) != 0), - ((p->flattening_methods & RPC_DATA) != 0), filename, p->name.lineno); - } - else if (items->item_type == INTERFACE_TYPE_BINDER - || items->item_type == INTERFACE_TYPE_RPC) { - interface_type* c = (interface_type*)items; - type = new InterfaceType(c->package ? c->package : "", - c->name.data, false, c->oneway, - filename, c->name.lineno); - } - else { - fprintf(stderr, "aidl: internal error %s:%d\n", __FILE__, __LINE__); - return 1; - } - - Type* old = NAMES.Find(type->QualifiedName()); - if (old == NULL) { - NAMES.Add(type); - - if (items->item_type == INTERFACE_TYPE_BINDER) { - // for interfaces, also add the stub and proxy types, we don't - // bother checking these for duplicates, because the parser - // won't let us do it. - interface_type* c = (interface_type*)items; - - string name = c->name.data; - name += ".Stub"; - Type* stub = new Type(c->package ? c->package : "", - name, Type::GENERATED, false, false, false, - filename, c->name.lineno); - NAMES.Add(stub); - - name = c->name.data; - name += ".Stub.Proxy"; - Type* proxy = new Type(c->package ? c->package : "", - name, Type::GENERATED, false, false, false, - filename, c->name.lineno); - NAMES.Add(proxy); - } - else if (items->item_type == INTERFACE_TYPE_RPC) { - // for interfaces, also add the service base type, we don't - // bother checking these for duplicates, because the parser - // won't let us do it. - interface_type* c = (interface_type*)items; - - string name = c->name.data; - name += ".ServiceBase"; - Type* base = new Type(c->package ? c->package : "", - name, Type::GENERATED, false, false, false, - filename, c->name.lineno); - NAMES.Add(base); - } - } else { - if (old->Kind() == Type::BUILT_IN) { - fprintf(stderr, "%s:%d attempt to redefine built in class %s\n", - filename, type->DeclLine(), - type->QualifiedName().c_str()); - err = 1; - } - else if (type->Kind() != old->Kind()) { - const char* oldKind = kind_to_string(old->Kind()); - const char* newKind = kind_to_string(type->Kind()); - - fprintf(stderr, "%s:%d attempt to redefine %s as %s,\n", - filename, type->DeclLine(), - type->QualifiedName().c_str(), newKind); - fprintf(stderr, "%s:%d previously defined here as %s.\n", - old->DeclFile().c_str(), old->DeclLine(), oldKind); - err = 1; - } - } - - items = items->next; - } - return err; -} - -// ========================================================== -static bool -matches_keyword(const char* str) -{ - static const char* KEYWORDS[] = { "abstract", "assert", "boolean", "break", - "byte", "case", "catch", "char", "class", "const", "continue", - "default", "do", "double", "else", "enum", "extends", "final", - "finally", "float", "for", "goto", "if", "implements", "import", - "instanceof", "int", "interface", "long", "native", "new", "package", - "private", "protected", "public", "return", "short", "static", - "strictfp", "super", "switch", "synchronized", "this", "throw", - "throws", "transient", "try", "void", "volatile", "while", - "true", "false", "null", - NULL - }; - const char** k = KEYWORDS; - while (*k) { - if (0 == strcmp(str, *k)) { - return true; - } - k++; - } - return false; -} - -static int -check_method(const char* filename, int kind, method_type* m) -{ - int err = 0; - - // return type - Type* returnType = NAMES.Search(m->type.type.data); - if (returnType == NULL) { - fprintf(stderr, "%s:%d unknown return type %s\n", filename, - m->type.type.lineno, m->type.type.data); - err = 1; - return err; - } - - if (returnType == EVENT_FAKE_TYPE) { - if (kind != INTERFACE_TYPE_RPC) { - fprintf(stderr, "%s:%d event methods only supported for rpc interfaces\n", - filename, m->type.type.lineno); - err = 1; - } - } else { - if (!(kind == INTERFACE_TYPE_BINDER ? returnType->CanWriteToParcel() - : returnType->CanWriteToRpcData())) { - fprintf(stderr, "%s:%d return type %s can't be marshalled.\n", filename, - m->type.type.lineno, m->type.type.data); - err = 1; - } - } - - if (m->type.dimension > 0 && !returnType->CanBeArray()) { - fprintf(stderr, "%s:%d return type %s%s can't be an array.\n", filename, - m->type.array_token.lineno, m->type.type.data, - m->type.array_token.data); - err = 1; - } - - if (m->type.dimension > 1) { - fprintf(stderr, "%s:%d return type %s%s only one" - " dimensional arrays are supported\n", filename, - m->type.array_token.lineno, m->type.type.data, - m->type.array_token.data); - err = 1; - } - - int index = 1; - - arg_type* arg = m->args; - while (arg) { - Type* t = NAMES.Search(arg->type.type.data); - - // check the arg type - if (t == NULL) { - fprintf(stderr, "%s:%d parameter %s (%d) unknown type %s\n", - filename, m->type.type.lineno, arg->name.data, index, - arg->type.type.data); - err = 1; - goto next; - } - - if (t == EVENT_FAKE_TYPE) { - fprintf(stderr, "%s:%d parameter %s (%d) event can not be used as a parameter %s\n", - filename, m->type.type.lineno, arg->name.data, index, - arg->type.type.data); - err = 1; - goto next; - } - - if (!(kind == INTERFACE_TYPE_BINDER ? t->CanWriteToParcel() : t->CanWriteToRpcData())) { - fprintf(stderr, "%s:%d parameter %d: '%s %s' can't be marshalled.\n", - filename, m->type.type.lineno, index, - arg->type.type.data, arg->name.data); - err = 1; - } - - if (returnType == EVENT_FAKE_TYPE - && convert_direction(arg->direction.data) != IN_PARAMETER) { - fprintf(stderr, "%s:%d parameter %d: '%s %s' All paremeters on events must be 'in'.\n", - filename, m->type.type.lineno, index, - arg->type.type.data, arg->name.data); - err = 1; - goto next; - } - - if (arg->direction.data == NULL - && (arg->type.dimension != 0 || t->CanBeOutParameter())) { - fprintf(stderr, "%s:%d parameter %d: '%s %s' can be an out" - " parameter, so you must declare it as in," - " out or inout.\n", - filename, m->type.type.lineno, index, - arg->type.type.data, arg->name.data); - err = 1; - } - - if (convert_direction(arg->direction.data) != IN_PARAMETER - && !t->CanBeOutParameter() - && arg->type.dimension == 0) { - fprintf(stderr, "%s:%d parameter %d: '%s %s %s' can only be an in" - " parameter.\n", - filename, m->type.type.lineno, index, - arg->direction.data, arg->type.type.data, - arg->name.data); - err = 1; - } - - if (arg->type.dimension > 0 && !t->CanBeArray()) { - fprintf(stderr, "%s:%d parameter %d: '%s %s%s %s' can't be an" - " array.\n", filename, - m->type.array_token.lineno, index, arg->direction.data, - arg->type.type.data, arg->type.array_token.data, - arg->name.data); - err = 1; - } - - if (arg->type.dimension > 1) { - fprintf(stderr, "%s:%d parameter %d: '%s %s%s %s' only one" - " dimensional arrays are supported\n", filename, - m->type.array_token.lineno, index, arg->direction.data, - arg->type.type.data, arg->type.array_token.data, - arg->name.data); - err = 1; - } - - // check that the name doesn't match a keyword - if (matches_keyword(arg->name.data)) { - fprintf(stderr, "%s:%d parameter %d %s is named the same as a" - " Java or aidl keyword\n", - filename, m->name.lineno, index, arg->name.data); - err = 1; - } - -next: - index++; - arg = arg->next; - } - - return err; -} - -static int -check_types(const char* filename, document_item_type* items) -{ - int err = 0; - while (items) { - // (nothing to check for USER_DATA_TYPE) - if (items->item_type == INTERFACE_TYPE_BINDER - || items->item_type == INTERFACE_TYPE_RPC) { - map<string,method_type*> methodNames; - interface_type* c = (interface_type*)items; - - interface_item_type* member = c->interface_items; - while (member) { - if (member->item_type == METHOD_TYPE) { - method_type* m = (method_type*)member; - - err |= check_method(filename, items->item_type, m); - - // prevent duplicate methods - if (methodNames.find(m->name.data) == methodNames.end()) { - methodNames[m->name.data] = m; - } else { - fprintf(stderr,"%s:%d attempt to redefine method %s,\n", - filename, m->name.lineno, m->name.data); - method_type* old = methodNames[m->name.data]; - fprintf(stderr, "%s:%d previously defined here.\n", - filename, old->name.lineno); - err = 1; - } - } - member = member->next; - } - } - - items = items->next; - } - return err; -} - -// ========================================================== -static int -exactly_one_interface(const char* filename, const document_item_type* items, const Options& options, - bool* onlyParcelable) -{ - if (items == NULL) { - fprintf(stderr, "%s: file does not contain any interfaces\n", - filename); - return 1; - } - - const document_item_type* next = items->next; - // Allow parcelables to skip the "one-only" rule. - if (items->next != NULL && next->item_type != USER_DATA_TYPE) { - int lineno = -1; - if (next->item_type == INTERFACE_TYPE_BINDER) { - lineno = ((interface_type*)next)->interface_token.lineno; - } - else if (next->item_type == INTERFACE_TYPE_RPC) { - lineno = ((interface_type*)next)->interface_token.lineno; - } - fprintf(stderr, "%s:%d aidl can only handle one interface per file\n", - filename, lineno); - return 1; - } - - if (items->item_type == USER_DATA_TYPE) { - *onlyParcelable = true; - if (options.failOnParcelable) { - fprintf(stderr, "%s:%d aidl can only generate code for interfaces, not" - " parcelables or flattenables,\n", filename, - ((user_data_type*)items)->keyword_token.lineno); - fprintf(stderr, "%s:%d .aidl files that only declare parcelables or flattenables" - "may not go in the Makefile.\n", filename, - ((user_data_type*)items)->keyword_token.lineno); - return 1; - } - } else { - *onlyParcelable = false; - } - - return 0; -} - -// ========================================================== -void -generate_dep_file(const Options& options, const document_item_type* items) -{ - /* we open the file in binary mode to ensure that the same output is - * generated on all platforms !! - */ - FILE* to = NULL; - if (options.autoDepFile) { - string fileName = options.outputFileName + ".d"; - to = fopen(fileName.c_str(), "wb"); - } else { - to = fopen(options.depFileName.c_str(), "wb"); - } - - if (to == NULL) { - return; - } - - const char* slash = "\\"; - import_info* import = g_imports; - if (import == NULL) { - slash = ""; - } - - if (items->item_type == INTERFACE_TYPE_BINDER || items->item_type == INTERFACE_TYPE_RPC) { - fprintf(to, "%s: \\\n", options.outputFileName.c_str()); - } else { - // parcelable: there's no output file. - fprintf(to, " : \\\n"); - } - fprintf(to, " %s %s\n", options.inputFileName.c_str(), slash); - - while (import) { - if (import->next == NULL) { - slash = ""; - } - if (import->filename) { - fprintf(to, " %s %s\n", import->filename, slash); - } - import = import->next; - } - - fprintf(to, "\n"); - - // Output "<imported_file>: " so make won't fail if the imported file has - // been deleted, moved or renamed in incremental build. - import = g_imports; - while (import) { - if (import->filename) { - fprintf(to, "%s :\n", import->filename); - } - import = import->next; - } - - fclose(to); -} - -// ========================================================== -static string -generate_outputFileName2(const Options& options, const buffer_type& name, const char* package) -{ - string result; - - // create the path to the destination folder based on the - // interface package name - result = options.outputBaseFolder; - result += OS_PATH_SEPARATOR; - - string packageStr = package; - size_t len = packageStr.length(); - for (size_t i=0; i<len; i++) { - if (packageStr[i] == '.') { - packageStr[i] = OS_PATH_SEPARATOR; - } - } - - result += packageStr; - - // add the filename by replacing the .aidl extension to .java - const char* p = strchr(name.data, '.'); - len = p ? p-name.data : strlen(name.data); - - result += OS_PATH_SEPARATOR; - result.append(name.data, len); - result += ".java"; - - return result; -} - -// ========================================================== -static string -generate_outputFileName(const Options& options, const document_item_type* items) -{ - // items has already been checked to have only one interface. - if (items->item_type == INTERFACE_TYPE_BINDER || items->item_type == INTERFACE_TYPE_RPC) { - interface_type* type = (interface_type*)items; - - return generate_outputFileName2(options, type->name, type->package); - } else if (items->item_type == USER_DATA_TYPE) { - user_data_type* type = (user_data_type*)items; - return generate_outputFileName2(options, type->name, type->package); - } - - // I don't think we can come here, but safer than returning NULL. - string result; - return result; -} - - - -// ========================================================== -static void -check_outputFilePath(const string& path) { - size_t len = path.length(); - for (size_t i=0; i<len ; i++) { - if (path[i] == OS_PATH_SEPARATOR) { - string p = path.substr(0, i); - if (access(path.data(), F_OK) != 0) { -#ifdef HAVE_MS_C_RUNTIME - _mkdir(p.data()); -#else - mkdir(p.data(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP); -#endif - } - } - } -} - - -// ========================================================== -static int -parse_preprocessed_file(const string& filename) -{ - int err; - - FILE* f = fopen(filename.c_str(), "rb"); - if (f == NULL) { - fprintf(stderr, "aidl: can't open preprocessed file: %s\n", - filename.c_str()); - return 1; - } - - int lineno = 1; - char line[1024]; - char type[1024]; - char fullname[1024]; - while (fgets(line, sizeof(line), f)) { - // skip comments and empty lines - if (!line[0] || strncmp(line, "//", 2) == 0) { - continue; - } - - sscanf(line, "%s %[^; \r\n\t];", type, fullname); - - char* packagename; - char* classname = rfind(fullname, '.'); - if (classname != NULL) { - *classname = '\0'; - classname++; - packagename = fullname; - } else { - classname = fullname; - packagename = NULL; - } - - //printf("%s:%d:...%s...%s...%s...\n", filename.c_str(), lineno, - // type, packagename, classname); - document_item_type* doc; - - if (0 == strcmp("parcelable", type)) { - user_data_type* parcl = (user_data_type*)malloc( - sizeof(user_data_type)); - memset(parcl, 0, sizeof(user_data_type)); - parcl->document_item.item_type = USER_DATA_TYPE; - parcl->keyword_token.lineno = lineno; - parcl->keyword_token.data = strdup(type); - parcl->package = packagename ? strdup(packagename) : NULL; - parcl->name.lineno = lineno; - parcl->name.data = strdup(classname); - parcl->semicolon_token.lineno = lineno; - parcl->semicolon_token.data = strdup(";"); - parcl->flattening_methods = PARCELABLE_DATA; - doc = (document_item_type*)parcl; - } - else if (0 == strcmp("flattenable", type)) { - user_data_type* parcl = (user_data_type*)malloc( - sizeof(user_data_type)); - memset(parcl, 0, sizeof(user_data_type)); - parcl->document_item.item_type = USER_DATA_TYPE; - parcl->keyword_token.lineno = lineno; - parcl->keyword_token.data = strdup(type); - parcl->package = packagename ? strdup(packagename) : NULL; - parcl->name.lineno = lineno; - parcl->name.data = strdup(classname); - parcl->semicolon_token.lineno = lineno; - parcl->semicolon_token.data = strdup(";"); - parcl->flattening_methods = RPC_DATA; - doc = (document_item_type*)parcl; - } - else if (0 == strcmp("interface", type)) { - interface_type* iface = (interface_type*)malloc( - sizeof(interface_type)); - memset(iface, 0, sizeof(interface_type)); - iface->document_item.item_type = INTERFACE_TYPE_BINDER; - iface->interface_token.lineno = lineno; - iface->interface_token.data = strdup(type); - iface->package = packagename ? strdup(packagename) : NULL; - iface->name.lineno = lineno; - iface->name.data = strdup(classname); - iface->open_brace_token.lineno = lineno; - iface->open_brace_token.data = strdup("{"); - iface->close_brace_token.lineno = lineno; - iface->close_brace_token.data = strdup("}"); - doc = (document_item_type*)iface; - } - else { - fprintf(stderr, "%s:%d: bad type in line: %s\n", - filename.c_str(), lineno, line); - return 1; - } - err = gather_types(filename.c_str(), doc); - lineno++; - } - - if (!feof(f)) { - fprintf(stderr, "%s:%d: error reading file, line to long.\n", - filename.c_str(), lineno); - return 1; - } - - fclose(f); - return 0; -} - -static int -check_and_assign_method_ids(const char * filename, interface_item_type* first_item) -{ - // Check whether there are any methods with manually assigned id's and any that are not. - // Either all method id's must be manually assigned or all of them must not. - // Also, check for duplicates of user set id's and that the id's are within the proper bounds. - set<int> usedIds; - interface_item_type* item = first_item; - bool hasUnassignedIds = false; - bool hasAssignedIds = false; - while (item != NULL) { - if (item->item_type == METHOD_TYPE) { - method_type* method_item = (method_type*)item; - if (method_item->hasId) { - hasAssignedIds = true; - method_item->assigned_id = atoi(method_item->id.data); - // Ensure that the user set id is not duplicated. - if (usedIds.find(method_item->assigned_id) != usedIds.end()) { - // We found a duplicate id, so throw an error. - fprintf(stderr, - "%s:%d Found duplicate method id (%d) for method: %s\n", - filename, method_item->id.lineno, - method_item->assigned_id, method_item->name.data); - return 1; - } - // Ensure that the user set id is within the appropriate limits - if (method_item->assigned_id < MIN_USER_SET_METHOD_ID || - method_item->assigned_id > MAX_USER_SET_METHOD_ID) { - fprintf(stderr, "%s:%d Found out of bounds id (%d) for method: %s\n", - filename, method_item->id.lineno, - method_item->assigned_id, method_item->name.data); - fprintf(stderr, " Value for id must be between %d and %d inclusive.\n", - MIN_USER_SET_METHOD_ID, MAX_USER_SET_METHOD_ID); - return 1; - } - usedIds.insert(method_item->assigned_id); - } else { - hasUnassignedIds = true; - } - if (hasAssignedIds && hasUnassignedIds) { - fprintf(stderr, - "%s: You must either assign id's to all methods or to none of them.\n", - filename); - return 1; - } - } - item = item->next; - } - - // In the case that all methods have unassigned id's, set a unique id for them. - if (hasUnassignedIds) { - int newId = 0; - item = first_item; - while (item != NULL) { - if (item->item_type == METHOD_TYPE) { - method_type* method_item = (method_type*)item; - method_item->assigned_id = newId++; - } - item = item->next; - } - } - - // success - return 0; -} - -// ========================================================== -static int -compile_aidl(Options& options) -{ - int err = 0, N; - - set_import_paths(options.importPaths); - - register_base_types(); - - // import the preprocessed file - N = options.preprocessedFiles.size(); - for (int i=0; i<N; i++) { - const string& s = options.preprocessedFiles[i]; - err |= parse_preprocessed_file(s); - } - if (err != 0) { - return err; - } - - // parse the main file - g_callbacks = &g_mainCallbacks; - err = parse_aidl(options.inputFileName.c_str()); - document_item_type* mainDoc = g_document; - g_document = NULL; - - // parse the imports - g_callbacks = &g_mainCallbacks; - import_info* import = g_imports; - while (import) { - if (NAMES.Find(import->neededClass) == NULL) { - import->filename = find_import_file(import->neededClass); - if (!import->filename) { - fprintf(stderr, "%s:%d: couldn't find import for class %s\n", - import->from, import->statement.lineno, - import->neededClass); - err |= 1; - } else { - err |= parse_aidl(import->filename); - import->doc = g_document; - if (import->doc == NULL) { - err |= 1; - } - } - } - import = import->next; - } - // bail out now if parsing wasn't successful - if (err != 0 || mainDoc == NULL) { - //fprintf(stderr, "aidl: parsing failed, stopping.\n"); - return 1; - } - - // complain about ones that aren't in the right files - err |= check_filenames(options.inputFileName.c_str(), mainDoc); - import = g_imports; - while (import) { - err |= check_filenames(import->filename, import->doc); - import = import->next; - } - - // gather the types that have been declared - err |= gather_types(options.inputFileName.c_str(), mainDoc); - import = g_imports; - while (import) { - err |= gather_types(import->filename, import->doc); - import = import->next; - } - -#if 0 - printf("---- main doc ----\n"); - test_document(mainDoc); - - import = g_imports; - while (import) { - printf("---- import doc ----\n"); - test_document(import->doc); - import = import->next; - } - NAMES.Dump(); -#endif - - // check the referenced types in mainDoc to make sure we've imported them - err |= check_types(options.inputFileName.c_str(), mainDoc); - - // finally, there really only needs to be one thing in mainDoc, and it - // needs to be an interface. - bool onlyParcelable = false; - err |= exactly_one_interface(options.inputFileName.c_str(), mainDoc, options, &onlyParcelable); - - // If this includes an interface definition, then assign method ids and validate. - if (!onlyParcelable) { - err |= check_and_assign_method_ids(options.inputFileName.c_str(), - ((interface_type*)mainDoc)->interface_items); - } - - // after this, there shouldn't be any more errors because of the - // input. - if (err != 0 || mainDoc == NULL) { - return 1; - } - - // if needed, generate the outputFileName from the outputBaseFolder - if (options.outputFileName.length() == 0 && - options.outputBaseFolder.length() > 0) { - options.outputFileName = generate_outputFileName(options, mainDoc); - } - - // if we were asked to, generate a make dependency file - // unless it's a parcelable *and* it's supposed to fail on parcelable - if ((options.autoDepFile || options.depFileName != "") && - !(onlyParcelable && options.failOnParcelable)) { - // make sure the folders of the output file all exists - check_outputFilePath(options.outputFileName); - generate_dep_file(options, mainDoc); - } - - // they didn't ask to fail on parcelables, so just exit quietly. - if (onlyParcelable && !options.failOnParcelable) { - return 0; - } - - // make sure the folders of the output file all exists - check_outputFilePath(options.outputFileName); - - err = generate_java(options.outputFileName, options.inputFileName.c_str(), - (interface_type*)mainDoc); - - return err; -} - -static int -preprocess_aidl(const Options& options) -{ - vector<string> lines; - int err; - - // read files - int N = options.filesToPreprocess.size(); - for (int i=0; i<N; i++) { - g_callbacks = &g_mainCallbacks; - err = parse_aidl(options.filesToPreprocess[i].c_str()); - if (err != 0) { - return err; - } - document_item_type* doc = g_document; - string line; - if (doc->item_type == USER_DATA_TYPE) { - user_data_type* parcelable = (user_data_type*)doc; - if ((parcelable->flattening_methods & PARCELABLE_DATA) != 0) { - line = "parcelable "; - } - if ((parcelable->flattening_methods & RPC_DATA) != 0) { - line = "flattenable "; - } - if (parcelable->package) { - line += parcelable->package; - line += '.'; - } - line += parcelable->name.data; - } else { - line = "interface "; - interface_type* iface = (interface_type*)doc; - if (iface->package) { - line += iface->package; - line += '.'; - } - line += iface->name.data; - } - line += ";\n"; - lines.push_back(line); - } - - // write preprocessed file - int fd = open( options.outputFileName.c_str(), - O_RDWR|O_CREAT|O_TRUNC|O_BINARY, -#ifdef HAVE_MS_C_RUNTIME - _S_IREAD|_S_IWRITE); -#else - S_IRUSR|S_IWUSR|S_IRGRP); -#endif - if (fd == -1) { - fprintf(stderr, "aidl: could not open file for write: %s\n", - options.outputFileName.c_str()); - return 1; - } - - N = lines.size(); - for (int i=0; i<N; i++) { - const string& s = lines[i]; - int len = s.length(); - if (len != write(fd, s.c_str(), len)) { - fprintf(stderr, "aidl: error writing to file %s\n", - options.outputFileName.c_str()); - close(fd); - unlink(options.outputFileName.c_str()); - return 1; - } - } - - close(fd); - return 0; -} - -// ========================================================== -int -main(int argc, const char **argv) -{ - Options options; - int result = parse_options(argc, argv, &options); - if (result) { - return result; - } - - switch (options.task) - { - case COMPILE_AIDL: - return compile_aidl(options); - case PREPROCESS_AIDL: - return preprocess_aidl(options); - } - fprintf(stderr, "aidl: internal error\n"); - return 1; -} diff --git a/tools/aidl/aidl_language.cpp b/tools/aidl/aidl_language.cpp deleted file mode 100644 index cd6a3bd..0000000 --- a/tools/aidl/aidl_language.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "aidl_language.h" -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#ifdef HAVE_MS_C_RUNTIME -int isatty(int fd) -{ - return (fd == 0); -} -#endif - -#if 0 -ParserCallbacks k_parserCallbacks = { - NULL -}; -#endif - -ParserCallbacks* g_callbacks = NULL; // &k_parserCallbacks; - diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h deleted file mode 100644 index de1370c..0000000 --- a/tools/aidl/aidl_language.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef DEVICE_TOOLS_AIDL_AIDL_LANGUAGE_H -#define DEVICE_TOOLS_AIDL_AIDL_LANGUAGE_H - - -typedef enum { - NO_EXTRA_TEXT = 0, - SHORT_COMMENT, - LONG_COMMENT, - COPY_TEXT, - WHITESPACE -} which_extra_text; - -typedef struct extra_text_type { - unsigned lineno; - which_extra_text which; - char* data; - unsigned len; - struct extra_text_type* next; -} extra_text_type; - -typedef struct buffer_type { - unsigned lineno; - unsigned token; - char *data; - extra_text_type* extra; -} buffer_type; - -typedef struct type_type { - buffer_type type; - buffer_type array_token; - int dimension; -} type_type; - -typedef struct arg_type { - buffer_type comma_token; // empty in the first one in the list - buffer_type direction; - type_type type; - buffer_type name; - struct arg_type *next; -} arg_type; - -enum { - METHOD_TYPE -}; - -typedef struct interface_item_type { - unsigned item_type; - struct interface_item_type* next; -} interface_item_type; - -typedef struct method_type { - interface_item_type interface_item; - type_type type; - bool oneway; - buffer_type oneway_token; - buffer_type name; - buffer_type open_paren_token; - arg_type* args; - buffer_type close_paren_token; - bool hasId; - buffer_type equals_token; - buffer_type id; - // XXX missing comments/copy text here - buffer_type semicolon_token; - buffer_type* comments_token; // points into this structure, DO NOT DELETE - int assigned_id; -} method_type; - -enum { - USER_DATA_TYPE = 12, - INTERFACE_TYPE_BINDER, - INTERFACE_TYPE_RPC -}; - -typedef struct document_item_type { - unsigned item_type; - struct document_item_type* next; -} document_item_type; - - -// for user_data_type.flattening_methods -enum { - PARCELABLE_DATA = 0x1, - RPC_DATA = 0x2 -}; - -typedef struct user_data_type { - document_item_type document_item; - buffer_type keyword_token; // only the first one - char* package; - buffer_type name; - buffer_type semicolon_token; - int flattening_methods; -} user_data_type; - -typedef struct interface_type { - document_item_type document_item; - buffer_type interface_token; - bool oneway; - buffer_type oneway_token; - char* package; - buffer_type name; - buffer_type open_brace_token; - interface_item_type* interface_items; - buffer_type close_brace_token; - buffer_type* comments_token; // points into this structure, DO NOT DELETE -} interface_type; - -typedef union lexer_type { - buffer_type buffer; - type_type type; - arg_type *arg; - method_type* method; - interface_item_type* interface_item; - interface_type* interface_obj; - user_data_type* user_data; - document_item_type* document_item; -} lexer_type; - - -#define YYSTYPE lexer_type - -#if __cplusplus -extern "C" { -#endif - -int parse_aidl(char const *); - -// strips off the leading whitespace, the "import" text -// also returns whether it's a local or system import -// we rely on the input matching the import regex from below -char* parse_import_statement(const char* text); - -// in, out or inout -enum { - IN_PARAMETER = 1, - OUT_PARAMETER = 2, - INOUT_PARAMETER = 3 -}; -int convert_direction(const char* direction); - -// callbacks from within the parser -// these functions all take ownership of the strings -typedef struct ParserCallbacks { - void (*document)(document_item_type* items); - void (*import)(buffer_type* statement); -} ParserCallbacks; - -extern ParserCallbacks* g_callbacks; - -// true if there was an error parsing, false otherwise -extern int g_error; - -// the name of the file we're currently parsing -extern char const* g_currentFilename; - -// the package name for our current file -extern char const* g_currentPackage; - -typedef enum { - STATEMENT_INSIDE_INTERFACE -} error_type; - -void init_buffer_type(buffer_type* buf, int lineno); - - -#if __cplusplus -} -#endif - - -#endif // DEVICE_TOOLS_AIDL_AIDL_LANGUAGE_H diff --git a/tools/aidl/aidl_language_l.l b/tools/aidl/aidl_language_l.l deleted file mode 100644 index 3d33e7a..0000000 --- a/tools/aidl/aidl_language_l.l +++ /dev/null @@ -1,214 +0,0 @@ -%{ -#include "aidl_language.h" -#include "aidl_language_y.h" -#include "search_path.h" -#include <string.h> -#include <stdlib.h> - -extern YYSTYPE yylval; - -// comment and whitespace handling -// these functions save a copy of the buffer -static void begin_extra_text(unsigned lineno, which_extra_text which); -static void append_extra_text(char* text); -static extra_text_type* get_extra_text(void); // you now own the object - // this returns -static void drop_extra_text(void); - -// package handling -static void do_package_statement(const char* importText); - -#define SET_BUFFER(t) \ - do { \ - yylval.buffer.lineno = yylineno; \ - yylval.buffer.token = (t); \ - yylval.buffer.data = strdup(yytext); \ - yylval.buffer.extra = get_extra_text(); \ - } while(0) - -%} - -%option yylineno -%option noyywrap - -%x COPYING LONG_COMMENT - -identifier [_a-zA-Z][_a-zA-Z0-9\.]* -whitespace ([ \t\n\r]+) -brackets \[{whitespace}?\] -idvalue (0|[1-9][0-9]*) - -%% - - -\%\%\{ { begin_extra_text(yylineno, COPY_TEXT); BEGIN(COPYING); } -<COPYING>\}\%\% { BEGIN(INITIAL); } -<COPYING>.*\n { append_extra_text(yytext); } -<COPYING>.* { append_extra_text(yytext); } -<COPYING>\n+ { append_extra_text(yytext); } - - -\/\* { begin_extra_text(yylineno, (which_extra_text)LONG_COMMENT); - BEGIN(LONG_COMMENT); } -<LONG_COMMENT>[^*]* { append_extra_text(yytext); } -<LONG_COMMENT>\*+[^/] { append_extra_text(yytext); } -<LONG_COMMENT>\n { append_extra_text(yytext); } -<LONG_COMMENT>\**\/ { BEGIN(INITIAL); } - -^{whitespace}?import{whitespace}[^ \t\r\n]+{whitespace}?; { - SET_BUFFER(IMPORT); - return IMPORT; - } -^{whitespace}?package{whitespace}[^ \t\r\n]+{whitespace}?; { - do_package_statement(yytext); - SET_BUFFER(PACKAGE); - return PACKAGE; - } -<<EOF>> { yyterminate(); } - -\/\/.*\n { begin_extra_text(yylineno, SHORT_COMMENT); - append_extra_text(yytext); } - -{whitespace} { /* begin_extra_text(yylineno, WHITESPACE); - append_extra_text(yytext); */ } - -; { SET_BUFFER(';'); return ';'; } -\{ { SET_BUFFER('{'); return '{'; } -\} { SET_BUFFER('}'); return '}'; } -\( { SET_BUFFER('('); return '('; } -\) { SET_BUFFER(')'); return ')'; } -, { SET_BUFFER(','); return ','; } -= { SET_BUFFER('='); return '='; } - - /* keywords */ -parcelable { SET_BUFFER(PARCELABLE); return PARCELABLE; } -interface { SET_BUFFER(INTERFACE); return INTERFACE; } -flattenable { SET_BUFFER(FLATTENABLE); return FLATTENABLE; } -rpc { SET_BUFFER(INTERFACE); return RPC; } -in { SET_BUFFER(IN); return IN; } -out { SET_BUFFER(OUT); return OUT; } -inout { SET_BUFFER(INOUT); return INOUT; } -oneway { SET_BUFFER(ONEWAY); return ONEWAY; } - -{brackets}+ { SET_BUFFER(ARRAY); return ARRAY; } -{idvalue} { SET_BUFFER(IDVALUE); return IDVALUE; } -{identifier} { SET_BUFFER(IDENTIFIER); return IDENTIFIER; } -{identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\> { - SET_BUFFER(GENERIC); return GENERIC; } - - /* syntax error! */ -. { printf("UNKNOWN(%s)", yytext); - yylval.buffer.lineno = yylineno; - yylval.buffer.token = IDENTIFIER; - yylval.buffer.data = strdup(yytext); - return IDENTIFIER; - } - -%% - -// comment and whitespace handling -// ================================================ -extra_text_type* g_extraText = NULL; -extra_text_type* g_nextExtraText = NULL; - -void begin_extra_text(unsigned lineno, which_extra_text which) -{ - extra_text_type* text = (extra_text_type*)malloc(sizeof(extra_text_type)); - text->lineno = lineno; - text->which = which; - text->data = NULL; - text->len = 0; - text->next = NULL; - if (g_nextExtraText == NULL) { - g_extraText = text; - } else { - g_nextExtraText->next = text; - } - g_nextExtraText = text; -} - -void append_extra_text(char* text) -{ - if (g_nextExtraText->data == NULL) { - g_nextExtraText->data = strdup(text); - g_nextExtraText->len = strlen(text); - } else { - char* orig = g_nextExtraText->data; - unsigned oldLen = g_nextExtraText->len; - unsigned len = strlen(text); - g_nextExtraText->len += len; - g_nextExtraText->data = (char*)malloc(g_nextExtraText->len+1); - memcpy(g_nextExtraText->data, orig, oldLen); - memcpy(g_nextExtraText->data+oldLen, text, len); - g_nextExtraText->data[g_nextExtraText->len] = '\0'; - free(orig); - } -} - -extra_text_type* -get_extra_text(void) -{ - extra_text_type* result = g_extraText; - g_extraText = NULL; - g_nextExtraText = NULL; - return result; -} - -void drop_extra_text(void) -{ - extra_text_type* p = g_extraText; - while (p) { - extra_text_type* next = p->next; - free(p->data); - free(p); - free(next); - } - g_extraText = NULL; - g_nextExtraText = NULL; -} - - -// package handling -// ================================================ -void do_package_statement(const char* importText) -{ - if (g_currentPackage) free((void*)g_currentPackage); - g_currentPackage = parse_import_statement(importText); -} - - -// main parse function -// ================================================ -char const* g_currentFilename = NULL; -char const* g_currentPackage = NULL; - -int yyparse(void); - -int parse_aidl(char const *filename) -{ - yyin = fopen(filename, "r"); - if (yyin) { - char const* oldFilename = g_currentFilename; - char const* oldPackage = g_currentPackage; - g_currentFilename = strdup(filename); - - g_error = 0; - yylineno = 1; - int rv = yyparse(); - if (g_error != 0) { - rv = g_error; - } - - free((void*)g_currentFilename); - g_currentFilename = oldFilename; - - if (g_currentPackage) free((void*)g_currentPackage); - g_currentPackage = oldPackage; - - return rv; - } else { - fprintf(stderr, "aidl: unable to open file for read: %s\n", filename); - return 1; - } -} - diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y deleted file mode 100644 index 9b40d28..0000000 --- a/tools/aidl/aidl_language_y.y +++ /dev/null @@ -1,373 +0,0 @@ -%{ -#include "aidl_language.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int yyerror(char* errstr); -int yylex(void); -extern int yylineno; - -static int count_brackets(const char*); - -%} - -%token IMPORT -%token PACKAGE -%token IDENTIFIER -%token IDVALUE -%token GENERIC -%token ARRAY -%token PARCELABLE -%token INTERFACE -%token FLATTENABLE -%token RPC -%token IN -%token OUT -%token INOUT -%token ONEWAY - -%% -document: - document_items { g_callbacks->document($1.document_item); } - | headers document_items { g_callbacks->document($2.document_item); } - ; - -headers: - package { } - | imports { } - | package imports { } - ; - -package: - PACKAGE { } - ; - -imports: - IMPORT { g_callbacks->import(&($1.buffer)); } - | IMPORT imports { g_callbacks->import(&($1.buffer)); } - ; - -document_items: - { $$.document_item = NULL; } - | document_items declaration { - if ($2.document_item == NULL) { - // error cases only - $$ = $1; - } else { - document_item_type* p = $1.document_item; - while (p && p->next) { - p=p->next; - } - if (p) { - p->next = (document_item_type*)$2.document_item; - $$ = $1; - } else { - $$.document_item = (document_item_type*)$2.document_item; - } - } - } - | document_items error { - fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", g_currentFilename, - $2.buffer.lineno, $2.buffer.data); - $$ = $1; - } - ; - -declaration: - parcelable_decl { $$.document_item = (document_item_type*)$1.user_data; } - | interface_decl { $$.document_item = (document_item_type*)$1.interface_item; } - ; - -parcelable_decl: - PARCELABLE IDENTIFIER ';' { - user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type)); - b->document_item.item_type = USER_DATA_TYPE; - b->document_item.next = NULL; - b->keyword_token = $1.buffer; - b->name = $2.buffer; - b->package = g_currentPackage ? strdup(g_currentPackage) : NULL; - b->semicolon_token = $3.buffer; - b->flattening_methods = PARCELABLE_DATA; - $$.user_data = b; - } - | PARCELABLE ';' { - fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n", - g_currentFilename, $1.buffer.lineno); - $$.user_data = NULL; - } - | PARCELABLE error ';' { - fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); - $$.user_data = NULL; - } - | FLATTENABLE IDENTIFIER ';' { - user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type)); - b->document_item.item_type = USER_DATA_TYPE; - b->document_item.next = NULL; - b->keyword_token = $1.buffer; - b->name = $2.buffer; - b->package = g_currentPackage ? strdup(g_currentPackage) : NULL; - b->semicolon_token = $3.buffer; - b->flattening_methods = PARCELABLE_DATA | RPC_DATA; - $$.user_data = b; - } - | FLATTENABLE ';' { - fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name.\n", - g_currentFilename, $1.buffer.lineno); - $$.user_data = NULL; - } - | FLATTENABLE error ';' { - fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name, saw \"%s\".\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); - $$.user_data = NULL; - } - - ; - -interface_header: - INTERFACE { - interface_type* c = (interface_type*)malloc(sizeof(interface_type)); - c->document_item.item_type = INTERFACE_TYPE_BINDER; - c->document_item.next = NULL; - c->interface_token = $1.buffer; - c->oneway = false; - memset(&c->oneway_token, 0, sizeof(buffer_type)); - c->comments_token = &c->interface_token; - $$.interface_obj = c; - } - | ONEWAY INTERFACE { - interface_type* c = (interface_type*)malloc(sizeof(interface_type)); - c->document_item.item_type = INTERFACE_TYPE_BINDER; - c->document_item.next = NULL; - c->interface_token = $2.buffer; - c->oneway = true; - c->oneway_token = $1.buffer; - c->comments_token = &c->oneway_token; - $$.interface_obj = c; - } - | RPC { - interface_type* c = (interface_type*)malloc(sizeof(interface_type)); - c->document_item.item_type = INTERFACE_TYPE_RPC; - c->document_item.next = NULL; - c->interface_token = $1.buffer; - c->oneway = false; - memset(&c->oneway_token, 0, sizeof(buffer_type)); - c->comments_token = &c->interface_token; - $$.interface_obj = c; - } - ; - -interface_keywords: - INTERFACE - | RPC - ; - -interface_decl: - interface_header IDENTIFIER '{' interface_items '}' { - interface_type* c = $1.interface_obj; - c->name = $2.buffer; - c->package = g_currentPackage ? strdup(g_currentPackage) : NULL; - c->open_brace_token = $3.buffer; - c->interface_items = $4.interface_item; - c->close_brace_token = $5.buffer; - $$.interface_obj = c; - } - | interface_keywords error '{' interface_items '}' { - fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); - $$.document_item = NULL; - } - | interface_keywords error '}' { - fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); - $$.document_item = NULL; - } - - ; - -interface_items: - { $$.interface_item = NULL; } - | interface_items method_decl { - interface_item_type* p=$1.interface_item; - while (p && p->next) { - p=p->next; - } - if (p) { - p->next = (interface_item_type*)$2.method; - $$ = $1; - } else { - $$.interface_item = (interface_item_type*)$2.method; - } - } - | interface_items error ';' { - fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n", - g_currentFilename, $3.buffer.lineno); - $$ = $1; - } - ; - -method_decl: - type IDENTIFIER '(' arg_list ')' ';' { - method_type *method = (method_type*)malloc(sizeof(method_type)); - method->interface_item.item_type = METHOD_TYPE; - method->interface_item.next = NULL; - method->oneway = false; - method->type = $1.type; - memset(&method->oneway_token, 0, sizeof(buffer_type)); - method->name = $2.buffer; - method->open_paren_token = $3.buffer; - method->args = $4.arg; - method->close_paren_token = $5.buffer; - method->hasId = false; - memset(&method->equals_token, 0, sizeof(buffer_type)); - memset(&method->id, 0, sizeof(buffer_type)); - method->semicolon_token = $6.buffer; - method->comments_token = &method->type.type; - $$.method = method; - } - | ONEWAY type IDENTIFIER '(' arg_list ')' ';' { - method_type *method = (method_type*)malloc(sizeof(method_type)); - method->interface_item.item_type = METHOD_TYPE; - method->interface_item.next = NULL; - method->oneway = true; - method->oneway_token = $1.buffer; - method->type = $2.type; - method->name = $3.buffer; - method->open_paren_token = $4.buffer; - method->args = $5.arg; - method->close_paren_token = $6.buffer; - method->hasId = false; - memset(&method->equals_token, 0, sizeof(buffer_type)); - memset(&method->id, 0, sizeof(buffer_type)); - method->semicolon_token = $7.buffer; - method->comments_token = &method->oneway_token; - $$.method = method; - } - | type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' { - method_type *method = (method_type*)malloc(sizeof(method_type)); - method->interface_item.item_type = METHOD_TYPE; - method->interface_item.next = NULL; - method->oneway = false; - memset(&method->oneway_token, 0, sizeof(buffer_type)); - method->type = $1.type; - method->name = $2.buffer; - method->open_paren_token = $3.buffer; - method->args = $4.arg; - method->close_paren_token = $5.buffer; - method->hasId = true; - method->equals_token = $6.buffer; - method->id = $7.buffer; - method->semicolon_token = $8.buffer; - method->comments_token = &method->type.type; - $$.method = method; - } - | ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' { - method_type *method = (method_type*)malloc(sizeof(method_type)); - method->interface_item.item_type = METHOD_TYPE; - method->interface_item.next = NULL; - method->oneway = true; - method->oneway_token = $1.buffer; - method->type = $2.type; - method->name = $3.buffer; - method->open_paren_token = $4.buffer; - method->args = $5.arg; - method->close_paren_token = $6.buffer; - method->hasId = true; - method->equals_token = $7.buffer; - method->id = $8.buffer; - method->semicolon_token = $9.buffer; - method->comments_token = &method->oneway_token; - $$.method = method; - } - ; - -arg_list: - { $$.arg = NULL; } - | arg { $$ = $1; } - | arg_list ',' arg { - if ($$.arg != NULL) { - // only NULL on error - $$ = $1; - arg_type *p = $1.arg; - while (p && p->next) { - p=p->next; - } - $3.arg->comma_token = $2.buffer; - p->next = $3.arg; - } - } - | error { - fprintf(stderr, "%s:%d: syntax error in parameter list\n", g_currentFilename, $1.buffer.lineno); - $$.arg = NULL; - } - ; - -arg: - direction type IDENTIFIER { - arg_type* arg = (arg_type*)malloc(sizeof(arg_type)); - memset(&arg->comma_token, 0, sizeof(buffer_type)); - arg->direction = $1.buffer; - arg->type = $2.type; - arg->name = $3.buffer; - arg->next = NULL; - $$.arg = arg; - } - ; - -type: - IDENTIFIER { - $$.type.type = $1.buffer; - init_buffer_type(&$$.type.array_token, yylineno); - $$.type.dimension = 0; - } - | IDENTIFIER ARRAY { - $$.type.type = $1.buffer; - $$.type.array_token = $2.buffer; - $$.type.dimension = count_brackets($2.buffer.data); - } - | GENERIC { - $$.type.type = $1.buffer; - init_buffer_type(&$$.type.array_token, yylineno); - $$.type.dimension = 0; - } - ; - -direction: - { init_buffer_type(&$$.buffer, yylineno); } - | IN { $$.buffer = $1.buffer; } - | OUT { $$.buffer = $1.buffer; } - | INOUT { $$.buffer = $1.buffer; } - ; - -%% - -#include <ctype.h> -#include <stdio.h> - -int g_error = 0; - -int yyerror(char* errstr) -{ - fprintf(stderr, "%s:%d: %s\n", g_currentFilename, yylineno, errstr); - g_error = 1; - return 1; -} - -void init_buffer_type(buffer_type* buf, int lineno) -{ - buf->lineno = lineno; - buf->token = 0; - buf->data = NULL; - buf->extra = NULL; -} - -static int count_brackets(const char* s) -{ - int n=0; - while (*s) { - if (*s == '[') n++; - s++; - } - return n; -} diff --git a/tools/aidl/generate_java.cpp b/tools/aidl/generate_java.cpp deleted file mode 100644 index 9e57407..0000000 --- a/tools/aidl/generate_java.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "generate_java.h" -#include "Type.h" -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -// ================================================= -VariableFactory::VariableFactory(const string& base) - :m_base(base), - m_index(0) -{ -} - -Variable* -VariableFactory::Get(Type* type) -{ - char name[100]; - sprintf(name, "%s%d", m_base.c_str(), m_index); - m_index++; - Variable* v = new Variable(type, name); - m_vars.push_back(v); - return v; -} - -Variable* -VariableFactory::Get(int index) -{ - return m_vars[index]; -} - -// ================================================= -string -gather_comments(extra_text_type* extra) -{ - string s; - while (extra) { - if (extra->which == SHORT_COMMENT) { - s += extra->data; - } - else if (extra->which == LONG_COMMENT) { - s += "/*"; - s += extra->data; - s += "*/"; - } - extra = extra->next; - } - return s; -} - -string -append(const char* a, const char* b) -{ - string s = a; - s += b; - return s; -} - -// ================================================= -int -generate_java(const string& filename, const string& originalSrc, - interface_type* iface) -{ - Class* cl; - - if (iface->document_item.item_type == INTERFACE_TYPE_BINDER) { - cl = generate_binder_interface_class(iface); - } - else if (iface->document_item.item_type == INTERFACE_TYPE_RPC) { - cl = generate_rpc_interface_class(iface); - } - - Document* document = new Document; - document->comment = ""; - if (iface->package) document->package = iface->package; - document->originalSrc = originalSrc; - document->classes.push_back(cl); - -// printf("outputting... filename=%s\n", filename.c_str()); - FILE* to; - if (filename == "-") { - to = stdout; - } else { - /* open file in binary mode to ensure that the tool produces the - * same output on all platforms !! - */ - to = fopen(filename.c_str(), "wb"); - if (to == NULL) { - fprintf(stderr, "unable to open %s for write\n", filename.c_str()); - return 1; - } - } - - document->Write(to); - - fclose(to); - return 0; -} - diff --git a/tools/aidl/generate_java.h b/tools/aidl/generate_java.h deleted file mode 100644 index 4bfcfeb..0000000 --- a/tools/aidl/generate_java.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef GENERATE_JAVA_H -#define GENERATE_JAVA_H - -#include "aidl_language.h" -#include "AST.h" - -#include <string> - -using namespace std; - -int generate_java(const string& filename, const string& originalSrc, - interface_type* iface); - -Class* generate_binder_interface_class(const interface_type* iface); -Class* generate_rpc_interface_class(const interface_type* iface); - -string gather_comments(extra_text_type* extra); -string append(const char* a, const char* b); - -class VariableFactory -{ -public: - VariableFactory(const string& base); // base must be short - Variable* Get(Type* type); - Variable* Get(int index); -private: - vector<Variable*> m_vars; - string m_base; - int m_index; -}; - -#endif // GENERATE_JAVA_H - diff --git a/tools/aidl/generate_java_binder.cpp b/tools/aidl/generate_java_binder.cpp deleted file mode 100644 index f291ceb..0000000 --- a/tools/aidl/generate_java_binder.cpp +++ /dev/null @@ -1,560 +0,0 @@ -#include "generate_java.h" -#include "Type.h" -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -// ================================================= -class StubClass : public Class -{ -public: - StubClass(Type* type, Type* interfaceType); - virtual ~StubClass(); - - Variable* transact_code; - Variable* transact_data; - Variable* transact_reply; - Variable* transact_flags; - SwitchStatement* transact_switch; -private: - void make_as_interface(Type* interfaceType); -}; - -StubClass::StubClass(Type* type, Type* interfaceType) - :Class() -{ - this->comment = "/** Local-side IPC implementation stub class. */"; - this->modifiers = PUBLIC | ABSTRACT | STATIC; - this->what = Class::CLASS; - this->type = type; - this->extends = BINDER_NATIVE_TYPE; - this->interfaces.push_back(interfaceType); - - // descriptor - Field* descriptor = new Field(STATIC | FINAL | PRIVATE, - new Variable(STRING_TYPE, "DESCRIPTOR")); - descriptor->value = "\"" + interfaceType->QualifiedName() + "\""; - this->elements.push_back(descriptor); - - // ctor - Method* ctor = new Method; - ctor->modifiers = PUBLIC; - ctor->comment = "/** Construct the stub at attach it to the " - "interface. */"; - ctor->name = "Stub"; - ctor->statements = new StatementBlock; - MethodCall* attach = new MethodCall(THIS_VALUE, "attachInterface", - 2, THIS_VALUE, new LiteralExpression("DESCRIPTOR")); - ctor->statements->Add(attach); - this->elements.push_back(ctor); - - // asInterface - make_as_interface(interfaceType); - - // asBinder - Method* asBinder = new Method; - asBinder->modifiers = PUBLIC | OVERRIDE; - asBinder->returnType = IBINDER_TYPE; - asBinder->name = "asBinder"; - asBinder->statements = new StatementBlock; - asBinder->statements->Add(new ReturnStatement(THIS_VALUE)); - this->elements.push_back(asBinder); - - // onTransact - this->transact_code = new Variable(INT_TYPE, "code"); - this->transact_data = new Variable(PARCEL_TYPE, "data"); - this->transact_reply = new Variable(PARCEL_TYPE, "reply"); - this->transact_flags = new Variable(INT_TYPE, "flags"); - Method* onTransact = new Method; - onTransact->modifiers = PUBLIC | OVERRIDE; - onTransact->returnType = BOOLEAN_TYPE; - onTransact->name = "onTransact"; - onTransact->parameters.push_back(this->transact_code); - onTransact->parameters.push_back(this->transact_data); - onTransact->parameters.push_back(this->transact_reply); - onTransact->parameters.push_back(this->transact_flags); - onTransact->statements = new StatementBlock; - onTransact->exceptions.push_back(REMOTE_EXCEPTION_TYPE); - this->elements.push_back(onTransact); - this->transact_switch = new SwitchStatement(this->transact_code); - - onTransact->statements->Add(this->transact_switch); - MethodCall* superCall = new MethodCall(SUPER_VALUE, "onTransact", 4, - this->transact_code, this->transact_data, - this->transact_reply, this->transact_flags); - onTransact->statements->Add(new ReturnStatement(superCall)); -} - -StubClass::~StubClass() -{ -} - -void -StubClass::make_as_interface(Type *interfaceType) -{ - Variable* obj = new Variable(IBINDER_TYPE, "obj"); - - Method* m = new Method; - m->comment = "/**\n * Cast an IBinder object into an "; - m->comment += interfaceType->QualifiedName(); - m->comment += " interface,\n"; - m->comment += " * generating a proxy if needed.\n */"; - m->modifiers = PUBLIC | STATIC; - m->returnType = interfaceType; - m->name = "asInterface"; - m->parameters.push_back(obj); - m->statements = new StatementBlock; - - IfStatement* ifstatement = new IfStatement(); - ifstatement->expression = new Comparison(obj, "==", NULL_VALUE); - ifstatement->statements = new StatementBlock; - ifstatement->statements->Add(new ReturnStatement(NULL_VALUE)); - m->statements->Add(ifstatement); - - // IInterface iin = obj.queryLocalInterface(DESCRIPTOR) - MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface"); - queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR")); - IInterfaceType* iinType = new IInterfaceType(); - Variable *iin = new Variable(iinType, "iin"); - VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface, NULL); - m->statements->Add(iinVd); - - // Ensure the instance type of the local object is as expected. - // One scenario where this is needed is if another package (with a - // different class loader) runs in the same process as the service. - - // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) iin; - Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE); - Comparison* instOfCheck = new Comparison(iin, " instanceof ", - new LiteralExpression(interfaceType->QualifiedName())); - IfStatement* instOfStatement = new IfStatement(); - instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck); - instOfStatement->statements = new StatementBlock; - instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType, iin))); - m->statements->Add(instOfStatement); - - string proxyType = interfaceType->QualifiedName(); - proxyType += ".Stub.Proxy"; - NewExpression* ne = new NewExpression(NAMES.Find(proxyType)); - ne->arguments.push_back(obj); - m->statements->Add(new ReturnStatement(ne)); - - this->elements.push_back(m); -} - - - -// ================================================= -class ProxyClass : public Class -{ -public: - ProxyClass(Type* type, InterfaceType* interfaceType); - virtual ~ProxyClass(); - - Variable* mRemote; - bool mOneWay; -}; - -ProxyClass::ProxyClass(Type* type, InterfaceType* interfaceType) - :Class() -{ - this->modifiers = PRIVATE | STATIC; - this->what = Class::CLASS; - this->type = type; - this->interfaces.push_back(interfaceType); - - mOneWay = interfaceType->OneWay(); - - // IBinder mRemote - mRemote = new Variable(IBINDER_TYPE, "mRemote"); - this->elements.push_back(new Field(PRIVATE, mRemote)); - - // Proxy() - Variable* remote = new Variable(IBINDER_TYPE, "remote"); - Method* ctor = new Method; - ctor->name = "Proxy"; - ctor->statements = new StatementBlock; - ctor->parameters.push_back(remote); - ctor->statements->Add(new Assignment(mRemote, remote)); - this->elements.push_back(ctor); - - // IBinder asBinder() - Method* asBinder = new Method; - asBinder->modifiers = PUBLIC | OVERRIDE; - asBinder->returnType = IBINDER_TYPE; - asBinder->name = "asBinder"; - asBinder->statements = new StatementBlock; - asBinder->statements->Add(new ReturnStatement(mRemote)); - this->elements.push_back(asBinder); -} - -ProxyClass::~ProxyClass() -{ -} - -// ================================================= -static void -generate_new_array(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel) -{ - Variable* len = new Variable(INT_TYPE, v->name + "_length"); - addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt"))); - IfStatement* lencheck = new IfStatement(); - lencheck->expression = new Comparison(len, "<", new LiteralExpression("0")); - lencheck->statements->Add(new Assignment(v, NULL_VALUE)); - lencheck->elseif = new IfStatement(); - lencheck->elseif->statements->Add(new Assignment(v, - new NewArrayExpression(t, len))); - addTo->Add(lencheck); -} - -static void -generate_write_to_parcel(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel, int flags) -{ - if (v->dimension == 0) { - t->WriteToParcel(addTo, v, parcel, flags); - } - if (v->dimension == 1) { - t->WriteArrayToParcel(addTo, v, parcel, flags); - } -} - -static void -generate_create_from_parcel(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl) -{ - if (v->dimension == 0) { - t->CreateFromParcel(addTo, v, parcel, cl); - } - if (v->dimension == 1) { - t->CreateArrayFromParcel(addTo, v, parcel, cl); - } -} - -static void -generate_read_from_parcel(Type* t, StatementBlock* addTo, Variable* v, - Variable* parcel, Variable** cl) -{ - if (v->dimension == 0) { - t->ReadFromParcel(addTo, v, parcel, cl); - } - if (v->dimension == 1) { - t->ReadArrayFromParcel(addTo, v, parcel, cl); - } -} - - -static void -generate_method(const method_type* method, Class* interface, - StubClass* stubClass, ProxyClass* proxyClass, int index) -{ - arg_type* arg; - int i; - bool hasOutParams = false; - - const bool oneway = proxyClass->mOneWay || method->oneway; - - // == the TRANSACT_ constant ============================================= - string transactCodeName = "TRANSACTION_"; - transactCodeName += method->name.data; - - char transactCodeValue[60]; - sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index); - - Field* transactCode = new Field(STATIC | FINAL, - new Variable(INT_TYPE, transactCodeName)); - transactCode->value = transactCodeValue; - stubClass->elements.push_back(transactCode); - - // == the declaration in the interface =================================== - Method* decl = new Method; - decl->comment = gather_comments(method->comments_token->extra); - decl->modifiers = PUBLIC; - decl->returnType = NAMES.Search(method->type.type.data); - decl->returnTypeDimension = method->type.dimension; - decl->name = method->name.data; - - arg = method->args; - while (arg != NULL) { - decl->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - arg = arg->next; - } - - decl->exceptions.push_back(REMOTE_EXCEPTION_TYPE); - - interface->elements.push_back(decl); - - // == the stub method ==================================================== - - Case* c = new Case(transactCodeName); - - MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data); - - // interface token validation is the very first thing we do - c->statements->Add(new MethodCall(stubClass->transact_data, - "enforceInterface", 1, new LiteralExpression("DESCRIPTOR"))); - - // args - Variable* cl = NULL; - VariableFactory stubArgs("_arg"); - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(t); - v->dimension = arg->type.dimension; - - c->statements->Add(new VariableDeclaration(v)); - - if (convert_direction(arg->direction.data) & IN_PARAMETER) { - generate_create_from_parcel(t, c->statements, v, - stubClass->transact_data, &cl); - } else { - if (arg->type.dimension == 0) { - c->statements->Add(new Assignment(v, new NewExpression(v->type))); - } - else if (arg->type.dimension == 1) { - generate_new_array(v->type, c->statements, v, - stubClass->transact_data); - } - else { - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, - __LINE__); - } - } - - realCall->arguments.push_back(v); - - arg = arg->next; - } - - // the real call - Variable* _result = NULL; - if (0 == strcmp(method->type.type.data, "void")) { - c->statements->Add(realCall); - - if (!oneway) { - // report that there were no exceptions - MethodCall* ex = new MethodCall(stubClass->transact_reply, - "writeNoException", 0); - c->statements->Add(ex); - } - } else { - _result = new Variable(decl->returnType, "_result", - decl->returnTypeDimension); - c->statements->Add(new VariableDeclaration(_result, realCall)); - - if (!oneway) { - // report that there were no exceptions - MethodCall* ex = new MethodCall(stubClass->transact_reply, - "writeNoException", 0); - c->statements->Add(ex); - } - - // marshall the return value - generate_write_to_parcel(decl->returnType, c->statements, _result, - stubClass->transact_reply, - Type::PARCELABLE_WRITE_RETURN_VALUE); - } - - // out parameters - i = 0; - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(i++); - - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - generate_write_to_parcel(t, c->statements, v, - stubClass->transact_reply, - Type::PARCELABLE_WRITE_RETURN_VALUE); - hasOutParams = true; - } - - arg = arg->next; - } - - // return true - c->statements->Add(new ReturnStatement(TRUE_VALUE)); - stubClass->transact_switch->cases.push_back(c); - - // == the proxy method =================================================== - Method* proxy = new Method; - proxy->comment = gather_comments(method->comments_token->extra); - proxy->modifiers = PUBLIC | OVERRIDE; - proxy->returnType = NAMES.Search(method->type.type.data); - proxy->returnTypeDimension = method->type.dimension; - proxy->name = method->name.data; - proxy->statements = new StatementBlock; - arg = method->args; - while (arg != NULL) { - proxy->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - arg = arg->next; - } - proxy->exceptions.push_back(REMOTE_EXCEPTION_TYPE); - proxyClass->elements.push_back(proxy); - - // the parcels - Variable* _data = new Variable(PARCEL_TYPE, "_data"); - proxy->statements->Add(new VariableDeclaration(_data, - new MethodCall(PARCEL_TYPE, "obtain"))); - Variable* _reply = NULL; - if (!oneway) { - _reply = new Variable(PARCEL_TYPE, "_reply"); - proxy->statements->Add(new VariableDeclaration(_reply, - new MethodCall(PARCEL_TYPE, "obtain"))); - } - - // the return value - _result = NULL; - if (0 != strcmp(method->type.type.data, "void")) { - _result = new Variable(proxy->returnType, "_result", - method->type.dimension); - proxy->statements->Add(new VariableDeclaration(_result)); - } - - // try and finally - TryStatement* tryStatement = new TryStatement(); - proxy->statements->Add(tryStatement); - FinallyStatement* finallyStatement = new FinallyStatement(); - proxy->statements->Add(finallyStatement); - - // the interface identifier token: the DESCRIPTOR constant, marshalled as a string - tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken", - 1, new LiteralExpression("DESCRIPTOR"))); - - // the parameters - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = new Variable(t, arg->name.data, arg->type.dimension); - int dir = convert_direction(arg->direction.data); - if (dir == OUT_PARAMETER && arg->type.dimension != 0) { - IfStatement* checklen = new IfStatement(); - checklen->expression = new Comparison(v, "==", NULL_VALUE); - checklen->statements->Add(new MethodCall(_data, "writeInt", 1, - new LiteralExpression("-1"))); - checklen->elseif = new IfStatement(); - checklen->elseif->statements->Add(new MethodCall(_data, "writeInt", - 1, new FieldVariable(v, "length"))); - tryStatement->statements->Add(checklen); - } - else if (dir & IN_PARAMETER) { - generate_write_to_parcel(t, tryStatement->statements, v, _data, 0); - } - arg = arg->next; - } - - // the transact call - MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4, - new LiteralExpression("Stub." + transactCodeName), - _data, _reply ? _reply : NULL_VALUE, - new LiteralExpression( - oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")); - tryStatement->statements->Add(call); - - // throw back exceptions. - if (_reply) { - MethodCall* ex = new MethodCall(_reply, "readException", 0); - tryStatement->statements->Add(ex); - } - - // returning and cleanup - if (_reply != NULL) { - if (_result != NULL) { - generate_create_from_parcel(proxy->returnType, - tryStatement->statements, _result, _reply, &cl); - } - - // the out/inout parameters - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = new Variable(t, arg->name.data, arg->type.dimension); - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - generate_read_from_parcel(t, tryStatement->statements, - v, _reply, &cl); - } - arg = arg->next; - } - - finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); - } - finallyStatement->statements->Add(new MethodCall(_data, "recycle")); - - if (_result != NULL) { - proxy->statements->Add(new ReturnStatement(_result)); - } -} - -static void -generate_interface_descriptors(StubClass* stub, ProxyClass* proxy) -{ - // the interface descriptor transaction handler - Case* c = new Case("INTERFACE_TRANSACTION"); - c->statements->Add(new MethodCall(stub->transact_reply, "writeString", - 1, new LiteralExpression("DESCRIPTOR"))); - c->statements->Add(new ReturnStatement(TRUE_VALUE)); - stub->transact_switch->cases.push_back(c); - - // and the proxy-side method returning the descriptor directly - Method* getDesc = new Method; - getDesc->modifiers = PUBLIC; - getDesc->returnType = STRING_TYPE; - getDesc->returnTypeDimension = 0; - getDesc->name = "getInterfaceDescriptor"; - getDesc->statements = new StatementBlock; - getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR"))); - proxy->elements.push_back(getDesc); -} - -Class* -generate_binder_interface_class(const interface_type* iface) -{ - InterfaceType* interfaceType = static_cast<InterfaceType*>( - NAMES.Find(iface->package, iface->name.data)); - - // the interface class - Class* interface = new Class; - interface->comment = gather_comments(iface->comments_token->extra); - interface->modifiers = PUBLIC; - interface->what = Class::INTERFACE; - interface->type = interfaceType; - interface->interfaces.push_back(IINTERFACE_TYPE); - - // the stub inner class - StubClass* stub = new StubClass( - NAMES.Find(iface->package, append(iface->name.data, ".Stub").c_str()), - interfaceType); - interface->elements.push_back(stub); - - // the proxy inner class - ProxyClass* proxy = new ProxyClass( - NAMES.Find(iface->package, - append(iface->name.data, ".Stub.Proxy").c_str()), - interfaceType); - stub->elements.push_back(proxy); - - // stub and proxy support for getInterfaceDescriptor() - generate_interface_descriptors(stub, proxy); - - // all the declared methods of the interface - int index = 0; - interface_item_type* item = iface->interface_items; - while (item != NULL) { - if (item->item_type == METHOD_TYPE) { - method_type * method_item = (method_type*) item; - generate_method(method_item, interface, stub, proxy, method_item->assigned_id); - } - item = item->next; - index++; - } - - return interface; -} - diff --git a/tools/aidl/generate_java_rpc.cpp b/tools/aidl/generate_java_rpc.cpp deleted file mode 100644 index 5e4dacc..0000000 --- a/tools/aidl/generate_java_rpc.cpp +++ /dev/null @@ -1,1001 +0,0 @@ -#include "generate_java.h" -#include "Type.h" -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -Type* SERVICE_CONTEXT_TYPE = new Type("android.content", - "Context", Type::BUILT_IN, false, false, false); -Type* PRESENTER_BASE_TYPE = new Type("android.support.place.connector", - "EventListener", Type::BUILT_IN, false, false, false); -Type* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector", - "EventListener.Listener", Type::BUILT_IN, false, false, false); -Type* RPC_BROKER_TYPE = new Type("android.support.place.connector", "Broker", - Type::BUILT_IN, false, false, false); -Type* RPC_CONTAINER_TYPE = new Type("com.android.athome.connector", "ConnectorContainer", - Type::BUILT_IN, false, false, false); -Type* PLACE_INFO_TYPE = new Type("android.support.place.connector", "PlaceInfo", - Type::BUILT_IN, false, false, false); -// TODO: Just use Endpoint, so this works for all endpoints. -Type* RPC_CONNECTOR_TYPE = new Type("android.support.place.connector", "Connector", - Type::BUILT_IN, false, false, false); -Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc", - "EndpointInfo", true, __FILE__, __LINE__); -Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler", - true, __FILE__, __LINE__); -Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler", - Type::BUILT_IN, false, false, false); -Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.rpc", "RpcContext", true, - __FILE__, __LINE__); - -static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, - Variable* v, Variable* data, Variable** cl); -static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from); -static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, - Variable* data); - -static string -format_int(int n) -{ - char str[20]; - sprintf(str, "%d", n); - return string(str); -} - -static string -class_name_leaf(const string& str) -{ - string::size_type pos = str.rfind('.'); - if (pos == string::npos) { - return str; - } else { - return string(str, pos+1); - } -} - -static string -results_class_name(const string& n) -{ - string str = n; - str[0] = toupper(str[0]); - str.insert(0, "On"); - return str; -} - -static string -results_method_name(const string& n) -{ - string str = n; - str[0] = toupper(str[0]); - str.insert(0, "on"); - return str; -} - -static string -push_method_name(const string& n) -{ - string str = n; - str[0] = toupper(str[0]); - str.insert(0, "push"); - return str; -} - -// ================================================= -class DispatcherClass : public Class -{ -public: - DispatcherClass(const interface_type* iface, Expression* target); - virtual ~DispatcherClass(); - - void AddMethod(const method_type* method); - void DoneWithMethods(); - - Method* processMethod; - Variable* actionParam; - Variable* requestParam; - Variable* rpcContextParam; - Variable* errorParam; - Variable* requestData; - Variable* resultData; - IfStatement* dispatchIfStatement; - Expression* targetExpression; - -private: - void generate_process(); -}; - -DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target) - :Class(), - dispatchIfStatement(NULL), - targetExpression(target) -{ - generate_process(); -} - -DispatcherClass::~DispatcherClass() -{ -} - -void -DispatcherClass::generate_process() -{ - // byte[] process(String action, byte[] params, RpcContext context, RpcError status) - this->processMethod = new Method; - this->processMethod->modifiers = PUBLIC; - this->processMethod->returnType = BYTE_TYPE; - this->processMethod->returnTypeDimension = 1; - this->processMethod->name = "process"; - this->processMethod->statements = new StatementBlock; - - this->actionParam = new Variable(STRING_TYPE, "action"); - this->processMethod->parameters.push_back(this->actionParam); - - this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1); - this->processMethod->parameters.push_back(this->requestParam); - - this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0); - this->processMethod->parameters.push_back(this->rpcContextParam); - - this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0); - this->processMethod->parameters.push_back(this->errorParam); - - this->requestData = new Variable(RPC_DATA_TYPE, "request"); - this->processMethod->statements->Add(new VariableDeclaration(requestData, - new NewExpression(RPC_DATA_TYPE, 1, this->requestParam))); - - this->resultData = new Variable(RPC_DATA_TYPE, "resultData"); - this->processMethod->statements->Add(new VariableDeclaration(this->resultData, - NULL_VALUE)); -} - -void -DispatcherClass::AddMethod(const method_type* method) -{ - arg_type* arg; - - // The if/switch statement - IfStatement* ifs = new IfStatement(); - ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals", - 1, this->actionParam); - StatementBlock* block = ifs->statements = new StatementBlock; - if (this->dispatchIfStatement == NULL) { - this->dispatchIfStatement = ifs; - this->processMethod->statements->Add(dispatchIfStatement); - } else { - this->dispatchIfStatement->elseif = ifs; - this->dispatchIfStatement = ifs; - } - - // The call to decl (from above) - MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data); - - // args - Variable* classLoader = NULL; - VariableFactory stubArgs("_arg"); - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(t); - v->dimension = arg->type.dimension; - - // Unmarshall the parameter - block->Add(new VariableDeclaration(v)); - if (convert_direction(arg->direction.data) & IN_PARAMETER) { - generate_create_from_data(t, block, arg->name.data, v, - this->requestData, &classLoader); - } else { - if (arg->type.dimension == 0) { - block->Add(new Assignment(v, new NewExpression(v->type))); - } - else if (arg->type.dimension == 1) { - generate_new_array(v->type, block, v, this->requestData); - } - else { - fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, - __LINE__); - } - } - - // Add that parameter to the method call - realCall->arguments.push_back(v); - - arg = arg->next; - } - - // Add a final parameter: RpcContext. Contains data about - // incoming request (e.g., certificate) - realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); - - Type* returnType = NAMES.Search(method->type.type.data); - if (returnType == EVENT_FAKE_TYPE) { - returnType = VOID_TYPE; - } - - // the real call - bool first = true; - Variable* _result = NULL; - if (returnType == VOID_TYPE) { - block->Add(realCall); - } else { - _result = new Variable(returnType, "_result", - method->type.dimension); - block->Add(new VariableDeclaration(_result, realCall)); - - // need the result RpcData - if (first) { - block->Add(new Assignment(this->resultData, - new NewExpression(RPC_DATA_TYPE))); - first = false; - } - - // marshall the return value - generate_write_to_data(returnType, block, - new StringLiteralExpression("_result"), _result, this->resultData); - } - - // out parameters - int i = 0; - arg = method->args; - while (arg != NULL) { - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(i++); - - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - // need the result RpcData - if (first) { - block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE))); - first = false; - } - - generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data), - v, this->resultData); - } - - arg = arg->next; - } -} - -void -DispatcherClass::DoneWithMethods() -{ - if (this->dispatchIfStatement == NULL) { - return; - } - - this->elements.push_back(this->processMethod); - - IfStatement* fallthrough = new IfStatement(); - fallthrough->statements = new StatementBlock; - fallthrough->statements->Add(new ReturnStatement( - new MethodCall(SUPER_VALUE, "process", 4, - this->actionParam, this->requestParam, - this->rpcContextParam, - this->errorParam))); - this->dispatchIfStatement->elseif = fallthrough; - IfStatement* s = new IfStatement; - s->statements = new StatementBlock; - this->processMethod->statements->Add(s); - s->expression = new Comparison(this->resultData, "!=", NULL_VALUE); - s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize"))); - s->elseif = new IfStatement; - s = s->elseif; - s->statements->Add(new ReturnStatement(NULL_VALUE)); -} - -// ================================================= -class RpcProxyClass : public Class -{ -public: - RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType); - virtual ~RpcProxyClass(); - - Variable* endpoint; - Variable* broker; - -private: - void generate_ctor(); - void generate_get_endpoint_info(); -}; - -RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType) - :Class() -{ - this->comment = gather_comments(iface->comments_token->extra); - this->modifiers = PUBLIC; - this->what = Class::CLASS; - this->type = interfaceType; - - // broker - this->broker = new Variable(RPC_BROKER_TYPE, "_broker"); - this->elements.push_back(new Field(PRIVATE, this->broker)); - // endpoint - this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint"); - this->elements.push_back(new Field(PRIVATE, this->endpoint)); - - // methods - generate_ctor(); - generate_get_endpoint_info(); -} - -RpcProxyClass::~RpcProxyClass() -{ -} - -void -RpcProxyClass::generate_ctor() -{ - Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); - Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint"); - Method* ctor = new Method; - ctor->modifiers = PUBLIC; - ctor->name = class_name_leaf(this->type->Name()); - ctor->statements = new StatementBlock; - ctor->parameters.push_back(broker); - ctor->parameters.push_back(endpoint); - this->elements.push_back(ctor); - - ctor->statements->Add(new Assignment(this->broker, broker)); - ctor->statements->Add(new Assignment(this->endpoint, endpoint)); -} - -void -RpcProxyClass::generate_get_endpoint_info() -{ - Method* get = new Method; - get->modifiers = PUBLIC; - get->returnType = RPC_ENDPOINT_INFO_TYPE; - get->name = "getEndpointInfo"; - get->statements = new StatementBlock; - this->elements.push_back(get); - - get->statements->Add(new ReturnStatement(this->endpoint)); -} - -// ================================================= -class EventListenerClass : public DispatcherClass -{ -public: - EventListenerClass(const interface_type* iface, Type* listenerType); - virtual ~EventListenerClass(); - - Variable* _listener; - -private: - void generate_ctor(); -}; - -Expression* -generate_get_listener_expression(Type* cast) -{ - return new Cast(cast, new MethodCall(THIS_VALUE, "getView")); -} - -EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType) - :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener")) -{ - this->modifiers = PRIVATE; - this->what = Class::CLASS; - this->type = new Type(iface->package ? iface->package : "", - append(iface->name.data, ".Presenter"), - Type::GENERATED, false, false, false); - this->extends = PRESENTER_BASE_TYPE; - - this->_listener = new Variable(listenerType, "_listener"); - this->elements.push_back(new Field(PRIVATE, this->_listener)); - - // methods - generate_ctor(); -} - -EventListenerClass::~EventListenerClass() -{ -} - -void -EventListenerClass::generate_ctor() -{ - Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); - Variable* listener = new Variable(this->_listener->type, "listener"); - Method* ctor = new Method; - ctor->modifiers = PUBLIC; - ctor->name = class_name_leaf(this->type->Name()); - ctor->statements = new StatementBlock; - ctor->parameters.push_back(broker); - ctor->parameters.push_back(listener); - this->elements.push_back(ctor); - - ctor->statements->Add(new MethodCall("super", 2, broker, listener)); - ctor->statements->Add(new Assignment(this->_listener, listener)); -} - -// ================================================= -class ListenerClass : public Class -{ -public: - ListenerClass(const interface_type* iface); - virtual ~ListenerClass(); - - bool needed; - -private: - void generate_ctor(); -}; - -ListenerClass::ListenerClass(const interface_type* iface) - :Class(), - needed(false) -{ - this->comment = "/** Extend this to listen to the events from this class. */"; - this->modifiers = STATIC | PUBLIC ; - this->what = Class::CLASS; - this->type = new Type(iface->package ? iface->package : "", - append(iface->name.data, ".Listener"), - Type::GENERATED, false, false, false); - this->extends = PRESENTER_LISTENER_BASE_TYPE; -} - -ListenerClass::~ListenerClass() -{ -} - -// ================================================= -class EndpointBaseClass : public DispatcherClass -{ -public: - EndpointBaseClass(const interface_type* iface); - virtual ~EndpointBaseClass(); - - bool needed; - -private: - void generate_ctor(); -}; - -EndpointBaseClass::EndpointBaseClass(const interface_type* iface) - :DispatcherClass(iface, THIS_VALUE), - needed(false) -{ - this->comment = "/** Extend this to implement a link service. */"; - this->modifiers = STATIC | PUBLIC | ABSTRACT; - this->what = Class::CLASS; - this->type = new Type(iface->package ? iface->package : "", - append(iface->name.data, ".EndpointBase"), - Type::GENERATED, false, false, false); - this->extends = RPC_CONNECTOR_TYPE; - - // methods - generate_ctor(); -} - -EndpointBaseClass::~EndpointBaseClass() -{ -} - -void -EndpointBaseClass::generate_ctor() -{ - Variable* container = new Variable(RPC_CONTAINER_TYPE, "container"); - Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); - Variable* place = new Variable(PLACE_INFO_TYPE, "placeInfo"); - Method* ctor = new Method; - ctor->modifiers = PUBLIC; - ctor->name = class_name_leaf(this->type->Name()); - ctor->statements = new StatementBlock; - ctor->parameters.push_back(container); - ctor->parameters.push_back(broker); - ctor->parameters.push_back(place); - this->elements.push_back(ctor); - - ctor->statements->Add(new MethodCall("super", 3, container, broker, place)); -} - -// ================================================= -class ResultDispatcherClass : public Class -{ -public: - ResultDispatcherClass(); - virtual ~ResultDispatcherClass(); - - void AddMethod(int index, const string& name, Method** method, Variable** param); - - bool needed; - Variable* methodId; - Variable* callback; - Method* onResultMethod; - Variable* resultParam; - SwitchStatement* methodSwitch; - -private: - void generate_ctor(); - void generate_onResult(); -}; - -ResultDispatcherClass::ResultDispatcherClass() - :Class(), - needed(false) -{ - this->modifiers = PRIVATE | FINAL; - this->what = Class::CLASS; - this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false); - this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE); - - // methodId - this->methodId = new Variable(INT_TYPE, "methodId"); - this->elements.push_back(new Field(PRIVATE, this->methodId)); - this->callback = new Variable(OBJECT_TYPE, "callback"); - this->elements.push_back(new Field(PRIVATE, this->callback)); - - // methods - generate_ctor(); - generate_onResult(); -} - -ResultDispatcherClass::~ResultDispatcherClass() -{ -} - -void -ResultDispatcherClass::generate_ctor() -{ - Variable* methodIdParam = new Variable(INT_TYPE, "methId"); - Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj"); - Method* ctor = new Method; - ctor->modifiers = PUBLIC; - ctor->name = class_name_leaf(this->type->Name()); - ctor->statements = new StatementBlock; - ctor->parameters.push_back(methodIdParam); - ctor->parameters.push_back(callbackParam); - this->elements.push_back(ctor); - - ctor->statements->Add(new Assignment(this->methodId, methodIdParam)); - ctor->statements->Add(new Assignment(this->callback, callbackParam)); -} - -void -ResultDispatcherClass::generate_onResult() -{ - this->onResultMethod = new Method; - this->onResultMethod->modifiers = PUBLIC; - this->onResultMethod->returnType = VOID_TYPE; - this->onResultMethod->returnTypeDimension = 0; - this->onResultMethod->name = "onResult"; - this->onResultMethod->statements = new StatementBlock; - this->elements.push_back(this->onResultMethod); - - this->resultParam = new Variable(BYTE_TYPE, "result", 1); - this->onResultMethod->parameters.push_back(this->resultParam); - - this->methodSwitch = new SwitchStatement(this->methodId); - this->onResultMethod->statements->Add(this->methodSwitch); -} - -void -ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param) -{ - Method* m = new Method; - m->modifiers = PUBLIC; - m->returnType = VOID_TYPE; - m->returnTypeDimension = 0; - m->name = name; - m->statements = new StatementBlock; - *param = new Variable(BYTE_TYPE, "result", 1); - m->parameters.push_back(*param); - this->elements.push_back(m); - *method = m; - - Case* c = new Case(format_int(index)); - c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam)); - c->statements->Add(new Break()); - - this->methodSwitch->cases.push_back(c); -} - -// ================================================= -static void -generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from) -{ - fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__); - exit(1); -} - -static void -generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v, - Variable* data, Variable** cl) -{ - Expression* k = new StringLiteralExpression(key); - if (v->dimension == 0) { - t->CreateFromRpcData(addTo, k, v, data, cl); - } - if (v->dimension == 1) { - //t->ReadArrayFromRpcData(addTo, v, data, cl); - fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n", - __FILE__, __LINE__); - } -} - -static void -generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data) -{ - if (v->dimension == 0) { - t->WriteToRpcData(addTo, k, v, data, 0); - } - if (v->dimension == 1) { - //t->WriteArrayToParcel(addTo, v, data); - fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n", - __FILE__, __LINE__); - } -} - -// ================================================= -static Type* -generate_results_method(const method_type* method, RpcProxyClass* proxyClass) -{ - arg_type* arg; - - string resultsMethodName = results_method_name(method->name.data); - Type* resultsInterfaceType = new Type(results_class_name(method->name.data), - Type::GENERATED, false, false, false); - - if (!method->oneway) { - Class* resultsClass = new Class; - resultsClass->modifiers = STATIC | PUBLIC; - resultsClass->what = Class::INTERFACE; - resultsClass->type = resultsInterfaceType; - - Method* resultMethod = new Method; - resultMethod->comment = gather_comments(method->comments_token->extra); - resultMethod->modifiers = PUBLIC; - resultMethod->returnType = VOID_TYPE; - resultMethod->returnTypeDimension = 0; - resultMethod->name = resultsMethodName; - if (0 != strcmp("void", method->type.type.data)) { - resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data), - "_result", method->type.dimension)); - } - arg = method->args; - while (arg != NULL) { - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - resultMethod->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - } - arg = arg->next; - } - resultsClass->elements.push_back(resultMethod); - - if (resultMethod->parameters.size() > 0) { - proxyClass->elements.push_back(resultsClass); - return resultsInterfaceType; - } - } - //delete resultsInterfaceType; - return NULL; -} - -static void -generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass, - ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) -{ - arg_type* arg; - Method* proxyMethod = new Method; - proxyMethod->comment = gather_comments(method->comments_token->extra); - proxyMethod->modifiers = PUBLIC; - proxyMethod->returnType = VOID_TYPE; - proxyMethod->returnTypeDimension = 0; - proxyMethod->name = method->name.data; - proxyMethod->statements = new StatementBlock; - proxyClass->elements.push_back(proxyMethod); - - // The local variables - Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); - proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); - - // Add the arguments - arg = method->args; - while (arg != NULL) { - if (convert_direction(arg->direction.data) & IN_PARAMETER) { - // Function signature - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = new Variable(t, arg->name.data, arg->type.dimension); - proxyMethod->parameters.push_back(v); - - // Input parameter marshalling - generate_write_to_data(t, proxyMethod->statements, - new StringLiteralExpression(arg->name.data), v, _data); - } - arg = arg->next; - } - - // If there is a results interface for this class - Expression* resultParameter; - if (resultsInterfaceType != NULL) { - // Result interface parameter - Variable* resultListener = new Variable(resultsInterfaceType, "_result"); - proxyMethod->parameters.push_back(resultListener); - - // Add the results dispatcher callback - resultsDispatcherClass->needed = true; - resultParameter = new NewExpression(resultsDispatcherClass->type, 2, - new LiteralExpression(format_int(index)), resultListener); - } else { - resultParameter = NULL_VALUE; - } - - // All proxy methods take an error parameter - Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors"); - proxyMethod->parameters.push_back(errorListener); - - // Call the broker - proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"), - "sendRpc", 5, - proxyClass->endpoint, - new StringLiteralExpression(method->name.data), - new MethodCall(_data, "serialize"), - resultParameter, - errorListener)); -} - -static void -generate_result_dispatcher_method(const method_type* method, - ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) -{ - arg_type* arg; - Method* dispatchMethod; - Variable* dispatchParam; - resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam); - - Variable* classLoader = NULL; - Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData"); - dispatchMethod->statements->Add(new VariableDeclaration(resultData, - new NewExpression(RPC_DATA_TYPE, 1, dispatchParam))); - - // The callback method itself - MethodCall* realCall = new MethodCall( - new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")), - results_method_name(method->name.data)); - - // The return value - { - Type* t = NAMES.Search(method->type.type.data); - if (t != VOID_TYPE) { - Variable* rv = new Variable(t, "rv"); - dispatchMethod->statements->Add(new VariableDeclaration(rv)); - generate_create_from_data(t, dispatchMethod->statements, "_result", rv, - resultData, &classLoader); - realCall->arguments.push_back(rv); - } - } - - VariableFactory stubArgs("arg"); - arg = method->args; - while (arg != NULL) { - if (convert_direction(arg->direction.data) & OUT_PARAMETER) { - // Unmarshall the results - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = stubArgs.Get(t); - dispatchMethod->statements->Add(new VariableDeclaration(v)); - - generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v, - resultData, &classLoader); - - // Add the argument to the callback - realCall->arguments.push_back(v); - } - arg = arg->next; - } - - // Call the callback method - IfStatement* ifst = new IfStatement; - ifst->expression = new Comparison(new FieldVariable(THIS_VALUE, "callback"), "!=", NULL_VALUE); - dispatchMethod->statements->Add(ifst); - ifst->statements->Add(realCall); -} - -static void -generate_regular_method(const method_type* method, RpcProxyClass* proxyClass, - EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass, - int index) -{ - arg_type* arg; - - // == the callback interface for results ================================ - // the service base class - Type* resultsInterfaceType = generate_results_method(method, proxyClass); - - // == the method in the proxy class ===================================== - generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index); - - // == the method in the result dispatcher class ========================= - if (resultsInterfaceType != NULL) { - generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType, - index); - } - - // == The abstract method that the service developers implement ========== - Method* decl = new Method; - decl->comment = gather_comments(method->comments_token->extra); - decl->modifiers = PUBLIC | ABSTRACT; - decl->returnType = NAMES.Search(method->type.type.data); - decl->returnTypeDimension = method->type.dimension; - decl->name = method->name.data; - arg = method->args; - while (arg != NULL) { - decl->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - arg = arg->next; - } - - // Add the default RpcContext param to all methods - decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); - - serviceBaseClass->elements.push_back(decl); - - - // == the dispatch method in the service base class ====================== - serviceBaseClass->AddMethod(method); -} - -static void -generate_event_method(const method_type* method, RpcProxyClass* proxyClass, - EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass, - EventListenerClass* presenterClass, int index) -{ - arg_type* arg; - listenerClass->needed = true; - - // == the push method in the service base class ========================= - Method* push = new Method; - push->modifiers = PUBLIC; - push->name = push_method_name(method->name.data); - push->statements = new StatementBlock; - push->returnType = VOID_TYPE; - serviceBaseClass->elements.push_back(push); - - // The local variables - Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); - push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); - - // Add the arguments - arg = method->args; - while (arg != NULL) { - // Function signature - Type* t = NAMES.Search(arg->type.type.data); - Variable* v = new Variable(t, arg->name.data, arg->type.dimension); - push->parameters.push_back(v); - - // Input parameter marshalling - generate_write_to_data(t, push->statements, - new StringLiteralExpression(arg->name.data), v, _data); - - arg = arg->next; - } - - // Send the notifications - push->statements->Add(new MethodCall("pushEvent", 2, - new StringLiteralExpression(method->name.data), - new MethodCall(_data, "serialize"))); - - // == the event callback dispatcher method ==================================== - presenterClass->AddMethod(method); - - // == the event method in the listener base class ===================== - Method* event = new Method; - event->modifiers = PUBLIC; - event->name = method->name.data; - event->statements = new StatementBlock; - event->returnType = VOID_TYPE; - listenerClass->elements.push_back(event); - arg = method->args; - while (arg != NULL) { - event->parameters.push_back(new Variable( - NAMES.Search(arg->type.type.data), arg->name.data, - arg->type.dimension)); - arg = arg->next; - } - - // Add a final parameter: RpcContext. Contains data about - // incoming request (e.g., certificate) - event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); -} - -static void -generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType) -{ - // AndroidAtHomePresenter _presenter; - // void startListening(Listener listener) { - // stopListening(); - // _presenter = new Presenter(_broker, listener); - // _presenter.startListening(_endpoint); - // } - // void stopListening() { - // if (_presenter != null) { - // _presenter.stopListening(); - // } - // } - - Variable* _presenter = new Variable(presenterType, "_presenter"); - proxyClass->elements.push_back(new Field(PRIVATE, _presenter)); - - Variable* listener = new Variable(listenerType, "listener"); - - Method* startListeningMethod = new Method; - startListeningMethod->modifiers = PUBLIC; - startListeningMethod->returnType = VOID_TYPE; - startListeningMethod->name = "startListening"; - startListeningMethod->statements = new StatementBlock; - startListeningMethod->parameters.push_back(listener); - proxyClass->elements.push_back(startListeningMethod); - - startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening")); - startListeningMethod->statements->Add(new Assignment(_presenter, - new NewExpression(presenterType, 2, proxyClass->broker, listener))); - startListeningMethod->statements->Add(new MethodCall(_presenter, - "startListening", 1, proxyClass->endpoint)); - - Method* stopListeningMethod = new Method; - stopListeningMethod->modifiers = PUBLIC; - stopListeningMethod->returnType = VOID_TYPE; - stopListeningMethod->name = "stopListening"; - stopListeningMethod->statements = new StatementBlock; - proxyClass->elements.push_back(stopListeningMethod); - - IfStatement* ifst = new IfStatement; - ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE); - stopListeningMethod->statements->Add(ifst); - - ifst->statements->Add(new MethodCall(_presenter, "stopListening")); - ifst->statements->Add(new Assignment(_presenter, NULL_VALUE)); -} - -Class* -generate_rpc_interface_class(const interface_type* iface) -{ - // the proxy class - InterfaceType* interfaceType = static_cast<InterfaceType*>( - NAMES.Find(iface->package, iface->name.data)); - RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType); - - // the listener class - ListenerClass* listener = new ListenerClass(iface); - - // the presenter class - EventListenerClass* presenter = new EventListenerClass(iface, listener->type); - - // the service base class - EndpointBaseClass* base = new EndpointBaseClass(iface); - proxy->elements.push_back(base); - - // the result dispatcher - ResultDispatcherClass* results = new ResultDispatcherClass(); - - // all the declared methods of the proxy - int index = 0; - interface_item_type* item = iface->interface_items; - while (item != NULL) { - if (item->item_type == METHOD_TYPE) { - if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) { - generate_event_method((method_type*)item, proxy, base, listener, presenter, index); - } else { - generate_regular_method((method_type*)item, proxy, base, results, index); - } - } - item = item->next; - index++; - } - presenter->DoneWithMethods(); - base->DoneWithMethods(); - - // only add this if there are methods with results / out parameters - if (results->needed) { - proxy->elements.push_back(results); - } - if (listener->needed) { - proxy->elements.push_back(listener); - proxy->elements.push_back(presenter); - generate_listener_methods(proxy, presenter->type, listener->type); - } - - return proxy; -} diff --git a/tools/aidl/options.cpp b/tools/aidl/options.cpp deleted file mode 100644 index 7b2daeb..0000000 --- a/tools/aidl/options.cpp +++ /dev/null @@ -1,154 +0,0 @@ - -#include "options.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static int -usage() -{ - fprintf(stderr, - "usage: aidl OPTIONS INPUT [OUTPUT]\n" - " aidl --preprocess OUTPUT INPUT...\n" - "\n" - "OPTIONS:\n" - " -I<DIR> search path for import statements.\n" - " -d<FILE> generate dependency file.\n" - " -a generate dependency file next to the output file with the name based on the input file.\n" - " -p<FILE> file created by --preprocess to import.\n" - " -o<FOLDER> base output folder for generated files.\n" - " -b fail when trying to compile a parcelable.\n" - "\n" - "INPUT:\n" - " An aidl interface file.\n" - "\n" - "OUTPUT:\n" - " The generated interface files.\n" - " If omitted and the -o option is not used, the input filename is used, with the .aidl extension changed to a .java extension.\n" - " If the -o option is used, the generated files will be placed in the base output folder, under their package folder\n" - ); - return 1; -} - -int -parse_options(int argc, const char* const* argv, Options *options) -{ - int i = 1; - - if (argc >= 2 && 0 == strcmp(argv[1], "--preprocess")) { - if (argc < 4) { - return usage(); - } - options->outputFileName = argv[2]; - for (int i=3; i<argc; i++) { - options->filesToPreprocess.push_back(argv[i]); - } - options->task = PREPROCESS_AIDL; - return 0; - } - - options->task = COMPILE_AIDL; - options->failOnParcelable = false; - options->autoDepFile = false; - - // OPTIONS - while (i < argc) { - const char* s = argv[i]; - int len = strlen(s); - if (s[0] == '-') { - if (len > 1) { - // -I<system-import-path> - if (s[1] == 'I') { - if (len > 2) { - options->importPaths.push_back(s+2); - } else { - fprintf(stderr, "-I option (%d) requires a path.\n", i); - return usage(); - } - } - else if (s[1] == 'd') { - if (len > 2) { - options->depFileName = s+2; - } else { - fprintf(stderr, "-d option (%d) requires a file.\n", i); - return usage(); - } - } - else if (s[1] == 'a') { - options->autoDepFile = true; - } - else if (s[1] == 'p') { - if (len > 2) { - options->preprocessedFiles.push_back(s+2); - } else { - fprintf(stderr, "-p option (%d) requires a file.\n", i); - return usage(); - } - } - else if (s[1] == 'o') { - if (len > 2) { - options->outputBaseFolder = s+2; - } else { - fprintf(stderr, "-o option (%d) requires a path.\n", i); - return usage(); - } - } - else if (len == 2 && s[1] == 'b') { - options->failOnParcelable = true; - } - else { - // s[1] is not known - fprintf(stderr, "unknown option (%d): %s\n", i, s); - return usage(); - } - } else { - // len <= 1 - fprintf(stderr, "unknown option (%d): %s\n", i, s); - return usage(); - } - } else { - // s[0] != '-' - break; - } - i++; - } - - // INPUT - if (i < argc) { - options->inputFileName = argv[i]; - i++; - } else { - fprintf(stderr, "INPUT required\n"); - return usage(); - } - - // OUTPUT - if (i < argc) { - options->outputFileName = argv[i]; - i++; - } else if (options->outputBaseFolder.length() == 0) { - // copy input into output and change the extension from .aidl to .java - options->outputFileName = options->inputFileName; - string::size_type pos = options->outputFileName.size()-5; - if (options->outputFileName.compare(pos, 5, ".aidl") == 0) { // 5 = strlen(".aidl") - options->outputFileName.replace(pos, 5, ".java"); // 5 = strlen(".aidl") - } else { - fprintf(stderr, "INPUT is not an .aidl file.\n"); - return usage(); - } - } - - // anything remaining? - if (i != argc) { - fprintf(stderr, "unknown option%s:", (i==argc-1?(const char*)"":(const char*)"s")); - for (; i<argc-1; i++) { - fprintf(stderr, " %s", argv[i]); - } - fprintf(stderr, "\n"); - return usage(); - } - - return 0; -} - diff --git a/tools/aidl/options.h b/tools/aidl/options.h deleted file mode 100644 index 387e37d..0000000 --- a/tools/aidl/options.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef DEVICE_TOOLS_AIDL_H -#define DEVICE_TOOLS_AIDL_H - -#include <string.h> -#include <string> -#include <vector> - -using namespace std; - -enum { - COMPILE_AIDL, - PREPROCESS_AIDL -}; - -// This struct is the parsed version of the command line options -struct Options -{ - int task; - bool failOnParcelable; - vector<string> importPaths; - vector<string> preprocessedFiles; - string inputFileName; - string outputFileName; - string outputBaseFolder; - string depFileName; - bool autoDepFile; - - vector<string> filesToPreprocess; -}; - -// takes the inputs from the command line and fills in the Options struct -// Returns 0 on success, and nonzero on failure. -// It also prints the usage statement on failure. -int parse_options(int argc, const char* const* argv, Options *options); - -#endif // DEVICE_TOOLS_AIDL_H diff --git a/tools/aidl/options_test.cpp b/tools/aidl/options_test.cpp deleted file mode 100644 index bd106ce..0000000 --- a/tools/aidl/options_test.cpp +++ /dev/null @@ -1,291 +0,0 @@ -#include <iostream> -#include "options.h" - -const bool VERBOSE = false; - -using namespace std; - -struct Answer { - const char* argv[8]; - int result; - const char* systemSearchPath[8]; - const char* localSearchPath[8]; - const char* inputFileName; - language_t nativeLanguage; - const char* outputH; - const char* outputCPP; - const char* outputJava; -}; - -bool -match_arrays(const char* const*expected, const vector<string> &got) -{ - int count = 0; - while (expected[count] != NULL) { - count++; - } - if (got.size() != count) { - return false; - } - for (int i=0; i<count; i++) { - if (got[i] != expected[i]) { - return false; - } - } - return true; -} - -void -print_array(const char* prefix, const char* const*expected) -{ - while (*expected) { - cout << prefix << *expected << endl; - expected++; - } -} - -void -print_array(const char* prefix, const vector<string> &got) -{ - size_t count = got.size(); - for (size_t i=0; i<count; i++) { - cout << prefix << got[i] << endl; - } -} - -static int -test(const Answer& answer) -{ - int argc = 0; - while (answer.argv[argc]) { - argc++; - } - - int err = 0; - - Options options; - int result = parse_options(argc, answer.argv, &options); - - // result - if (((bool)result) != ((bool)answer.result)) { - cout << "mismatch: result: got " << result << " expected " << - answer.result << endl; - err = 1; - } - - if (result != 0) { - // if it failed, everything is invalid - return err; - } - - // systemSearchPath - if (!match_arrays(answer.systemSearchPath, options.systemSearchPath)) { - cout << "mismatch: systemSearchPath: got" << endl; - print_array(" ", options.systemSearchPath); - cout << " expected" << endl; - print_array(" ", answer.systemSearchPath); - err = 1; - } - - // localSearchPath - if (!match_arrays(answer.localSearchPath, options.localSearchPath)) { - cout << "mismatch: localSearchPath: got" << endl; - print_array(" ", options.localSearchPath); - cout << " expected" << endl; - print_array(" ", answer.localSearchPath); - err = 1; - } - - // inputFileName - if (answer.inputFileName != options.inputFileName) { - cout << "mismatch: inputFileName: got " << options.inputFileName - << " expected " << answer.inputFileName << endl; - err = 1; - } - - // nativeLanguage - if (answer.nativeLanguage != options.nativeLanguage) { - cout << "mismatch: nativeLanguage: got " << options.nativeLanguage - << " expected " << answer.nativeLanguage << endl; - err = 1; - } - - // outputH - if (answer.outputH != options.outputH) { - cout << "mismatch: outputH: got " << options.outputH - << " expected " << answer.outputH << endl; - err = 1; - } - - // outputCPP - if (answer.outputCPP != options.outputCPP) { - cout << "mismatch: outputCPP: got " << options.outputCPP - << " expected " << answer.outputCPP << endl; - err = 1; - } - - // outputJava - if (answer.outputJava != options.outputJava) { - cout << "mismatch: outputJava: got " << options.outputJava - << " expected " << answer.outputJava << endl; - err = 1; - } - - return err; -} - -const Answer g_tests[] = { - - { - /* argv */ { "test", "-i/moof", "-I/blah", "-Ibleh", "-imoo", "inputFileName.aidl_cpp", NULL, NULL }, - /* result */ 0, - /* systemSearchPath */ { "/blah", "bleh", NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { "/moof", "moo", NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "inputFileName.aidl_cpp", - /* nativeLanguage */ CPP, - /* outputH */ "", - /* outputCPP */ "", - /* outputJava */ "" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-oh", "outputH", NULL, NULL, NULL, NULL }, - /* result */ 0, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "inputFileName.aidl_cpp", - /* nativeLanguage */ CPP, - /* outputH */ "outputH", - /* outputCPP */ "", - /* outputJava */ "" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-ocpp", "outputCPP", NULL, NULL, NULL, NULL }, - /* result */ 0, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "inputFileName.aidl_cpp", - /* nativeLanguage */ CPP, - /* outputH */ "", - /* outputCPP */ "outputCPP", - /* outputJava */ "" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-ojava", "outputJava", NULL, NULL, NULL, NULL }, - /* result */ 0, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "inputFileName.aidl_cpp", - /* nativeLanguage */ CPP, - /* outputH */ "", - /* outputCPP */ "", - /* outputJava */ "outputJava" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-oh", "outputH", "-ocpp", "outputCPP", "-ojava", "outputJava" }, - /* result */ 0, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "inputFileName.aidl_cpp", - /* nativeLanguage */ CPP, - /* outputH */ "outputH", - /* outputCPP */ "outputCPP", - /* outputJava */ "outputJava" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-oh", "outputH", "-oh", "outputH1", NULL, NULL }, - /* result */ 1, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "", - /* nativeLanguage */ CPP, - /* outputH */ "", - /* outputCPP */ "", - /* outputJava */ "" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-ocpp", "outputCPP", "-ocpp", "outputCPP1", NULL, NULL }, - /* result */ 1, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "", - /* nativeLanguage */ CPP, - /* outputH */ "", - /* outputCPP */ "", - /* outputJava */ "" - }, - - { - /* argv */ { "test", "inputFileName.aidl_cpp", "-ojava", "outputJava", "-ojava", "outputJava1", NULL, NULL }, - /* result */ 1, - /* systemSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* localSearchPath */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - /* inputFileName */ "", - /* nativeLanguage */ CPP, - /* outputH */ "", - /* outputCPP */ "", - /* outputJava */ "" - }, - -}; - -int -main(int argc, const char** argv) -{ - const int count = sizeof(g_tests)/sizeof(g_tests[0]); - int matches[count]; - - int result = 0; - for (int i=0; i<count; i++) { - if (VERBOSE) { - cout << endl; - cout << "---------------------------------------------" << endl; - const char* const* p = g_tests[i].argv; - while (*p) { - cout << " " << *p; - p++; - } - cout << endl; - cout << "---------------------------------------------" << endl; - } - matches[i] = test(g_tests[i]); - if (VERBOSE) { - if (0 == matches[i]) { - cout << "passed" << endl; - } else { - cout << "failed" << endl; - } - result |= matches[i]; - } - } - - cout << endl; - cout << "=============================================" << endl; - cout << "options_test summary" << endl; - cout << "=============================================" << endl; - - if (!result) { - cout << "passed" << endl; - } else { - cout << "failed the following tests:" << endl; - for (int i=0; i<count; i++) { - if (matches[i]) { - cout << " "; - const char* const* p = g_tests[i].argv; - while (*p) { - cout << " " << *p; - p++; - } - cout << endl; - } - } - } - - return result; -} - diff --git a/tools/aidl/search_path.cpp b/tools/aidl/search_path.cpp deleted file mode 100644 index ffb6cb2..0000000 --- a/tools/aidl/search_path.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include <unistd.h> -#include "search_path.h" -#include "options.h" -#include <string.h> - -#ifdef HAVE_MS_C_RUNTIME -#include <io.h> -#endif - -static vector<string> g_importPaths; - -void -set_import_paths(const vector<string>& importPaths) -{ - g_importPaths = importPaths; -} - -char* -find_import_file(const char* given) -{ - string expected = given; - - int N = expected.length(); - for (int i=0; i<N; i++) { - char c = expected[i]; - if (c == '.') { - expected[i] = OS_PATH_SEPARATOR; - } - } - expected += ".aidl"; - - vector<string>& paths = g_importPaths; - for (vector<string>::iterator it=paths.begin(); it!=paths.end(); it++) { - string f = *it; - if (f.size() == 0) { - f = "."; - f += OS_PATH_SEPARATOR; - } - else if (f[f.size()-1] != OS_PATH_SEPARATOR) { - f += OS_PATH_SEPARATOR; - } - f.append(expected); - -#ifdef HAVE_MS_C_RUNTIME - /* check that the file exists and is not write-only */ - if (0 == _access(f.c_str(), 0) && /* mode 0=exist */ - 0 == _access(f.c_str(), 4) ) { /* mode 4=readable */ -#else - if (0 == access(f.c_str(), R_OK)) { -#endif - return strdup(f.c_str()); - } - } - - return NULL; -} - diff --git a/tools/aidl/search_path.h b/tools/aidl/search_path.h deleted file mode 100644 index 2bf94b1..0000000 --- a/tools/aidl/search_path.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef DEVICE_TOOLS_AIDL_SEARCH_PATH_H -#define DEVICE_TOOLS_AIDL_SEARCH_PATH_H - -#include <stdio.h> - -#if __cplusplus -#include <vector> -#include <string> -using namespace std; -extern "C" { -#endif - -// returns a FILE* and the char* for the file that it found -// given is the class name we're looking for -char* find_import_file(const char* given); - -#if __cplusplus -}; // extern "C" -void set_import_paths(const vector<string>& importPaths); -#endif - -#endif // DEVICE_TOOLS_AIDL_SEARCH_PATH_H - diff --git a/tools/layoutlib/.gitignore b/tools/layoutlib/.gitignore deleted file mode 100644 index c5e82d7..0000000 --- a/tools/layoutlib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bin
\ No newline at end of file diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk deleted file mode 100644 index 4e73568..0000000 --- a/tools/layoutlib/Android.mk +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (C) 2008 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. -# -LOCAL_PATH := $(my-dir) -include $(CLEAR_VARS) - -# -# Define rules to build temp_layoutlib.jar, which contains a subset of -# the classes in framework.jar. The layoutlib_create tool is used to -# transform the framework jar into the temp_layoutlib jar. -# - -# We need to process the framework classes.jar file, but we can't -# depend directly on it (private vars won't be inherited correctly). -# So, we depend on framework's BUILT file. -built_framework_dep := $(call java-lib-deps,framework-base) -built_framework_classes := $(call java-lib-files,framework-base) - -built_core_dep := $(call java-lib-deps,core) -built_core_classes := $(call java-lib-files,core) - -built_layoutlib_create_jar := $(call intermediates-dir-for, \ - JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar - -# This is mostly a copy of config/host_java_library.mk -LOCAL_MODULE := temp_layoutlib -LOCAL_MODULE_CLASS := JAVA_LIBRARIES -LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX) -LOCAL_IS_HOST_MODULE := true -LOCAL_BUILT_MODULE_STEM := javalib.jar - -####################################### -include $(BUILD_SYSTEM)/base_rules.mk -####################################### - -$(LOCAL_BUILT_MODULE): $(built_core_dep) \ - $(built_framework_dep) \ - $(built_layoutlib_create_jar) - $(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) - - -# -# Include the subdir makefiles. -# -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/layoutlib/README b/tools/layoutlib/README deleted file mode 100644 index 0fea9bd..0000000 --- a/tools/layoutlib/README +++ /dev/null @@ -1,4 +0,0 @@ -Layoutlib is a custom version of the android View framework designed to run inside Eclipse. -The goal of the library is to provide layout rendering in Eclipse that are very very close to their rendering on devices. - -None of the com.android.* or android.* classes in layoutlib run on devices.
\ No newline at end of file diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath deleted file mode 100644 index 3c124d9..0000000 --- a/tools/layoutlib/bridge/.classpath +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry excluding="org/kxml2/io/" kind="src" path="src"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/> - <classpathentry kind="output" path="bin"/> -</classpath> diff --git a/tools/layoutlib/bridge/.project b/tools/layoutlib/bridge/.project deleted file mode 100644 index e36e71b..0000000 --- a/tools/layoutlib/bridge/.project +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>layoutlib_bridge</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/tools/layoutlib/bridge/.settings/README.txt b/tools/layoutlib/bridge/.settings/README.txt deleted file mode 100644 index 9120b20..0000000 --- a/tools/layoutlib/bridge/.settings/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -Copy this in eclipse project as a .settings folder at the root. -This ensure proper compilation compliance and warning/error levels.
\ No newline at end of file diff --git a/tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs b/tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5381a0e..0000000 --- a/tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,93 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullReference=error -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk deleted file mode 100644 index 687a91f..0000000 --- a/tools/layoutlib/bridge/Android.mk +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (C) 2008 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. -# -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_JAVA_RESOURCE_DIRS := resources - - -LOCAL_JAVA_LIBRARIES := \ - kxml2-2.3.0 \ - layoutlib_api-prebuilt \ - tools-common-prebuilt - -LOCAL_STATIC_JAVA_LIBRARIES := \ - temp_layoutlib \ - ninepatch-prebuilt - -LOCAL_MODULE := layoutlib - -include $(BUILD_HOST_JAVA_LIBRARY) - -# Build all sub-directories -include $(call all-makefiles-under,$(LOCAL_PATH)) - diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml deleted file mode 100644 index 7adc5af..0000000 --- a/tools/layoutlib/bridge/resources/bars/action_bar.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android"> - <include layout="@android:layout/action_bar_home" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> -</merge> diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png Binary files differdeleted file mode 100644 index 84e6bc8..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png Binary files differdeleted file mode 100644 index 38e4f45..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png Binary files differdeleted file mode 100644 index bf9f300..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png Binary files differdeleted file mode 100644 index bd44b52..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png Binary files differdeleted file mode 100644 index a4be298..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png Binary files differdeleted file mode 100644 index a00bc5b..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png Binary files differdeleted file mode 100644 index dc3183b..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png Binary files differdeleted file mode 100644 index b07f611..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png Binary files differdeleted file mode 100644 index c629387..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png Binary files differdeleted file mode 100644 index eb7c1a4..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/navigation_bar.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml deleted file mode 100644 index 599ca08..0000000 --- a/tools/layoutlib/bridge/resources/bars/navigation_bar.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content"/> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1"/> -</merge> diff --git a/tools/layoutlib/bridge/resources/bars/status_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml deleted file mode 100644 index d3c492e..0000000 --- a/tools/layoutlib/bridge/resources/bars/status_bar.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginLeft="3dip" - android:layout_marginRight="5dip"/> -</merge> diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml deleted file mode 100644 index 76d78d9..0000000 --- a/tools/layoutlib/bridge/resources/bars/title_bar.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<merge xmlns:android="http://schemas.android.com/apk/res/android"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> -</merge> diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png Binary files differdeleted file mode 100644 index bd60cd6..0000000 --- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png Binary files differdeleted file mode 100644 index c5bc5c9..0000000 --- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png Binary files differdeleted file mode 100644 index f621d9c..0000000 --- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png +++ /dev/null diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java deleted file mode 100644 index b10ec9f..0000000 --- a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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. - */ - -package android.animation; - -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; - -import android.os.Handler; -import android.os.Handler_Delegate; -import android.os.Handler_Delegate.IHandlerCallback; -import android.os.Message; - -import java.util.PriorityQueue; -import java.util.Queue; - -/** - * Abstract animation thread. - * <p/> - * This does not actually start an animation, instead it fakes a looper that will play whatever - * animation is sending messages to its own {@link Handler}. - * <p/> - * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}. - * <p/> - * If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do - * anything. - * - */ -public abstract class AnimationThread extends Thread { - - private static class MessageBundle implements Comparable<MessageBundle> { - final Handler mTarget; - final Message mMessage; - final long mUptimeMillis; - - MessageBundle(Handler target, Message message, long uptimeMillis) { - mTarget = target; - mMessage = message; - mUptimeMillis = uptimeMillis; - } - - @Override - public int compareTo(MessageBundle bundle) { - if (mUptimeMillis < bundle.mUptimeMillis) { - return -1; - } - return 1; - } - } - - private final RenderSessionImpl mSession; - - private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>(); - private final IAnimationListener mListener; - - public AnimationThread(RenderSessionImpl scene, String threadName, - IAnimationListener listener) { - super(threadName); - mSession = scene; - mListener = listener; - } - - public abstract Result preAnimation(); - public abstract void postAnimation(); - - @Override - public void run() { - Bridge.prepareThread(); - try { - /* FIXME: The ANIMATION_FRAME message no longer exists. Instead, the - * animation timing loop is completely based on a Choreographer objects - * that schedules animation and drawing frames. The animation handler is - * no longer even a handler; it is just a Runnable enqueued on the Choreographer. - Handler_Delegate.setCallback(new IHandlerCallback() { - @Override - public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) { - if (msg.what == ValueAnimator.ANIMATION_START || - msg.what == ValueAnimator.ANIMATION_FRAME) { - mQueue.add(new MessageBundle(handler, msg, uptimeMillis)); - } else { - // just ignore. - } - } - }); - */ - - // call out to the pre-animation work, which should start an animation or more. - Result result = preAnimation(); - if (result.isSuccess() == false) { - mListener.done(result); - } - - // loop the animation - RenderSession session = mSession.getSession(); - do { - // check early. - if (mListener.isCanceled()) { - break; - } - - // get the next message. - MessageBundle bundle = mQueue.poll(); - if (bundle == null) { - break; - } - - // sleep enough for this bundle to be on time - long currentTime = System.currentTimeMillis(); - if (currentTime < bundle.mUptimeMillis) { - try { - sleep(bundle.mUptimeMillis - currentTime); - } catch (InterruptedException e) { - // FIXME log/do something/sleep again? - e.printStackTrace(); - } - } - - // check after sleeping. - if (mListener.isCanceled()) { - break; - } - - // ready to do the work, acquire the scene. - result = mSession.acquire(250); - if (result.isSuccess() == false) { - mListener.done(result); - return; - } - - // process the bundle. If the animation is not finished, this will enqueue - // the next message, so mQueue will have another one. - try { - // check after acquiring in case it took a while. - if (mListener.isCanceled()) { - break; - } - - bundle.mTarget.handleMessage(bundle.mMessage); - if (mSession.render(false /*freshRender*/).isSuccess()) { - mListener.onNewFrame(session); - } - } finally { - mSession.release(); - } - } while (mListener.isCanceled() == false && mQueue.size() > 0); - - mListener.done(Status.SUCCESS.createResult()); - - } catch (Throwable throwable) { - // can't use Bridge.getLog() as the exception might be thrown outside - // of an acquire/release block. - mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable)); - - } finally { - postAnimation(); - Handler_Delegate.setCallback(null); - Bridge.cleanupThread(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java deleted file mode 100644 index 7b444aa..0000000 --- a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ - -package android.animation; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.animation.PropertyValuesHolder - * - * Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been - * replaced by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - * The main goal of this class' methods are to provide a native way to access setters and getters - * on some object. In this case we want to default to using Java reflection instead so the native - * methods do nothing. - * - */ -/*package*/ class PropertyValuesHolder_Delegate { - - @LayoutlibDelegate - /*package*/ static int nGetIntMethod(Class<?> targetClass, String methodName) { - // return 0 to force PropertyValuesHolder to use Java reflection. - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nGetFloatMethod(Class<?> targetClass, String methodName) { - // return 0 to force PropertyValuesHolder to use Java reflection. - return 0; - } - - @LayoutlibDelegate - /*package*/ static void nCallIntMethod(Object target, int methodID, int arg) { - // do nothing - } - - @LayoutlibDelegate - /*package*/ static void nCallFloatMethod(Object target, int methodID, float arg) { - // do nothing - } -} diff --git a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java deleted file mode 100644 index aabd3f1..0000000 --- a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - -package android.app; - -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.os.Bundle; - -/** - * Delegate used to provide new implementation of a select few methods of {@link Fragment} - * - * Through the layoutlib_create tool, the original methods of Fragment have been replaced - * by calls to methods of the same name in this delegate class. - * - * The methods being re-implemented are the ones responsible for instantiating Fragment objects. - * Because the classes of these objects are found in the project, these methods need access to - * {@link IProjectCallback} object. They are however static methods, so the callback is set - * before the inflation through {@link #setProjectCallback(IProjectCallback)}. - */ -public class Fragment_Delegate { - - private static IProjectCallback sProjectCallback; - - /** - * Sets the current {@link IProjectCallback} to be used to instantiate classes coming - * from the project being rendered. - */ - public static void setProjectCallback(IProjectCallback projectCallback) { - sProjectCallback = projectCallback; - } - - /** - * Like {@link #instantiate(Context, String, Bundle)} but with a null - * argument Bundle. - */ - @LayoutlibDelegate - /*package*/ static Fragment instantiate(Context context, String fname) { - return instantiate(context, fname, null); - } - - /** - * Create a new instance of a Fragment with the given class name. This is - * the same as calling its empty constructor. - * - * @param context The calling context being used to instantiate the fragment. - * This is currently just used to get its ClassLoader. - * @param fname The class name of the fragment to instantiate. - * @param args Bundle of arguments to supply to the fragment, which it - * can retrieve with {@link #getArguments()}. May be null. - * @return Returns a new fragment instance. - * @throws InstantiationException If there is a failure in instantiating - * the given fragment class. This is a runtime exception; it is not - * normally expected to happen. - */ - @LayoutlibDelegate - /*package*/ static Fragment instantiate(Context context, String fname, Bundle args) { - try { - if (sProjectCallback != null) { - Fragment f = (Fragment) sProjectCallback.loadView(fname, - new Class[0], new Object[0]); - - if (args != null) { - args.setClassLoader(f.getClass().getClassLoader()); - f.mArguments = args; - } - return f; - } - - return null; - } catch (ClassNotFoundException e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (java.lang.InstantiationException e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (IllegalAccessException e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } catch (Exception e) { - throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname - + ": make sure class name exists, is public, and has an" - + " empty constructor that is public", e); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java deleted file mode 100644 index a953918..0000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.content.res; - -import com.android.layoutlib.bridge.Bridge; - -import android.content.res.AssetManager; - -public class BridgeAssetManager extends AssetManager { - - /** - * This initializes the static field {@link AssetManager#mSystem} which is used - * by methods who get a global asset manager using {@link AssetManager#getSystem()}. - * <p/> - * They will end up using our bridge asset manager. - * <p/> - * {@link Bridge} calls this method after setting up a new bridge. - */ - public static AssetManager initSystem() { - if (!(AssetManager.sSystem instanceof BridgeAssetManager)) { - // Note that AssetManager() creates a system AssetManager and we override it - // with our BridgeAssetManager. - AssetManager.sSystem = new BridgeAssetManager(); - AssetManager.sSystem.makeStringBlocks(false); - } - return AssetManager.sSystem; - } - - /** - * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects - * around that would prevent us from unloading the library. - */ - public static void clearSystem() { - AssetManager.sSystem = null; - } - - private BridgeAssetManager() { - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java deleted file mode 100644 index 8794452..0000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.content.res; - -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.ninepatch.NinePatch; -import com.android.resources.ResourceType; -import com.android.util.Pair; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.ViewGroup.LayoutParams; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; - -/** - * - */ -public final class BridgeResources extends Resources { - - private BridgeContext mContext; - private IProjectCallback mProjectCallback; - private boolean[] mPlatformResourceFlag = new boolean[1]; - - /** - * Simpler wrapper around FileInputStream. This is used when the input stream represent - * not a normal bitmap but a nine patch. - * This is useful when the InputStream is created in a method but used in another that needs - * to know whether this is 9-patch or not, such as BitmapFactory. - */ - public class NinePatchInputStream extends FileInputStream { - private boolean mFakeMarkSupport = true; - public NinePatchInputStream(File file) throws FileNotFoundException { - super(file); - } - - @Override - public boolean markSupported() { - if (mFakeMarkSupport) { - // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream. - return true; - } - - return super.markSupported(); - } - - public void disableFakeMarkSupport() { - // disable fake mark support so that in case codec actually try to use them - // we don't lie to them. - mFakeMarkSupport = false; - } - } - - /** - * This initializes the static field {@link Resources#mSystem} which is used - * by methods who get global resources using {@link Resources#getSystem()}. - * <p/> - * They will end up using our bridge resources. - * <p/> - * {@link Bridge} calls this method after setting up a new bridge. - */ - public static Resources initSystem(BridgeContext context, - AssetManager assets, - DisplayMetrics metrics, - Configuration config, - IProjectCallback projectCallback) { - return Resources.mSystem = new BridgeResources(context, - assets, - metrics, - config, - projectCallback); - } - - /** - * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects - * around that would prevent us from unloading the library. - */ - public static void disposeSystem() { - if (Resources.mSystem instanceof BridgeResources) { - ((BridgeResources)(Resources.mSystem)).mContext = null; - ((BridgeResources)(Resources.mSystem)).mProjectCallback = null; - } - Resources.mSystem = null; - } - - private BridgeResources(BridgeContext context, AssetManager assets, DisplayMetrics metrics, - Configuration config, IProjectCallback projectCallback) { - super(assets, metrics, config); - mContext = context; - mProjectCallback = projectCallback; - } - - public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) { - return new BridgeTypedArray(this, mContext, numEntries, platformFile); - } - - private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) { - // first get the String related to this id in the framework - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); - - if (resourceInfo != null) { - platformResFlag_out[0] = true; - String attributeName = resourceInfo.getSecond(); - - return Pair.of(attributeName, mContext.getRenderResources().getFrameworkResource( - resourceInfo.getFirst(), attributeName)); - } - - // didn't find a match in the framework? look in the project. - if (mProjectCallback != null) { - resourceInfo = mProjectCallback.resolveResourceId(id); - - if (resourceInfo != null) { - platformResFlag_out[0] = false; - String attributeName = resourceInfo.getSecond(); - - return Pair.of(attributeName, mContext.getRenderResources().getProjectResource( - resourceInfo.getFirst(), attributeName)); - } - } - - return null; - } - - @Override - public Drawable getDrawable(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - return ResourceHelper.getDrawable(value.getSecond(), mContext); - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public int getColor(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - try { - return ResourceHelper.getColor(value.getSecond().getValue()); - } catch (NumberFormatException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, - null /*data*/); - return 0; - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return 0; - } - - @Override - public ColorStateList getColorStateList(int id) throws NotFoundException { - Pair<String, ResourceValue> resValue = getResourceValue(id, mPlatformResourceFlag); - - if (resValue != null) { - ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(), - mContext); - if (stateList != null) { - return stateList; - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public CharSequence getText(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - return v; - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public XmlResourceParser getLayout(int id) throws NotFoundException { - Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag); - - if (v != null) { - ResourceValue value = v.getSecond(); - XmlPullParser parser = null; - - try { - // check if the current parser can provide us with a custom parser. - if (mPlatformResourceFlag[0] == false) { - parser = mProjectCallback.getParser(value); - } - - // create a new one manually if needed. - if (parser == null) { - File xml = new File(value.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - parser = ParserFactory.create(xml); - } - } - - if (parser != null) { - return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value.getValue(), e, null /*data*/); - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. - } - - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public XmlResourceParser getAnimation(int id) throws NotFoundException { - Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag); - - if (v != null) { - ResourceValue value = v.getSecond(); - XmlPullParser parser = null; - - try { - File xml = new File(value.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - parser = ParserFactory.create(xml); - - return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value.getValue(), e, null /*data*/); - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. - } - - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public TypedArray obtainAttributes(AttributeSet set, int[] attrs) { - return mContext.obtainStyledAttributes(set, attrs); - } - - @Override - public TypedArray obtainTypedArray(int id) throws NotFoundException { - throw new UnsupportedOperationException(); - } - - - @Override - public float getDimension(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - if (v.equals(BridgeConstants.MATCH_PARENT) || - v.equals(BridgeConstants.FILL_PARENT)) { - return LayoutParams.MATCH_PARENT; - } else if (v.equals(BridgeConstants.WRAP_CONTENT)) { - return LayoutParams.WRAP_CONTENT; - } - - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, mTmpValue, true /*requireUnit*/) && - mTmpValue.type == TypedValue.TYPE_DIMENSION) { - return mTmpValue.getDimension(getDisplayMetrics()); - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return 0; - } - - @Override - public int getDimensionPixelOffset(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, mTmpValue, true /*requireUnit*/) && - mTmpValue.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelOffset(mTmpValue.data, - getDisplayMetrics()); - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return 0; - } - - @Override - public int getDimensionPixelSize(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, mTmpValue, true /*requireUnit*/) && - mTmpValue.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelSize(mTmpValue.data, - getDisplayMetrics()); - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return 0; - } - - @Override - public int getInteger(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - int radix = 10; - if (v.startsWith("0x")) { - v = v.substring(2); - radix = 16; - } - try { - return Integer.parseInt(v, radix); - } catch (NumberFormatException e) { - // return exception below - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return 0; - } - - @Override - public boolean getBoolean(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - ResourceValue resValue = value.getSecond(); - - assert resValue != null; - if (resValue != null) { - String v = resValue.getValue(); - if (v != null) { - return Boolean.parseBoolean(v); - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return false; - } - - @Override - public String getResourceEntryName(int resid) throws NotFoundException { - throw new UnsupportedOperationException(); - } - - @Override - public String getResourceName(int resid) throws NotFoundException { - throw new UnsupportedOperationException(); - } - - @Override - public String getResourceTypeName(int resid) throws NotFoundException { - throw new UnsupportedOperationException(); - } - - @Override - public String getString(int id, Object... formatArgs) throws NotFoundException { - String s = getString(id); - if (s != null) { - return String.format(s, formatArgs); - - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public String getString(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null && value.getSecond().getValue() != null) { - return value.getSecond().getValue(); - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public void getValue(int id, TypedValue outValue, boolean resolveRefs) - throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - String v = value.getSecond().getValue(); - - if (v != null) { - if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue, - false /*requireUnit*/)) { - return; - } - - // else it's a string - outValue.type = TypedValue.TYPE_STRING; - outValue.string = v; - return; - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - } - - @Override - public void getValue(String name, TypedValue outValue, boolean resolveRefs) - throws NotFoundException { - throw new UnsupportedOperationException(); - } - - @Override - public XmlResourceParser getXml(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - String v = value.getSecond().getValue(); - - if (v != null) { - // check this is a file - File f = new File(v); - if (f.isFile()) { - try { - XmlPullParser parser = ParserFactory.create(f); - - return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); - } catch (XmlPullParserException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } catch (FileNotFoundException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public XmlResourceParser loadXmlResourceParser(String file, int id, - int assetCookie, String type) throws NotFoundException { - // even though we know the XML file to load directly, we still need to resolve the - // id so that we can know if it's a platform or project resource. - // (mPlatformResouceFlag will get the result and will be used later). - getResourceValue(id, mPlatformResourceFlag); - - File f = new File(file); - try { - XmlPullParser parser = ParserFactory.create(f); - - return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); - } catch (XmlPullParserException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } catch (FileNotFoundException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } - } - - - @Override - public InputStream openRawResource(int id) throws NotFoundException { - Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - - if (value != null) { - String path = value.getSecond().getValue(); - - if (path != null) { - // check this is a file - File f = new File(path); - if (f.isFile()) { - try { - // if it's a nine-patch return a custom input stream so that - // other methods (mainly bitmap factory) can detect it's a 9-patch - // and actually load it as a 9-patch instead of a normal bitmap - if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) { - return new NinePatchInputStream(f); - } - return new FileInputStream(f); - } catch (FileNotFoundException e) { - NotFoundException newE = new NotFoundException(); - newE.initCause(e); - throw newE; - } - } - } - } - - // id was not found or not resolved. Throw a NotFoundException. - throwException(id); - - // this is not used since the method above always throws - return null; - } - - @Override - public InputStream openRawResource(int id, TypedValue value) throws NotFoundException { - getValue(id, value, true); - - String path = value.string.toString(); - - File f = new File(path); - if (f.isFile()) { - try { - // if it's a nine-patch return a custom input stream so that - // other methods (mainly bitmap factory) can detect it's a 9-patch - // and actually load it as a 9-patch instead of a normal bitmap - if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) { - return new NinePatchInputStream(f); - } - return new FileInputStream(f); - } catch (FileNotFoundException e) { - NotFoundException exception = new NotFoundException(); - exception.initCause(e); - throw exception; - } - } - - throw new NotFoundException(); - } - - @Override - public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException { - throw new UnsupportedOperationException(); - } - - /** - * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource type. - * @param id the id of the resource - * @throws NotFoundException - */ - private void throwException(int id) throws NotFoundException { - // first get the String related to this id in the framework - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); - - // if the name is unknown in the framework, get it from the custom view loader. - if (resourceInfo == null && mProjectCallback != null) { - resourceInfo = mProjectCallback.resolveResourceId(id); - } - - String message = null; - if (resourceInfo != null) { - message = String.format( - "Could not find %1$s resource matching value 0x%2$X (resolved name: %3$s) in current configuration.", - resourceInfo.getFirst(), id, resourceInfo.getSecond()); - } else { - message = String.format( - "Could not resolve resource value: 0x%1$X.", id); - } - - throw new NotFoundException(message); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java deleted file mode 100644 index 446d139..0000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.content.res; - -import com.android.ide.common.rendering.api.AttrResourceValue; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.internal.util.XmlUtils; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.resources.ResourceType; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.graphics.drawable.Drawable; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.LayoutInflater_Delegate; -import android.view.ViewGroup.LayoutParams; - -import java.io.File; -import java.util.Arrays; -import java.util.Map; - -/** - * Custom implementation of TypedArray to handle non compiled resources. - */ -public final class BridgeTypedArray extends TypedArray { - - private final BridgeResources mBridgeResources; - private final BridgeContext mContext; - private final boolean mPlatformFile; - - private ResourceValue[] mResourceData; - private String[] mNames; - private boolean[] mIsFramework; - - public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len, - boolean platformFile) { - super(null, null, null, 0); - mBridgeResources = resources; - mContext = context; - mPlatformFile = platformFile; - mResourceData = new ResourceValue[len]; - mNames = new String[len]; - mIsFramework = new boolean[len]; - } - - /** - * A bridge-specific method that sets a value in the type array - * @param index the index of the value in the TypedArray - * @param name the name of the attribute - * @param isFramework whether the attribute is in the android namespace. - * @param value the value of the attribute - */ - public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) { - mResourceData[index] = value; - mNames[index] = name; - mIsFramework[index] = isFramework; - } - - /** - * Seals the array after all calls to {@link #bridgeSetValue(int, String, ResourceValue)} have - * been done. - * <p/>This allows to compute the list of non default values, permitting - * {@link #getIndexCount()} to return the proper value. - */ - public void sealArray() { - // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt - // first count the array size - int count = 0; - for (ResourceValue data : mResourceData) { - if (data != null) { - count++; - } - } - - // allocate the table with an extra to store the size - mIndices = new int[count+1]; - mIndices[0] = count; - - // fill the array with the indices. - int index = 1; - for (int i = 0 ; i < mResourceData.length ; i++) { - if (mResourceData[i] != null) { - mIndices[index++] = i; - } - } - } - - /** - * Return the number of values in this array. - */ - @Override - public int length() { - return mResourceData.length; - } - - /** - * Return the Resources object this array was loaded from. - */ - @Override - public Resources getResources() { - return mBridgeResources; - } - - /** - * Retrieve the styled string value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return CharSequence holding string data. May be styled. Returns - * null if the attribute is not defined. - */ - @Override - public CharSequence getText(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (mResourceData[index] != null) { - // FIXME: handle styled strings! - return mResourceData[index].getValue(); - } - - return null; - } - - /** - * Retrieve the string value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined. - */ - @Override - public String getString(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (mResourceData[index] != null) { - return mResourceData[index].getValue(); - } - - return null; - } - - /** - * Retrieve the boolean value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. - * - * @return Attribute boolean value, or defValue if not defined. - */ - @Override - public boolean getBoolean(int index, boolean defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - String s = mResourceData[index].getValue(); - if (s != null) { - return XmlUtils.convertValueToBoolean(s, defValue); - } - - return defValue; - } - - /** - * Retrieve the integer value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. - * - * @return Attribute int value, or defValue if not defined. - */ - @Override - public int getInt(int index, int defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - String s = mResourceData[index].getValue(); - - if (RenderResources.REFERENCE_NULL.equals(s)) { - return defValue; - } - - if (s == null || s.length() == 0) { - return defValue; - } - - try { - return XmlUtils.convertValueToInt(s, defValue); - } catch (NumberFormatException e) { - // pass - } - - // Field is not null and is not an integer. - // Check for possible constants and try to find them. - // Get the map of attribute-constant -> IntegerValue - Map<String, Integer> map = null; - if (mIsFramework[index]) { - map = Bridge.getEnumValues(mNames[index]); - } else { - // get the styleable matching the resolved name - RenderResources res = mContext.getRenderResources(); - ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]); - if (attr instanceof AttrResourceValue) { - map = ((AttrResourceValue) attr).getAttributeValues(); - } - } - - if (map != null) { - // accumulator to store the value of the 1+ constants. - int result = 0; - - // split the value in case this is a mix of several flags. - String[] keywords = s.split("\\|"); - for (String keyword : keywords) { - Integer i = map.get(keyword.trim()); - if (i != null) { - result |= i.intValue(); - } else { - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%s\" in attribute \"%2$s\" is not a valid value", - keyword, mNames[index]), null /*data*/); - } - } - return result; - } - - return defValue; - } - - /** - * Retrieve the float value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return Attribute float value, or defValue if not defined.. - */ - @Override - public float getFloat(int index, float defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - String s = mResourceData[index].getValue(); - - if (s != null) { - try { - return Float.parseFloat(s); - } catch (NumberFormatException e) { - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%s\" in attribute \"%2$s\" cannot be converted to float.", - s, mNames[index]), null /*data*/); - - // we'll return the default value below. - } - } - return defValue; - } - - /** - * Retrieve the color value for the attribute at <var>index</var>. If - * the attribute references a color resource holding a complex - * {@link android.content.res.ColorStateList}, then the default color from - * the set is returned. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute color value, or defValue if not defined. - */ - @Override - public int getColor(int index, int defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - ColorStateList colorStateList = ResourceHelper.getColorStateList( - mResourceData[index], mContext); - if (colorStateList != null) { - return colorStateList.getDefaultColor(); - } - - return defValue; - } - - /** - * Retrieve the ColorStateList for the attribute at <var>index</var>. - * The value may be either a single solid color or a reference to - * a color or complex {@link android.content.res.ColorStateList} description. - * - * @param index Index of attribute to retrieve. - * - * @return ColorStateList for the attribute, or null if not defined. - */ - @Override - public ColorStateList getColorStateList(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (mResourceData[index] == null) { - return null; - } - - ResourceValue resValue = mResourceData[index]; - String value = resValue.getValue(); - - if (value == null) { - return null; - } - - if (RenderResources.REFERENCE_NULL.equals(value)) { - return null; - } - - // let the framework inflate the ColorStateList from the XML file. - File f = new File(value); - if (f.isFile()) { - try { - XmlPullParser parser = ParserFactory.create(f); - - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - parser, mContext, resValue.isFramework()); - try { - return ColorStateList.createFromXml(mContext.getResources(), blockParser); - } finally { - blockParser.ensurePopped(); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value, e, null /*data*/); - return null; - } catch (Exception e) { - // this is an error and not warning since the file existence is checked before - // attempting to parse it. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed to parse file " + value, e, null /*data*/); - - return null; - } - } - - try { - int color = ResourceHelper.getColor(value); - return ColorStateList.valueOf(color); - } catch (NumberFormatException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/); - } - - return null; - } - - /** - * Retrieve the integer value for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute integer value, or defValue if not defined. - */ - @Override - public int getInteger(int index, int defValue) { - return getInt(index, defValue); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var>. Unit - * conversions are based on the current {@link DisplayMetrics} - * associated with the resources this {@link TypedArray} object - * came from. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric, or defValue if not defined. - * - * @see #getDimensionPixelOffset - * @see #getDimensionPixelSize - */ - @Override - public float getDimension(int index, float defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - String s = mResourceData[index].getValue(); - - if (s == null) { - return defValue; - } else if (s.equals(BridgeConstants.MATCH_PARENT) || - s.equals(BridgeConstants.FILL_PARENT)) { - return LayoutParams.MATCH_PARENT; - } else if (s.equals(BridgeConstants.WRAP_CONTENT)) { - return LayoutParams.WRAP_CONTENT; - } else if (RenderResources.REFERENCE_NULL.equals(s)) { - return defValue; - } - - if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) { - return mValue.getDimension(mBridgeResources.getDisplayMetrics()); - } - - // looks like we were unable to resolve the dimension value - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%1$s\" in attribute \"%2$s\" is not a valid format.", - s, mNames[index]), null /*data*/); - - return defValue; - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var> for use - * as an offset in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for you. An offset conversion involves simply - * truncating the base value to an integer. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. - * - * @see #getDimension - * @see #getDimensionPixelSize - */ - @Override - public int getDimensionPixelOffset(int index, int defValue) { - return (int) getDimension(index, defValue); - } - - /** - * Retrieve a dimensional unit attribute at <var>index</var> for use - * as a size in raw pixels. This is the same as - * {@link #getDimension}, except the returned value is converted to - * integer pixels for use as a size. A size conversion involves - * rounding the base value, and ensuring that a non-zero base value - * is at least one pixel in size. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. - * - * @see #getDimension - * @see #getDimensionPixelOffset - */ - @Override - public int getDimensionPixelSize(int index, int defValue) { - try { - return getDimension(index); - } catch (RuntimeException e) { - if (mResourceData[index] != null) { - String s = mResourceData[index].getValue(); - - if (s != null) { - // looks like we were unable to resolve the dimension value - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%1$s\" in attribute \"%2$s\" is not a valid format.", - s, mNames[index]), null /*data*/); - } - } - - return defValue; - } - } - - /** - * Special version of {@link #getDimensionPixelSize} for retrieving - * {@link android.view.ViewGroup}'s layout_width and layout_height - * attributes. This is only here for performance reasons; applications - * should use {@link #getDimensionPixelSize}. - * - * @param index Index of the attribute to retrieve. - * @param name Textual name of attribute for error reporting. - * - * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels. - */ - @Override - public int getLayoutDimension(int index, String name) { - try { - // this will throw an exception - return getDimension(index); - } catch (RuntimeException e) { - - if (LayoutInflater_Delegate.sIsInInclude) { - throw new RuntimeException(); - } - - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - "You must supply a " + name + " attribute.", null); - - return 0; - } - } - - @Override - public int getLayoutDimension(int index, int defValue) { - return getDimensionPixelSize(index, defValue); - } - - private int getDimension(int index) { - if (mResourceData[index] == null) { - throw new RuntimeException(); - } - - String s = mResourceData[index].getValue(); - - if (s == null) { - throw new RuntimeException(); - } else if (s.equals(BridgeConstants.MATCH_PARENT) || - s.equals(BridgeConstants.FILL_PARENT)) { - return LayoutParams.MATCH_PARENT; - } else if (s.equals(BridgeConstants.WRAP_CONTENT)) { - return LayoutParams.WRAP_CONTENT; - } else if (RenderResources.REFERENCE_NULL.equals(s)) { - throw new RuntimeException(); - } - - if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) { - float f = mValue.getDimension(mBridgeResources.getDisplayMetrics()); - - final int res = (int)(f+0.5f); - if (res != 0) return res; - if (f == 0) return 0; - if (f > 0) return 1; - } - - throw new RuntimeException(); - } - - /** - * Retrieve a fractional unit attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param base The base value of this fraction. In other words, a - * standard fraction is multiplied by this value. - * @param pbase The parent base value of this fraction. In other - * words, a parent fraction (nn%p) is multiplied by this - * value. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute fractional value multiplied by the appropriate - * base value, or defValue if not defined. - */ - @Override - public float getFraction(int index, int base, int pbase, float defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - if (mResourceData[index] == null) { - return defValue; - } - - String value = mResourceData[index].getValue(); - if (value == null) { - return defValue; - } - - if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, - false /*requireUnit*/)) { - return mValue.getFraction(base, pbase); - } - - // looks like we were unable to resolve the fraction value - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.", - value, mNames[index]), null /*data*/); - - return defValue; - } - - /** - * Retrieve the resource identifier for the attribute at - * <var>index</var>. Note that attribute resource as resolved when - * the overall {@link TypedArray} object is retrieved. As a - * result, this function will return the resource identifier of the - * final resource value that was found, <em>not</em> necessarily the - * original resource that was specified by the attribute. - * - * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined or - * not a resource. - * - * @return Attribute resource identifier, or defValue if not defined. - */ - @Override - public int getResourceId(int index, int defValue) { - if (index < 0 || index >= mResourceData.length) { - return defValue; - } - - // get the Resource for this index - ResourceValue resValue = mResourceData[index]; - - // no data, return the default value. - if (resValue == null) { - return defValue; - } - - // check if this is a style resource - if (resValue instanceof StyleResourceValue) { - // get the id that will represent this style. - return mContext.getDynamicIdByStyle((StyleResourceValue)resValue); - } - - if (RenderResources.REFERENCE_NULL.equals(resValue.getValue())) { - return defValue; - } - - // if the attribute was a reference to a resource, and not a declaration of an id (@+id), - // then the xml attribute value was "resolved" which leads us to a ResourceValue with a - // valid getType() and getName() returning a resource name. - // (and getValue() returning null!). We need to handle this! - if (resValue.getResourceType() != null) { - // if this is a framework id - if (mPlatformFile || resValue.isFramework()) { - // look for idName in the android R classes - return mContext.getFrameworkResourceValue( - resValue.getResourceType(), resValue.getName(), defValue); - } - - // look for idName in the project R class. - return mContext.getProjectResourceValue( - resValue.getResourceType(), resValue.getName(), defValue); - } - - // else, try to get the value, and resolve it somehow. - String value = resValue.getValue(); - if (value == null) { - return defValue; - } - - // if the value is just an integer, return it. - try { - int i = Integer.parseInt(value); - if (Integer.toString(i).equals(value)) { - return i; - } - } catch (NumberFormatException e) { - // pass - } - - // Handle the @id/<name>, @+id/<name> and @android:id/<name> - // We need to return the exact value that was compiled (from the various R classes), - // as these values can be reused internally with calls to findViewById(). - // There's a trick with platform layouts that not use "android:" but their IDs are in - // fact in the android.R and com.android.internal.R classes. - // The field mPlatformFile will indicate that all IDs are to be looked up in the android R - // classes exclusively. - - // if this is a reference to an id, find it. - if (value.startsWith("@id/") || value.startsWith("@+") || - value.startsWith("@android:id/")) { - - int pos = value.indexOf('/'); - String idName = value.substring(pos + 1); - - // if this is a framework id - if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) { - // look for idName in the android R classes - return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue); - } - - // look for idName in the project R class. - return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue); - } - - // not a direct id valid reference? resolve it - Integer idValue = null; - - if (resValue.isFramework()) { - idValue = Bridge.getResourceId(resValue.getResourceType(), - resValue.getName()); - } else { - idValue = mContext.getProjectCallback().getResourceId( - resValue.getResourceType(), resValue.getName()); - } - - if (idValue != null) { - return idValue.intValue(); - } - - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE, - String.format( - "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]), - resValue); - - return defValue; - } - - /** - * Retrieve the Drawable for the attribute at <var>index</var>. This - * gets the resource ID of the selected attribute, and uses - * {@link Resources#getDrawable Resources.getDrawable} of the owning - * Resources object to retrieve its Drawable. - * - * @param index Index of attribute to retrieve. - * - * @return Drawable for the attribute, or null if not defined. - */ - @Override - public Drawable getDrawable(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (mResourceData[index] == null) { - return null; - } - - ResourceValue value = mResourceData[index]; - String stringValue = value.getValue(); - if (stringValue == null || RenderResources.REFERENCE_NULL.equals(stringValue)) { - return null; - } - - return ResourceHelper.getDrawable(value, mContext); - } - - - /** - * Retrieve the CharSequence[] for the attribute at <var>index</var>. - * This gets the resource ID of the selected attribute, and uses - * {@link Resources#getTextArray Resources.getTextArray} of the owning - * Resources object to retrieve its String[]. - * - * @param index Index of attribute to retrieve. - * - * @return CharSequence[] for the attribute, or null if not defined. - */ - @Override - public CharSequence[] getTextArray(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (mResourceData[index] == null) { - return null; - } - - String value = mResourceData[index].getValue(); - if (value != null) { - if (RenderResources.REFERENCE_NULL.equals(value)) { - return null; - } - - return new CharSequence[] { value }; - } - - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - String.format("Unknown value for getTextArray(%d) => %s", //DEBUG - index, mResourceData[index].getName())), null /*data*/); - - return null; - } - - /** - * Retrieve the raw TypedValue for the attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * @param outValue TypedValue object in which to place the attribute's - * data. - * - * @return Returns true if the value was retrieved, else false. - */ - @Override - public boolean getValue(int index, TypedValue outValue) { - if (index < 0 || index >= mResourceData.length) { - return false; - } - - if (mResourceData[index] == null) { - return false; - } - - String s = mResourceData[index].getValue(); - - return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, - false /*requireUnit*/); - } - - /** - * Determines whether there is an attribute at <var>index</var>. - * - * @param index Index of attribute to retrieve. - * - * @return True if the attribute has a value, false otherwise. - */ - @Override - public boolean hasValue(int index) { - if (index < 0 || index >= mResourceData.length) { - return false; - } - - return mResourceData[index] != null; - } - - /** - * Retrieve the raw TypedValue for the attribute at <var>index</var> - * and return a temporary object holding its data. This object is only - * valid until the next call on to {@link TypedArray}. - * - * @param index Index of attribute to retrieve. - * - * @return Returns a TypedValue object if the attribute is defined, - * containing its data; otherwise returns null. (You will not - * receive a TypedValue whose type is TYPE_NULL.) - */ - @Override - public TypedValue peekValue(int index) { - if (index < 0 || index >= mResourceData.length) { - return null; - } - - if (getValue(index, mValue)) { - return mValue; - } - - return null; - } - - /** - * Returns a message about the parser state suitable for printing error messages. - */ - @Override - public String getPositionDescription() { - return "<internal -- stub if needed>"; - } - - /** - * Give back a previously retrieved TypedArray, for later re-use. - */ - @Override - public void recycle() { - // pass - } - - @Override - public String toString() { - return Arrays.toString(mResourceData); - } - } diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java deleted file mode 100644 index c9d615c..0000000 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.content.res; - -import com.android.layoutlib.bridge.impl.RenderSessionImpl; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.res.Resources.NotFoundException; -import android.content.res.Resources.Theme; -import android.util.AttributeSet; -import android.util.TypedValue; - -/** - * Delegate used to provide new implementation of a select few methods of {@link Resources$Theme} - * - * Through the layoutlib_create tool, the original methods of Theme have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class Resources_Theme_Delegate { - - @LayoutlibDelegate - /*package*/ static TypedArray obtainStyledAttributes( - Resources thisResources, Theme thisTheme, - int[] attrs) { - return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs); - } - - @LayoutlibDelegate - /*package*/ static TypedArray obtainStyledAttributes( - Resources thisResources, Theme thisTheme, - int resid, int[] attrs) - throws NotFoundException { - return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs); - } - - @LayoutlibDelegate - /*package*/ static TypedArray obtainStyledAttributes( - Resources thisResources, Theme thisTheme, - AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { - return RenderSessionImpl.getCurrentContext().obtainStyledAttributes( - set, attrs, defStyleAttr, defStyleRes); - } - - @LayoutlibDelegate - /*package*/ static boolean resolveAttribute( - Resources thisResources, Theme thisTheme, - int resid, TypedValue outValue, - boolean resolveRefs) { - return RenderSessionImpl.getCurrentContext().resolveThemeAttribute( - resid, outValue, resolveRefs); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java deleted file mode 100644 index 0a7899a..0000000 --- a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.content.res; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.util.TypedValue; - -public class TypedArray_Delegate { - - @LayoutlibDelegate - public static boolean getValueAt(TypedArray theTypedArray, int index, TypedValue outValue) { - // pass - return false; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java deleted file mode 100644 index a50a2bd..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Composite; - -/** - * Delegate implementing the native methods of android.graphics.AvoidXfermode - * - * Through the layoutlib_create tool, the original native methods of AvoidXfermode have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original AvoidXfermode class. - * - * Because this extends {@link Xfermode_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by - * {@link Xfermode_Delegate}. - * - */ -public class AvoidXfermode_Delegate extends Xfermode_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Composite getComposite(int alpha) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Avoid Xfermodes are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(int opColor, int tolerance, int nativeMode) { - AvoidXfermode_Delegate newDelegate = new AvoidXfermode_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java deleted file mode 100644 index 5256b58..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.ninepatch.NinePatchChunk; -import com.android.resources.Density; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.res.BridgeResources.NinePatchInputStream; -import android.graphics.BitmapFactory.Options; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStream; - -/** - * Delegate implementing the native methods of android.graphics.BitmapFactory - * - * Through the layoutlib_create tool, the original native methods of BitmapFactory have been - * replaced by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -/*package*/ class BitmapFactory_Delegate { - - // ------ Java delegates ------ - - @LayoutlibDelegate - /*package*/ static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { - if (bm == null || opts == null) { - return bm; - } - - final int density = opts.inDensity; - if (density == 0) { - return bm; - } - - bm.setDensity(density); - final int targetDensity = opts.inTargetDensity; - if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { - return bm; - } - - byte[] np = bm.getNinePatchChunk(); - final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np); - // DELEGATE CHANGE: never scale 9-patch - if (opts.inScaled && isNinePatch == false) { - float scale = targetDensity / (float)density; - // TODO: This is very inefficient and should be done in native by Skia - final Bitmap oldBitmap = bm; - bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f), - (int) (bm.getHeight() * scale + 0.5f), true); - oldBitmap.recycle(); - - if (isNinePatch) { - np = nativeScaleNinePatch(np, scale, outPadding); - bm.setNinePatchChunk(np); - } - bm.setDensity(targetDensity); - } - - return bm; - } - - - // ------ Native Delegates ------ - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, - Rect padding, Options opts) { - return nativeDecodeStream(is, storage, padding, opts, false, 1.f); - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, - Rect padding, Options opts, boolean applyScale, float scale) { - Bitmap bm = null; - - //TODO support rescaling - - Density density = Density.MEDIUM; - if (opts != null) { - density = Density.getEnum(opts.inDensity); - } - - try { - if (is instanceof NinePatchInputStream) { - NinePatchInputStream npis = (NinePatchInputStream) is; - npis.disableFakeMarkSupport(); - - // load the bitmap as a nine patch - com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load( - npis, true /*is9Patch*/, false /*convert*/); - - // get the bitmap and chunk objects. - bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/, - density); - NinePatchChunk chunk = ninePatch.getChunk(); - - // put the chunk in the bitmap - bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk)); - - // read the padding - int[] paddingarray = chunk.getPadding(); - padding.left = paddingarray[0]; - padding.top = paddingarray[1]; - padding.right = paddingarray[2]; - padding.bottom = paddingarray[3]; - } else { - // load the bitmap directly. - bm = Bitmap_Delegate.createBitmap(is, true, density); - } - } catch (IOException e) { - Bridge.getLog().error(null,"Failed to load image" , e, null); - } - - return bm; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, - Rect padding, Options opts) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts, - boolean applyScale, float scale) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset, - int length, Options opts) { - opts.inBitmap = null; - return null; - } - - @LayoutlibDelegate - /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) { - // don't scale for now. This should not be called anyway since we re-implement - // BitmapFactory.finishDecode(); - return chunk; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) { - return true; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java deleted file mode 100644 index 65a75b0..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Shader.TileMode; - -/** - * Delegate implementing the native methods of android.graphics.BitmapShader - * - * Through the layoutlib_create tool, the original native methods of BitmapShader have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original BitmapShader class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class BitmapShader_Delegate extends Shader_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - @Override - public boolean isSupported() { - return true; - } - - @Override - public String getSupportMessage() { - // no message since isSupported returns true; - return null; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(int native_bitmap, int shaderTileModeX, - int shaderTileModeY) { - Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(native_bitmap); - if (bitmap == null) { - return 0; - } - - BitmapShader_Delegate newDelegate = new BitmapShader_Delegate( - bitmap.getImage(), - Shader_Delegate.getTileMode(shaderTileModeX), - Shader_Delegate.getTileMode(shaderTileModeY)); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate(int native_shader, int native_bitmap, - int shaderTileModeX, int shaderTileModeY) { - // pass, not needed. - return 0; - } - - // ---- Private delegate/helper methods ---- - - private BitmapShader_Delegate(java.awt.image.BufferedImage image, - TileMode tileModeX, TileMode tileModeY) { - mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY); - } - - private class BitmapShaderPaint implements java.awt.Paint { - private final java.awt.image.BufferedImage mImage; - private final TileMode mTileModeX; - private final TileMode mTileModeY; - - BitmapShaderPaint(java.awt.image.BufferedImage image, - TileMode tileModeX, TileMode tileModeY) { - mImage = image; - mTileModeX = tileModeX; - mTileModeY = tileModeY; - } - - @Override - public java.awt.PaintContext createContext( - java.awt.image.ColorModel colorModel, - java.awt.Rectangle deviceBounds, - java.awt.geom.Rectangle2D userBounds, - java.awt.geom.AffineTransform xform, - java.awt.RenderingHints hints) { - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in BitmapShader", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in BitmapShader", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new BitmapShaderContext(canvasMatrix, localMatrix, colorModel); - } - - private class BitmapShaderContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - public BitmapShaderContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel; - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.ColorModel getColorModel() { - return mColorModel; - } - - @Override - public java.awt.image.Raster getRaster(int x, int y, int w, int h) { - java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h, - java.awt.image.BufferedImage.TYPE_INT_ARGB); - - int[] data = new int[w*h]; - - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix. - pt1[0] = pt2[0]; - pt1[1] = pt2[1]; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - data[index++] = getColor(pt2[0], pt2[1]); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - } - - /** - * Returns a color for an arbitrary point. - */ - private int getColor(float fx, float fy) { - int x = getCoordinate(Math.round(fx), mImage.getWidth(), mTileModeX); - int y = getCoordinate(Math.round(fy), mImage.getHeight(), mTileModeY); - - return mImage.getRGB(x, y); - } - - private int getCoordinate(int i, int size, TileMode mode) { - if (i < 0) { - switch (mode) { - case CLAMP: - i = 0; - break; - case REPEAT: - i = size - 1 - (-i % size); - break; - case MIRROR: - // this is the same as the positive side, just make the value positive - // first. - i = -i; - int count = i / size; - i = i % size; - - if ((count % 2) == 1) { - i = size - 1 - i; - } - break; - } - } else if (i >= size) { - switch (mode) { - case CLAMP: - i = size - 1; - break; - case REPEAT: - i = i % size; - break; - case MIRROR: - int count = i / size; - i = i % size; - - if ((count % 2) == 1) { - i = size - 1 - i; - } - break; - } - } - - return i; - } - - - @Override - public int getTransparency() { - return java.awt.Paint.TRANSLUCENT; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java deleted file mode 100644 index 4121f79..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ /dev/null @@ -1,592 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.resources.Density; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Bitmap.Config; -import android.os.Parcel; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.Buffer; -import java.util.Arrays; - -import javax.imageio.ImageIO; - -/** - * Delegate implementing the native methods of android.graphics.Bitmap - * - * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Bitmap class. - * - * @see DelegateManager - * - */ -public final class Bitmap_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<Bitmap_Delegate> sManager = - new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - private final Config mConfig; - private BufferedImage mImage; - private boolean mHasAlpha = true; - private boolean mHasMipMap = false; // TODO: check the default. - private int mGenerationId = 0; - - - // ---- Public Helper methods ---- - - /** - * Returns the native delegate associated to a given {@link Bitmap_Delegate} object. - */ - public static Bitmap_Delegate getDelegate(Bitmap bitmap) { - return sManager.getDelegate(bitmap.mNativeBitmap); - } - - /** - * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object. - */ - public static Bitmap_Delegate getDelegate(int native_bitmap) { - return sManager.getDelegate(native_bitmap); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given file content. - * - * @param input the file from which to read the bitmap content - * @param isMutable whether the bitmap is mutable - * @param density the density associated with the bitmap - * - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(File input, boolean isMutable, Density density) - throws IOException { - // create a delegate with the content of the file. - Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888); - - return createBitmap(delegate, isMutable, density.getDpiValue()); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given stream content. - * - * @param input the stream from which to read the bitmap content - * @param isMutable whether the bitmap is mutable - * @param density the density associated with the bitmap - * - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density) - throws IOException { - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888); - - return createBitmap(delegate, isMutable, density.getDpiValue()); - } - - /** - * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage} - * - * @param image the bitmap content - * @param isMutable whether the bitmap is mutable - * @param density the density associated with the bitmap - * - * @see Bitmap#isMutable() - * @see Bitmap#getDensity() - */ - public static Bitmap createBitmap(BufferedImage image, boolean isMutable, - Density density) throws IOException { - // create a delegate with the given image. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888); - - return createBitmap(delegate, isMutable, density.getDpiValue()); - } - - /** - * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}. - */ - public static BufferedImage getImage(Bitmap bitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap); - if (delegate == null) { - return null; - } - - return delegate.mImage; - } - - public static int getBufferedImageType(int nativeBitmapConfig) { - switch (Config.nativeToConfig(nativeBitmapConfig)) { - case ALPHA_8: - return BufferedImage.TYPE_INT_ARGB; - case RGB_565: - return BufferedImage.TYPE_INT_ARGB; - case ARGB_4444: - return BufferedImage.TYPE_INT_ARGB; - case ARGB_8888: - return BufferedImage.TYPE_INT_ARGB; - } - - return BufferedImage.TYPE_INT_ARGB; - } - - /** - * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}. - */ - public BufferedImage getImage() { - return mImage; - } - - /** - * Returns the Android bitmap config. Note that this not the config of the underlying - * Java2D bitmap. - */ - public Config getConfig() { - return mConfig; - } - - /** - * Returns the hasAlpha rendering hint - * @return true if the bitmap alpha should be used at render time - */ - public boolean hasAlpha() { - return mHasAlpha && mConfig != Config.RGB_565; - } - - public boolean hasMipMap() { - // TODO: check if more checks are required as in hasAlpha. - return mHasMipMap; - } - /** - * Update the generationId. - * - * @see Bitmap#getGenerationId() - */ - public void change() { - mGenerationId++; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width, - int height, int nativeConfig, boolean mutable) { - int imageType = getBufferedImageType(nativeConfig); - - // create the image - BufferedImage image = new BufferedImage(width, height, imageType); - - if (colors != null) { - image.setRGB(0, 0, width, height, colors, offset, stride); - } - - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig)); - - return createBitmap(delegate, mutable, Bitmap.getDefaultDensity()); - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) { - Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap); - if (srcBmpDelegate == null) { - return null; - } - - BufferedImage srcImage = srcBmpDelegate.getImage(); - - int width = srcImage.getWidth(); - int height = srcImage.getHeight(); - - int imageType = getBufferedImageType(nativeConfig); - - // create the image - BufferedImage image = new BufferedImage(width, height, imageType); - - // copy the source image into the image. - int[] argb = new int[width * height]; - srcImage.getRGB(0, 0, width, height, argb, 0, width); - image.setRGB(0, 0, width, height, argb, 0, width); - - // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig)); - - return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity()); - } - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(int nativeBitmap) { - sManager.removeJavaReferenceFor(nativeBitmap); - } - - @LayoutlibDelegate - /*package*/ static void nativeRecycle(int nativeBitmap) { - sManager.removeJavaReferenceFor(nativeBitmap); - } - - @LayoutlibDelegate - /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality, - OutputStream stream, byte[] tempStorage) { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.compress() is not supported", null /*data*/); - return true; - } - - @LayoutlibDelegate - /*package*/ static void nativeErase(int nativeBitmap, int color) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - BufferedImage image = delegate.mImage; - - Graphics2D g = image.createGraphics(); - try { - g.setColor(new java.awt.Color(color, true)); - - g.fillRect(0, 0, image.getWidth(), image.getHeight()); - } finally { - g.dispose(); - } - } - - @LayoutlibDelegate - /*package*/ static int nativeWidth(int nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mImage.getWidth(); - } - - @LayoutlibDelegate - /*package*/ static int nativeHeight(int nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mImage.getHeight(); - } - - @LayoutlibDelegate - /*package*/ static int nativeRowBytes(int nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mImage.getWidth(); - } - - @LayoutlibDelegate - /*package*/ static int nativeConfig(int nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mConfig.nativeInt; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeHasAlpha(int nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return true; - } - - return delegate.mHasAlpha; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeHasMipMap(int nativeBitmap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return true; - } - - return delegate.mHasMipMap; - } - - @LayoutlibDelegate - /*package*/ static int nativeGetPixel(int nativeBitmap, int x, int y) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mImage.getRGB(x, y); - } - - @LayoutlibDelegate - /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset, - int stride, int x, int y, int width, int height) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride); - } - - - @LayoutlibDelegate - /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.getImage().setRGB(x, y, color); - } - - @LayoutlibDelegate - /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset, - int stride, int x, int y, int width, int height) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.getImage().setRGB(x, y, width, height, colors, offset, stride); - } - - @LayoutlibDelegate - /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) { - // FIXME implement native delegate - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nativeCopyPixelsFromBuffer(int nb, Buffer src) { - // FIXME implement native delegate - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static int nativeGenerationId(int nativeBitmap) { - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return 0; - } - - return delegate.mGenerationId; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) { - // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only - // used during aidl call so really this should not be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.", - null /*data*/); - return null; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable, - int density, Parcel p) { - // This is only called when sending a bitmap through aidl, so really this should not - // be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.", - null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint, - int[] offsetXY) { - Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap); - if (bitmap == null) { - return null; - } - - // get the paint which can be null if nativePaint is 0. - Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint); - - if (paint != null && paint.getMaskFilter() != null) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER, - "MaskFilter not supported in Bitmap.extractAlpha", - null, null /*data*/); - } - - int alpha = paint != null ? paint.getAlpha() : 0xFF; - BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha); - - // create the delegate. The actual Bitmap config is only an alpha channel - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8); - - // the density doesn't matter, it's set by the Java method. - return createBitmap(delegate, false /*isMutable*/, - Density.DEFAULT_DENSITY /*density*/); - } - - @LayoutlibDelegate - /*package*/ static void nativePrepareToDraw(int nativeBitmap) { - // nothing to be done here. - } - - @LayoutlibDelegate - /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.mHasAlpha = hasAlpha; - } - - @LayoutlibDelegate - /*package*/ static void nativeSetHasMipMap(int nativeBitmap, boolean hasMipMap) { - // get the delegate from the native int. - Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); - if (delegate == null) { - return; - } - - delegate.mHasMipMap = hasMipMap; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSameAs(int nb0, int nb1) { - Bitmap_Delegate delegate1 = sManager.getDelegate(nb0); - if (delegate1 == null) { - return false; - } - - Bitmap_Delegate delegate2 = sManager.getDelegate(nb1); - if (delegate2 == null) { - return false; - } - - BufferedImage image1 = delegate1.getImage(); - BufferedImage image2 = delegate2.getImage(); - if (delegate1.mConfig != delegate2.mConfig || - image1.getWidth() != image2.getWidth() || - image1.getHeight() != image2.getHeight()) { - return false; - } - - // get the internal data - int w = image1.getWidth(); - int h = image2.getHeight(); - int[] argb1 = new int[w*h]; - int[] argb2 = new int[w*h]; - - image1.getRGB(0, 0, w, h, argb1, 0, w); - image2.getRGB(0, 0, w, h, argb2, 0, w); - - // compares - if (delegate1.mConfig == Config.ALPHA_8) { - // in this case we have to manually compare the alpha channel as the rest is garbage. - final int length = w*h; - for (int i = 0 ; i < length ; i++) { - if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) { - return false; - } - } - return true; - } - - return Arrays.equals(argb1, argb2); - } - - // ---- Private delegate/helper methods ---- - - private Bitmap_Delegate(BufferedImage image, Config config) { - mImage = image; - mConfig = config; - } - - private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) { - // get its native_int - int nativeInt = sManager.addNewDelegate(delegate); - - // and create/return a new Bitmap with it - // TODO: pass correct width, height, isPremultiplied - return new Bitmap(nativeInt, null /* buffer */, -1 /* width */, -1 /* height */, density, - isMutable, true /* isPremultiplied */, - null /*ninePatchChunk*/, null /* layoutBounds */); - } - - /** - * Creates and returns a copy of a given BufferedImage. - * <p/> - * if alpha is different than 255, then it is applied to the alpha channel of each pixel. - * - * @param image the image to copy - * @param imageType the type of the new image - * @param alpha an optional alpha modifier - * @return a new BufferedImage - */ - /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) { - int w = image.getWidth(); - int h = image.getHeight(); - - BufferedImage result = new BufferedImage(w, h, imageType); - - int[] argb = new int[w * h]; - image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); - - if (alpha != 255) { - final int length = argb.length; - for (int i = 0 ; i < length; i++) { - int a = (argb[i] >>> 24 * alpha) / 255; - argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF); - } - } - - result.setRGB(0, 0, w, h, argb, 0, w); - - return result; - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java deleted file mode 100644 index 4becba1..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.BlurMaskFilter - * - * Through the layoutlib_create tool, the original native methods of BlurMaskFilter have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original BlurMaskFilter class. - * - * Because this extends {@link MaskFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link MaskFilter_Delegate}. - * - * @see MaskFilter_Delegate - * - */ -public class BlurMaskFilter_Delegate extends MaskFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Blur Mask Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeConstructor(float radius, int style) { - BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java deleted file mode 100644 index 361f5d7..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ /dev/null @@ -1,1362 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.GcSnapshot; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Bitmap.Config; -import android.graphics.Paint_Delegate.FontInfo; -import android.text.TextUtils; - -import java.awt.Color; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Arc2D; -import java.awt.image.BufferedImage; -import java.util.List; - - -/** - * Delegate implementing the native methods of android.graphics.Canvas - * - * Through the layoutlib_create tool, the original native methods of Canvas have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Canvas class. - * - * @see DelegateManager - * - */ -public final class Canvas_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<Canvas_Delegate> sManager = - new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class); - - // ---- delegate helper data ---- - - private final static boolean[] sBoolOut = new boolean[1]; - - // ---- delegate data ---- - private Bitmap_Delegate mBitmap; - private GcSnapshot mSnapshot; - - private DrawFilter_Delegate mDrawFilter = null; - - // ---- Public Helper methods ---- - - /** - * Returns the native delegate associated to a given {@link Canvas} object. - */ - public static Canvas_Delegate getDelegate(Canvas canvas) { - return sManager.getDelegate(canvas.mNativeCanvas); - } - - /** - * Returns the native delegate associated to a given an int referencing a {@link Canvas} object. - */ - public static Canvas_Delegate getDelegate(int native_canvas) { - return sManager.getDelegate(native_canvas); - } - - /** - * Returns the current {@link Graphics2D} used to draw. - */ - public GcSnapshot getSnapshot() { - return mSnapshot; - } - - /** - * Returns the {@link DrawFilter} delegate or null if none have been set. - * - * @return the delegate or null. - */ - public DrawFilter_Delegate getDrawFilter() { - return mDrawFilter; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static boolean isOpaque(Canvas thisCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return false; - } - - return canvasDelegate.mBitmap.getConfig() == Config.RGB_565; - } - - @LayoutlibDelegate - /*package*/ static int getWidth(Canvas thisCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.mBitmap.getImage().getWidth(); - } - - @LayoutlibDelegate - /*package*/ static int getHeight(Canvas thisCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.mBitmap.getImage().getHeight(); - } - - @LayoutlibDelegate - /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.getSnapshot().translate(dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void rotate(Canvas thisCanvas, float degrees) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees)); - } - - @LayoutlibDelegate - /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.getSnapshot().scale(sx, sy); - } - - @LayoutlibDelegate - /*package*/ static void skew(Canvas thisCanvas, float kx, float ky) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return; - } - - // get the current top graphics2D object. - GcSnapshot g = canvasDelegate.getSnapshot(); - - // get its current matrix - AffineTransform currentTx = g.getTransform(); - // get the AffineTransform for the given skew. - float[] mtx = Matrix_Delegate.getSkew(kx, ky); - AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx); - - // combine them so that the given matrix is applied after. - currentTx.preConcatenate(matrixTx); - - // give it to the graphics2D as a new matrix replacing all previous transform - g.setTransform(currentTx); - } - - @LayoutlibDelegate - /*package*/ static boolean clipRect(Canvas thisCanvas, RectF rect) { - return clipRect(thisCanvas, rect.left, rect.top, rect.right, rect.bottom); - } - - @LayoutlibDelegate - /*package*/ static boolean clipRect(Canvas thisCanvas, Rect rect) { - return clipRect(thisCanvas, (float) rect.left, (float) rect.top, - (float) rect.right, (float) rect.bottom); - } - - @LayoutlibDelegate - /*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right, - float bottom) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return false; - } - - return canvasDelegate.clipRect(left, top, right, bottom, Region.Op.INTERSECT.nativeInt); - } - - @LayoutlibDelegate - /*package*/ static boolean clipRect(Canvas thisCanvas, int left, int top, int right, - int bottom) { - - return clipRect(thisCanvas, (float) left, (float) top, (float) right, (float) bottom); - } - - @LayoutlibDelegate - /*package*/ static int save(Canvas thisCanvas) { - return save(thisCanvas, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG); - } - - @LayoutlibDelegate - /*package*/ static int save(Canvas thisCanvas, int saveFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.save(saveFlags); - } - - @LayoutlibDelegate - /*package*/ static void restore(Canvas thisCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.restore(); - } - - @LayoutlibDelegate - /*package*/ static int getSaveCount(Canvas thisCanvas) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.getSnapshot().size(); - } - - @LayoutlibDelegate - /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.restoreTo(saveCount); - } - - @LayoutlibDelegate - /*package*/ static void drawPoints(Canvas thisCanvas, float[] pts, int offset, int count, - Paint paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawPoint is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void drawPoint(Canvas thisCanvas, float x, float y, Paint paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawPoint is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void drawLines(Canvas thisCanvas, - final float[] pts, final int offset, final int count, - Paint paint) { - draw(thisCanvas.mNativeCanvas, paint.mNativePaint, false /*compositeOnly*/, - false /*forceSrcMode*/, new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - for (int i = 0 ; i < count ; i += 4) { - graphics.drawLine((int)pts[i + offset], (int)pts[i + offset + 1], - (int)pts[i + offset + 2], (int)pts[i + offset + 3]); - } - } - }); - } - - @LayoutlibDelegate - /*package*/ static void freeCaches() { - // nothing to be done here. - } - - @LayoutlibDelegate - /*package*/ static void freeTextLayoutCaches() { - // nothing to be done here yet. - } - - @LayoutlibDelegate - /*package*/ static int initRaster(int nativeBitmapOrZero) { - if (nativeBitmapOrZero > 0) { - // get the Bitmap from the int - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero); - - // create a new Canvas_Delegate with the given bitmap and return its new native int. - Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate); - - return sManager.addNewDelegate(newDelegate); - } - - // create a new Canvas_Delegate and return its new native int. - Canvas_Delegate newDelegate = new Canvas_Delegate(); - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void copyNativeCanvasState(int srcCanvas, int dstCanvas) { - // get the delegate from the native int. - Canvas_Delegate srcCanvasDelegate = sManager.getDelegate(srcCanvas); - if (srcCanvasDelegate == null) { - return; - } - - // get the delegate from the native int. - Canvas_Delegate dstCanvasDelegate = sManager.getDelegate(dstCanvas); - if (dstCanvasDelegate == null) { - return; - } - // TODO: actually copy the canvas state. - } - - @LayoutlibDelegate - /*package*/ static int native_saveLayer(int nativeCanvas, RectF bounds, - int paint, int layerFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint); - if (paintDelegate == null) { - return 0; - } - - return canvasDelegate.saveLayer(bounds, paintDelegate, layerFlags); - } - - @LayoutlibDelegate - /*package*/ static int native_saveLayer(int nativeCanvas, float l, - float t, float r, float b, - int paint, int layerFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint); - if (paintDelegate == null) { - return 0; - } - - return canvasDelegate.saveLayer(new RectF(l, t, r, b), - paintDelegate, layerFlags); - } - - @LayoutlibDelegate - /*package*/ static int native_saveLayerAlpha(int nativeCanvas, - RectF bounds, int alpha, - int layerFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.saveLayerAlpha(bounds, alpha, layerFlags); - } - - @LayoutlibDelegate - /*package*/ static int native_saveLayerAlpha(int nativeCanvas, float l, - float t, float r, float b, - int alpha, int layerFlags) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return 0; - } - - return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags); - } - - - @LayoutlibDelegate - /*package*/ static void native_concat(int nCanvas, int nMatrix) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); - if (matrixDelegate == null) { - return; - } - - // get the current top graphics2D object. - GcSnapshot snapshot = canvasDelegate.getSnapshot(); - - // get its current matrix - AffineTransform currentTx = snapshot.getTransform(); - // get the AffineTransform of the given matrix - AffineTransform matrixTx = matrixDelegate.getAffineTransform(); - - // combine them so that the given matrix is applied after. - currentTx.concatenate(matrixTx); - - // give it to the graphics2D as a new matrix replacing all previous transform - snapshot.setTransform(currentTx); - } - - @LayoutlibDelegate - /*package*/ static void native_setMatrix(int nCanvas, int nMatrix) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); - if (matrixDelegate == null) { - return; - } - - // get the current top graphics2D object. - GcSnapshot snapshot = canvasDelegate.getSnapshot(); - - // get the AffineTransform of the given matrix - AffineTransform matrixTx = matrixDelegate.getAffineTransform(); - - // give it to the graphics2D as a new matrix replacing all previous transform - snapshot.setTransform(matrixTx); - - if (matrixDelegate.hasPerspective()) { - assert false; - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE, - "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " + - "supports affine transformations.", null, null /*data*/); - } - } - - @LayoutlibDelegate - /*package*/ static boolean native_clipRect(int nCanvas, - float left, float top, - float right, float bottom, - int regionOp) { - - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return false; - } - - return canvasDelegate.clipRect(left, top, right, bottom, regionOp); - } - - @LayoutlibDelegate - /*package*/ static boolean native_clipPath(int nativeCanvas, - int nativePath, - int regionOp) { - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return true; - } - - Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath); - if (pathDelegate == null) { - return true; - } - - return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp); - } - - @LayoutlibDelegate - /*package*/ static boolean native_clipRegion(int nativeCanvas, - int nativeRegion, - int regionOp) { - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return true; - } - - Region_Delegate region = Region_Delegate.getDelegate(nativeRegion); - if (region == null) { - return true; - } - - return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp); - } - - @LayoutlibDelegate - /*package*/ static void nativeSetDrawFilter(int nativeCanvas, int nativeFilter) { - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter); - - if (canvasDelegate.mDrawFilter != null && - canvasDelegate.mDrawFilter.isSupported() == false) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER, - canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/); - } - } - - @LayoutlibDelegate - /*package*/ static boolean native_getClipBounds(int nativeCanvas, - Rect bounds) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return false; - } - - Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds(); - if (rect != null && rect.isEmpty() == false) { - bounds.left = rect.x; - bounds.top = rect.y; - bounds.right = rect.x + rect.width; - bounds.bottom = rect.y + rect.height; - return true; - } - - return false; - } - - @LayoutlibDelegate - /*package*/ static void native_getCTM(int canvas, int matrix) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas); - if (canvasDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); - if (matrixDelegate == null) { - return; - } - - AffineTransform transform = canvasDelegate.getSnapshot().getTransform(); - matrixDelegate.set(Matrix_Delegate.makeValues(transform)); - } - - @LayoutlibDelegate - /*package*/ static boolean native_quickReject(int nativeCanvas, - RectF rect) { - // FIXME properly implement quickReject - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean native_quickReject(int nativeCanvas, - int path) { - // FIXME properly implement quickReject - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean native_quickReject(int nativeCanvas, - float left, float top, - float right, float bottom) { - // FIXME properly implement quickReject - return false; - } - - @LayoutlibDelegate - /*package*/ static void native_drawRGB(int nativeCanvas, int r, int g, int b) { - native_drawColor(nativeCanvas, 0xFF000000 | r << 16 | (g&0xFF) << 8 | (b&0xFF), - PorterDuff.Mode.SRC_OVER.nativeInt); - - } - - @LayoutlibDelegate - /*package*/ static void native_drawARGB(int nativeCanvas, int a, int r, int g, int b) { - native_drawColor(nativeCanvas, a << 24 | (r&0xFF) << 16 | (g&0xFF) << 8 | (b&0xFF), - PorterDuff.Mode.SRC_OVER.nativeInt); - } - - @LayoutlibDelegate - /*package*/ static void native_drawColor(int nativeCanvas, int color) { - native_drawColor(nativeCanvas, color, PorterDuff.Mode.SRC_OVER.nativeInt); - } - - @LayoutlibDelegate - /*package*/ static void native_drawColor(int nativeCanvas, final int color, final int mode) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - final int w = canvasDelegate.mBitmap.getImage().getWidth(); - final int h = canvasDelegate.mBitmap.getImage().getHeight(); - draw(nativeCanvas, new GcSnapshot.Drawable() { - - @Override - public void draw(Graphics2D graphics, Paint_Delegate paint) { - // reset its transform just in case - graphics.setTransform(new AffineTransform()); - - // set the color - graphics.setColor(new Color(color, true /*alpha*/)); - - Composite composite = PorterDuffXfermode_Delegate.getComposite( - PorterDuffXfermode_Delegate.getPorterDuffMode(mode), 0xFF); - if (composite != null) { - graphics.setComposite(composite); - } - - graphics.fillRect(0, 0, w, h); - } - }); - } - - @LayoutlibDelegate - /*package*/ static void native_drawPaint(int nativeCanvas, int paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawPaint is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void native_drawLine(int nativeCanvas, - final float startX, final float startY, final float stopX, final float stopY, - int paint) { - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY); - } - }); - } - - @LayoutlibDelegate - /*package*/ static void native_drawRect(int nativeCanvas, RectF rect, - int paint) { - native_drawRect(nativeCanvas, rect.left, rect.top, rect.right, rect.bottom, paint); - } - - @LayoutlibDelegate - /*package*/ static void native_drawRect(int nativeCanvas, - final float left, final float top, final float right, final float bottom, int paint) { - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - int style = paintDelegate.getStyle(); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fillRect((int)left, (int)top, - (int)(right-left), (int)(bottom-top)); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.drawRect((int)left, (int)top, - (int)(right-left), (int)(bottom-top)); - } - } - }); - } - - @LayoutlibDelegate - /*package*/ static void native_drawOval(int nativeCanvas, final RectF oval, int paint) { - if (oval.right > oval.left && oval.bottom > oval.top) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - int style = paintDelegate.getStyle(); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fillOval((int)oval.left, (int)oval.top, - (int)oval.width(), (int)oval.height()); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.drawOval((int)oval.left, (int)oval.top, - (int)oval.width(), (int)oval.height()); - } - } - }); - } - } - - @LayoutlibDelegate - /*package*/ static void native_drawCircle(int nativeCanvas, - float cx, float cy, float radius, int paint) { - native_drawOval(nativeCanvas, - new RectF(cx - radius, cy - radius, cx + radius, cy + radius), - paint); - } - - @LayoutlibDelegate - /*package*/ static void native_drawArc(int nativeCanvas, - final RectF oval, final float startAngle, final float sweep, - final boolean useCenter, int paint) { - if (oval.right > oval.left && oval.bottom > oval.top) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - int style = paintDelegate.getStyle(); - - Arc2D.Float arc = new Arc2D.Float( - oval.left, oval.top, oval.width(), oval.height(), - -startAngle, -sweep, - useCenter ? Arc2D.PIE : Arc2D.OPEN); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fill(arc); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.draw(arc); - } - } - }); - } - } - - @LayoutlibDelegate - /*package*/ static void native_drawRoundRect(int nativeCanvas, - final RectF rect, final float rx, final float ry, int paint) { - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - int style = paintDelegate.getStyle(); - - // draw - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fillRoundRect( - (int)rect.left, (int)rect.top, - (int)rect.width(), (int)rect.height(), - (int)rx, (int)ry); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.drawRoundRect( - (int)rect.left, (int)rect.top, - (int)rect.width(), (int)rect.height(), - (int)rx, (int)ry); - } - } - }); - } - - @LayoutlibDelegate - /*package*/ static void native_drawPath(int nativeCanvas, int path, int paint) { - final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path); - if (pathDelegate == null) { - return; - } - - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - Shape shape = pathDelegate.getJavaShape(); - int style = paintDelegate.getStyle(); - - if (style == Paint.Style.FILL.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.fill(shape); - } - - if (style == Paint.Style.STROKE.nativeInt || - style == Paint.Style.FILL_AND_STROKE.nativeInt) { - graphics.draw(shape); - } - } - }); - } - - @LayoutlibDelegate - /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap, - float left, float top, - int nativePaintOrZero, - int canvasDensity, - int screenDensity, - int bitmapDensity) { - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (bitmapDelegate == null) { - return; - } - - BufferedImage image = bitmapDelegate.getImage(); - float right = left + image.getWidth(); - float bottom = top + image.getHeight(); - - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, - 0, 0, image.getWidth(), image.getHeight(), - (int)left, (int)top, (int)right, (int)bottom); - } - - @LayoutlibDelegate - /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap, - Rect src, RectF dst, - int nativePaintOrZero, - int screenDensity, - int bitmapDensity) { - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (bitmapDelegate == null) { - return; - } - - BufferedImage image = bitmapDelegate.getImage(); - - if (src == null) { - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, - 0, 0, image.getWidth(), image.getHeight(), - (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom); - } else { - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, - src.left, src.top, src.width(), src.height(), - (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom); - } - } - - @LayoutlibDelegate - /*package*/ static void native_drawBitmap(int nativeCanvas, int bitmap, - Rect src, Rect dst, - int nativePaintOrZero, - int screenDensity, - int bitmapDensity) { - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); - if (bitmapDelegate == null) { - return; - } - - BufferedImage image = bitmapDelegate.getImage(); - - if (src == null) { - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, - 0, 0, image.getWidth(), image.getHeight(), - dst.left, dst.top, dst.right, dst.bottom); - } else { - drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, - src.left, src.top, src.width(), src.height(), - dst.left, dst.top, dst.right, dst.bottom); - } - } - - @LayoutlibDelegate - /*package*/ static void native_drawBitmap(int nativeCanvas, int[] colors, - int offset, int stride, final float x, - final float y, int width, int height, - boolean hasAlpha, - int nativePaintOrZero) { - - // create a temp BufferedImage containing the content. - final BufferedImage image = new BufferedImage(width, height, - hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); - image.setRGB(0, 0, width, height, colors, offset, stride); - - draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paint) { - if (paint != null && paint.isFilterBitmap()) { - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - graphics.drawImage(image, (int) x, (int) y, null); - } - }); - } - - @LayoutlibDelegate - /*package*/ static void nativeDrawBitmapMatrix(int nCanvas, int nBitmap, - int nMatrix, int nPaint) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - // get the delegate from the native int, which can be null - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); - - // get the delegate from the native int. - Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap); - if (bitmapDelegate == null) { - return; - } - - final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut); - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); - if (matrixDelegate == null) { - return; - } - - final AffineTransform mtx = matrixDelegate.getAffineTransform(); - - canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paint) { - if (paint != null && paint.isFilterBitmap()) { - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - //FIXME add support for canvas, screen and bitmap densities. - graphics.drawImage(image, mtx, null); - } - }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/); - } - - @LayoutlibDelegate - /*package*/ static void nativeDrawBitmapMesh(int nCanvas, int nBitmap, - int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, - int colorOffset, int nPaint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawBitmapMesh is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nativeDrawVertices(int nCanvas, int mode, int n, - float[] verts, int vertOffset, - float[] texs, int texOffset, - int[] colors, int colorOffset, - short[] indices, int indexOffset, - int indexCount, int nPaint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawVertices is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void native_drawText(int nativeCanvas, - final char[] text, final int index, final int count, - final float startX, final float startY, int flags, int paint) { - draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { - // WARNING: the logic in this method is similar to Paint_Delegate.measureText. - // Any change to this method should be reflected in Paint.measureText - // Paint.TextAlign indicates how the text is positioned relative to X. - // LEFT is the default and there's nothing to do. - float x = startX; - float y = startY; - if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) { - // TODO: check the value of bidiFlags. - float m = paintDelegate.measureText(text, index, count, 0); - if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) { - x -= m / 2; - } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) { - x -= m; - } - } - - List<FontInfo> fonts = paintDelegate.getFonts(); - - if (fonts.size() > 0) { - FontInfo mainFont = fonts.get(0); - int i = index; - int lastIndex = index + count; - while (i < lastIndex) { - // always start with the main font. - int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); - if (upTo == -1) { - // draw all the rest and exit. - graphics.setFont(mainFont.mFont); - graphics.drawChars(text, i, lastIndex - i, (int)x, (int)y); - return; - } else if (upTo > 0) { - // draw what's possible - graphics.setFont(mainFont.mFont); - graphics.drawChars(text, i, upTo - i, (int)x, (int)y); - - // compute the width that was drawn to increase x - x += mainFont.mMetrics.charsWidth(text, i, upTo - i); - - // move index to the first non displayed char. - i = upTo; - - // don't call continue at this point. Since it is certain the main font - // cannot display the font a index upTo (now ==i), we move on to the - // fallback fonts directly. - } - - // no char supported, attempt to read the next char(s) with the - // fallback font. In this case we only test the first character - // and then go back to test with the main font. - // Special test for 2-char characters. - boolean foundFont = false; - for (int f = 1 ; f < fonts.size() ; f++) { - FontInfo fontInfo = fonts.get(f); - - // need to check that the font can display the character. We test - // differently if the char is a high surrogate. - int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; - upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); - if (upTo == -1) { - // draw that char - graphics.setFont(fontInfo.mFont); - graphics.drawChars(text, i, charCount, (int)x, (int)y); - - // update x - x += fontInfo.mMetrics.charsWidth(text, i, charCount); - - // update the index in the text, and move on - i += charCount; - foundFont = true; - break; - - } - } - - // in case no font can display the char, display it with the main font. - // (it'll put a square probably) - if (foundFont == false) { - int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; - - graphics.setFont(mainFont.mFont); - graphics.drawChars(text, i, charCount, (int)x, (int)y); - - // measure it to advance x - x += mainFont.mMetrics.charsWidth(text, i, charCount); - - // and move to the next chars. - i += charCount; - } - } - } - } - }); - } - - @LayoutlibDelegate - /*package*/ static void native_drawText(int nativeCanvas, String text, - int start, int end, float x, float y, int flags, int paint) { - int count = end - start; - char[] buffer = TemporaryBuffer.obtain(count); - TextUtils.getChars(text, start, end, buffer, 0); - - native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint); - } - - @LayoutlibDelegate - /*package*/ static void native_drawTextRun(int nativeCanvas, String text, - int start, int end, int contextStart, int contextEnd, - float x, float y, int flags, int paint) { - int count = end - start; - char[] buffer = TemporaryBuffer.obtain(count); - TextUtils.getChars(text, start, end, buffer, 0); - - native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint); - } - - @LayoutlibDelegate - /*package*/ static void native_drawTextRun(int nativeCanvas, char[] text, - int start, int count, int contextStart, int contextCount, - float x, float y, int flags, int paint) { - native_drawText(nativeCanvas, text, start, count, x, y, flags, paint); - } - - @LayoutlibDelegate - /*package*/ static void native_drawPosText(int nativeCanvas, - char[] text, int index, - int count, float[] pos, - int paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawPosText is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void native_drawPosText(int nativeCanvas, - String text, float[] pos, - int paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawPosText is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void native_drawTextOnPath(int nativeCanvas, - char[] text, int index, - int count, int path, - float hOffset, - float vOffset, int bidiFlags, - int paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawTextOnPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void native_drawTextOnPath(int nativeCanvas, - String text, int path, - float hOffset, - float vOffset, - int flags, int paint) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Canvas.drawTextOnPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void finalizer(int nativeCanvas) { - // get the delegate from the native int so that it can be disposed. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.dispose(); - - // remove it from the manager. - sManager.removeJavaReferenceFor(nativeCanvas); - } - - // ---- Private delegate/helper methods ---- - - /** - * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint. - * <p>Note that the drawable may actually be executed several times if there are - * layers involved (see {@link #saveLayer(RectF, int, int)}. - */ - private static void draw(int nCanvas, int nPaint, boolean compositeOnly, boolean forceSrcMode, - GcSnapshot.Drawable drawable) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - // get the paint which can be null if nPaint is 0; - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); - - canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode); - } - - /** - * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided - * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}. - * <p>Note that the drawable may actually be executed several times if there are - * layers involved (see {@link #saveLayer(RectF, int, int)}. - */ - private static void draw(int nCanvas, GcSnapshot.Drawable drawable) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); - if (canvasDelegate == null) { - return; - } - - canvasDelegate.mSnapshot.draw(drawable); - } - - private Canvas_Delegate(Bitmap_Delegate bitmap) { - mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap); - } - - private Canvas_Delegate() { - mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/); - } - - /** - * Disposes of the {@link Graphics2D} stack. - */ - private void dispose() { - mSnapshot.dispose(); - } - - private int save(int saveFlags) { - // get the current save count - int count = mSnapshot.size(); - - mSnapshot = mSnapshot.save(saveFlags); - - // return the old save count - return count; - } - - private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) { - Paint_Delegate paint = new Paint_Delegate(); - paint.setAlpha(alpha); - return saveLayer(rect, paint, saveFlags); - } - - private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) { - // get the current save count - int count = mSnapshot.size(); - - mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags); - - // return the old save count - return count; - } - - /** - * Restores the {@link GcSnapshot} to <var>saveCount</var> - * @param saveCount the saveCount - */ - private void restoreTo(int saveCount) { - mSnapshot = mSnapshot.restoreTo(saveCount); - } - - /** - * Restores the {@link GcSnapshot} to <var>saveCount</var> - * @param saveCount the saveCount - */ - private void restore() { - mSnapshot = mSnapshot.restore(); - } - - private boolean clipRect(float left, float top, float right, float bottom, int regionOp) { - return mSnapshot.clipRect(left, top, right, bottom, regionOp); - } - - private void setBitmap(Bitmap_Delegate bitmap) { - mBitmap = bitmap; - assert mSnapshot.size() == 1; - mSnapshot.setBitmap(mBitmap); - } - - private static void drawBitmap( - int nativeCanvas, - Bitmap_Delegate bitmap, - int nativePaintOrZero, - final int sleft, final int stop, final int sright, final int sbottom, - final int dleft, final int dtop, final int dright, final int dbottom) { - // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); - if (canvasDelegate == null) { - return; - } - - // get the paint, which could be null if the int is 0 - Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero); - - final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut); - - draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0], - new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paint) { - if (paint != null && paint.isFilterBitmap()) { - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - //FIXME add support for canvas, screen and bitmap densities. - graphics.drawImage(image, dleft, dtop, dright, dbottom, - sleft, stop, sright, sbottom, null); - } - }); - } - - - /** - * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate. - * The image returns, through a 1-size boolean array, whether the drawing code should - * use a SRC composite no matter what the paint says. - * - * @param bitmap the bitmap - * @param paint the paint that will be used to draw - * @param forceSrcMode whether the composite will have to be SRC - * @return the image to draw - */ - private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint, - boolean[] forceSrcMode) { - BufferedImage image = bitmap.getImage(); - forceSrcMode[0] = false; - - // if the bitmap config is alpha_8, then we erase all color value from it - // before drawing it. - if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) { - fixAlpha8Bitmap(image); - } else if (bitmap.hasAlpha() == false) { - // hasAlpha is merely a rendering hint. There can in fact be alpha values - // in the bitmap but it should be ignored at drawing time. - // There is two ways to do this: - // - override the composite to be SRC. This can only be used if the composite - // was going to be SRC or SRC_OVER in the first place - // - Create a different bitmap to draw in which all the alpha channel values is set - // to 0xFF. - if (paint != null) { - Xfermode_Delegate xfermodeDelegate = paint.getXfermode(); - if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) { - PorterDuff.Mode mode = - ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode(); - - forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER || - mode == PorterDuff.Mode.SRC; - } - } - - // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB - if (forceSrcMode[0] == false) { - image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF); - } - } - - return image; - } - - private static void fixAlpha8Bitmap(final BufferedImage image) { - int w = image.getWidth(); - int h = image.getHeight(); - int[] argb = new int[w * h]; - image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); - - final int length = argb.length; - for (int i = 0 ; i < length; i++) { - argb[i] &= 0xFF000000; - } - image.setRGB(0, 0, w, h, argb, 0, w); - } -} - diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java deleted file mode 100644 index e5a7ab6..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.ColorFilter - * - * Through the layoutlib_create tool, the original native methods of ColorFilter have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original ColorFilter class. - * - * This also serve as a base class for all ColorFilter delegate classes. - * - * @see DelegateManager - * - */ -public abstract class ColorFilter_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<ColorFilter_Delegate> sManager = - new DelegateManager<ColorFilter_Delegate>(ColorFilter_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static ColorFilter_Delegate getDelegate(int nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void finalizer(int native_instance, int nativeColorFilter) { - sManager.removeJavaReferenceFor(native_instance); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java deleted file mode 100644 index 2de344b..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.ColorMatrixColorFilter - * - * Through the layoutlib_create tool, the original native methods of ColorMatrixColorFilter have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original ColorMatrixColorFilter class. - * - * Because this extends {@link ColorFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link ColorFilter_Delegate}. - * - * @see ColorFilter_Delegate - * - */ -public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "ColorMatrix Color Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeColorMatrixFilter(float[] array) { - ColorMatrixColorFilter_Delegate newDelegate = new ColorMatrixColorFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nColorMatrixFilter(int nativeFilter, float[] array) { - // pass - return 0; - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java deleted file mode 100644 index 7c04a87..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.ComposePathEffect - * - * Through the layoutlib_create tool, the original native methods of ComposePathEffect have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original ComposePathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class ComposePathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Compose Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(int outerpe, int innerpe) { - ComposePathEffect_Delegate newDelegate = new ComposePathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java deleted file mode 100644 index f6e1d00..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Paint; - -/** - * Delegate implementing the native methods of android.graphics.ComposeShader - * - * Through the layoutlib_create tool, the original native methods of ComposeShader have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original ComposeShader class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class ComposeShader_Delegate extends Shader_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Paint getJavaPaint() { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Compose Shaders are not supported in Layout Preview mode."; - } - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate1(int native_shaderA, int native_shaderB, - int native_mode) { - // FIXME not supported yet. - ComposeShader_Delegate newDelegate = new ComposeShader_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nativeCreate2(int native_shaderA, int native_shaderB, - int porterDuffMode) { - // FIXME not supported yet. - ComposeShader_Delegate newDelegate = new ComposeShader_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate1(int native_shader, int native_skiaShaderA, - int native_skiaShaderB, int native_mode) { - // pass, not needed. - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate2(int native_shader, int native_skiaShaderA, - int native_skiaShaderB, int porterDuffMode) { - // pass, not needed. - return 0; - } - - // ---- Private delegate/helper methods ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java deleted file mode 100644 index b0f8168..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.CornerPathEffect - * - * Through the layoutlib_create tool, the original native methods of CornerPathEffect have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original CornerPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class CornerPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Corner Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(float radius) { - CornerPathEffect_Delegate newDelegate = new CornerPathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java deleted file mode 100644 index d97c2ec..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.BasicStroke; -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.DashPathEffect - * - * Through the layoutlib_create tool, the original native methods of DashPathEffect have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original DashPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by - * {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public final class DashPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - private final float[] mIntervals; - private final float mPhase; - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - return new BasicStroke( - paint.getStrokeWidth(), - paint.getJavaCap(), - paint.getJavaJoin(), - paint.getJavaStrokeMiter(), - mIntervals, - mPhase); - } - - @Override - public boolean isSupported() { - return true; - } - - @Override - public String getSupportMessage() { - // no message since isSupported returns true; - return null; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(float intervals[], float phase) { - DashPathEffect_Delegate newDelegate = new DashPathEffect_Delegate(intervals, phase); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- - - private DashPathEffect_Delegate(float intervals[], float phase) { - mIntervals = new float[intervals.length]; - System.arraycopy(intervals, 0, mIntervals, 0, intervals.length); - mPhase = phase; - } -} - diff --git a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java deleted file mode 100644 index ec4a810..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.DiscretePathEffect - * - * Through the layoutlib_create tool, the original native methods of DiscretePathEffect have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original DiscretePathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class DiscretePathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Discrete Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(float length, float deviation) { - DiscretePathEffect_Delegate newDelegate = new DiscretePathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java deleted file mode 100644 index 870c46b..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.DrawFilter - * - * Through the layoutlib_create tool, the original native methods of DrawFilter have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original DrawFilter class. - * - * This also serve as a base class for all DrawFilter delegate classes. - * - * @see DelegateManager - * - */ -public abstract class DrawFilter_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<DrawFilter_Delegate> sManager = - new DelegateManager<DrawFilter_Delegate>(DrawFilter_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static DrawFilter_Delegate getDelegate(int nativeDrawFilter) { - return sManager.getDelegate(nativeDrawFilter); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(int nativeDrawFilter) { - sManager.removeJavaReferenceFor(nativeDrawFilter); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java deleted file mode 100644 index ebc1c1d..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.EmbossMaskFilter - * - * Through the layoutlib_create tool, the original native methods of EmbossMaskFilter have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original EmbossMaskFilter class. - * - * Because this extends {@link MaskFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link MaskFilter_Delegate}. - * - * @see MaskFilter_Delegate - * - */ -public class EmbossMaskFilter_Delegate extends MaskFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Emboss Mask Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeConstructor(float[] direction, float ambient, - float specular, float blurRadius) { - EmbossMaskFilter_Delegate newDelegate = new EmbossMaskFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java deleted file mode 100644 index 7475c22..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import android.graphics.Shader.TileMode; - -/** - * Base class for true Gradient shader delegate. - */ -public abstract class Gradient_Delegate extends Shader_Delegate { - - protected final int[] mColors; - protected final float[] mPositions; - - @Override - public boolean isSupported() { - // all gradient shaders are supported. - return true; - } - - @Override - public String getSupportMessage() { - // all gradient shaders are supported, no need for a gradient support - return null; - } - - /** - * Creates the base shader and do some basic test on the parameters. - * - * @param colors The colors to be distributed along the gradient line - * @param positions May be null. The relative positions [0..1] of each - * corresponding color in the colors array. If this is null, the - * the colors are distributed evenly along the gradient line. - */ - protected Gradient_Delegate(int colors[], float positions[]) { - if (colors.length < 2) { - throw new IllegalArgumentException("needs >= 2 number of colors"); - } - if (positions != null && colors.length != positions.length) { - throw new IllegalArgumentException("color and position arrays must be of equal length"); - } - - if (positions == null) { - float spacing = 1.f / (colors.length - 1); - positions = new float[colors.length]; - positions[0] = 0.f; - positions[colors.length-1] = 1.f; - for (int i = 1; i < colors.length - 1 ; i++) { - positions[i] = spacing * i; - } - } - - mColors = colors; - mPositions = positions; - } - - /** - * Base class for (Java) Gradient Paints. This handles computing the gradient colors based - * on the color and position lists, as well as the {@link TileMode} - * - */ - protected abstract static class GradientPaint implements java.awt.Paint { - private final static int GRADIENT_SIZE = 100; - - private final int[] mColors; - private final float[] mPositions; - private final TileMode mTileMode; - private int[] mGradient; - - protected GradientPaint(int[] colors, float[] positions, TileMode tileMode) { - mColors = colors; - mPositions = positions; - mTileMode = tileMode; - } - - @Override - public int getTransparency() { - return java.awt.Paint.TRANSLUCENT; - } - - /** - * Pre-computes the colors for the gradient. This must be called once before any call - * to {@link #getGradientColor(float)} - */ - protected void precomputeGradientColors() { - if (mGradient == null) { - // actually create an array with an extra size, so that we can really go - // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0 - mGradient = new int[GRADIENT_SIZE+1]; - - int prevPos = 0; - int nextPos = 1; - for (int i = 0 ; i <= GRADIENT_SIZE ; i++) { - // compute current position - float currentPos = (float)i/GRADIENT_SIZE; - while (currentPos > mPositions[nextPos]) { - prevPos = nextPos++; - } - - float percent = (currentPos - mPositions[prevPos]) / - (mPositions[nextPos] - mPositions[prevPos]); - - mGradient[i] = computeColor(mColors[prevPos], mColors[nextPos], percent); - } - } - } - - /** - * Returns the color based on the position in the gradient. - * <var>pos</var> can be anything, even < 0 or > > 1, as the gradient - * will use {@link TileMode} value to convert it into a [0,1] value. - */ - protected int getGradientColor(float pos) { - if (pos < 0.f) { - if (mTileMode != null) { - switch (mTileMode) { - case CLAMP: - pos = 0.f; - break; - case REPEAT: - // remove the integer part to stay in the [0,1] range. - // we also need to invert the value from [-1,0] to [0, 1] - pos = pos - (float)Math.floor(pos); - break; - case MIRROR: - // this is the same as the positive side, just make the value positive - // first. - pos = Math.abs(pos); - - // get the integer and the decimal part - int intPart = (int)Math.floor(pos); - pos = pos - intPart; - // 0 -> 1 : normal order - // 1 -> 2: mirrored - // etc.. - // this means if the intpart is odd we invert - if ((intPart % 2) == 1) { - pos = 1.f - pos; - } - break; - } - } else { - pos = 0.0f; - } - } else if (pos > 1f) { - if (mTileMode != null) { - switch (mTileMode) { - case CLAMP: - pos = 1.f; - break; - case REPEAT: - // remove the integer part to stay in the [0,1] range - pos = pos - (float)Math.floor(pos); - break; - case MIRROR: - // get the integer and the decimal part - int intPart = (int)Math.floor(pos); - pos = pos - intPart; - // 0 -> 1 : normal order - // 1 -> 2: mirrored - // etc.. - // this means if the intpart is odd we invert - if ((intPart % 2) == 1) { - pos = 1.f - pos; - } - break; - } - } else { - pos = 1.0f; - } - } - - int index = (int)((pos * GRADIENT_SIZE) + .5); - - return mGradient[index]; - } - - /** - * Returns the color between c1, and c2, based on the percent of the distance - * between c1 and c2. - */ - private int computeColor(int c1, int c2, float percent) { - int a = computeChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent); - int r = computeChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent); - int g = computeChannel((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF, percent); - int b = computeChannel((c1 ) & 0xFF, (c2 ) & 0xFF, percent); - return a << 24 | r << 16 | g << 8 | b; - } - - /** - * Returns the channel value between 2 values based on the percent of the distance between - * the 2 values.. - */ - private int computeChannel(int c1, int c2, float percent) { - return c1 + (int)((percent * (c2-c1)) + .5); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java deleted file mode 100644 index 51e0576..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.LayerRasterizer - * - * Through the layoutlib_create tool, the original native methods of LayerRasterizer have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original LayerRasterizer class. - * - * Because this extends {@link Rasterizer_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link Rasterizer_Delegate}. - * - * @see Rasterizer_Delegate - * - */ -public class LayerRasterizer_Delegate extends Rasterizer_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Layer Rasterizers are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeConstructor() { - LayerRasterizer_Delegate newDelegate = new LayerRasterizer_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nativeAddLayer(int native_layer, int native_paint, float dx, float dy) { - - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java deleted file mode 100644 index 0ee883d..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.LightingColorFilter - * - * Through the layoutlib_create tool, the original native methods of LightingColorFilter have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original LightingColorFilter class. - * - * Because this extends {@link ColorFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link ColorFilter_Delegate}. - * - * @see ColorFilter_Delegate - * - */ -public class LightingColorFilter_Delegate extends ColorFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Lighting Color Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int native_CreateLightingFilter(int mul, int add) { - LightingColorFilter_Delegate newDelegate = new LightingColorFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nCreateLightingFilter(int nativeFilter, int mul, int add) { - // pass - return 0; - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java deleted file mode 100644 index f117fca..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Shader.TileMode; - -/** - * Delegate implementing the native methods of android.graphics.LinearGradient - * - * Through the layoutlib_create tool, the original native methods of LinearGradient have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original LinearGradient class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public final class LinearGradient_Delegate extends Gradient_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate1(LinearGradient thisGradient, - float x0, float y0, float x1, float y1, - int colors[], float positions[], int tileMode) { - LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1, - colors, positions, Shader_Delegate.getTileMode(tileMode)); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nativeCreate2(LinearGradient thisGradient, - float x0, float y0, float x1, float y1, - int color0, int color1, int tileMode) { - return nativeCreate1(thisGradient, - x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/, - tileMode); - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate1(LinearGradient thisGradient, - int native_shader, float x0, float y0, float x1, float y1, - int colors[], float positions[], int tileMode) { - // nothing to be done here. - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate2(LinearGradient thisGradient, - int native_shader, float x0, float y0, float x1, float y1, - int color0, int color1, int tileMode) { - // nothing to be done here. - return 0; - } - - // ---- Private delegate/helper methods ---- - - /** - * Create a shader that draws a linear gradient along a line. - * - * @param x0 The x-coordinate for the start of the gradient line - * @param y0 The y-coordinate for the start of the gradient line - * @param x1 The x-coordinate for the end of the gradient line - * @param y1 The y-coordinate for the end of the gradient line - * @param colors The colors to be distributed along the gradient line - * @param positions May be null. The relative positions [0..1] of each - * corresponding color in the colors array. If this is null, the - * the colors are distributed evenly along the gradient line. - * @param tile The Shader tiling mode - */ - private LinearGradient_Delegate(float x0, float y0, float x1, float y1, - int colors[], float positions[], TileMode tile) { - super(colors, positions); - mJavaPaint = new LinearGradientPaint(x0, y0, x1, y1, mColors, mPositions, tile); - } - - // ---- Custom Java Paint ---- - /** - * Linear Gradient (Java) Paint able to handle more than 2 points, as - * {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile - * modes. - */ - private class LinearGradientPaint extends GradientPaint { - - private final float mX0; - private final float mY0; - private final float mDx; - private final float mDy; - private final float mDSize2; - - public LinearGradientPaint(float x0, float y0, float x1, float y1, int colors[], - float positions[], TileMode tile) { - super(colors, positions, tile); - mX0 = x0; - mY0 = y0; - mDx = x1 - x0; - mDy = y1 - y0; - mDSize2 = mDx * mDx + mDy * mDy; - } - - @Override - public java.awt.PaintContext createContext( - java.awt.image.ColorModel colorModel, - java.awt.Rectangle deviceBounds, - java.awt.geom.Rectangle2D userBounds, - java.awt.geom.AffineTransform xform, - java.awt.RenderingHints hints) { - precomputeGradientColors(); - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in LinearGradient", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in LinearGradient", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new LinearGradientPaintContext(canvasMatrix, localMatrix, colorModel); - } - - private class LinearGradientPaintContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - private LinearGradientPaintContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel; - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.ColorModel getColorModel() { - return mColorModel; - } - - @Override - public java.awt.image.Raster getRaster(int x, int y, int w, int h) { - java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h, - java.awt.image.BufferedImage.TYPE_INT_ARGB); - - int[] data = new int[w*h]; - - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix. - pt1[0] = pt2[0]; - pt1[1] = pt2[1]; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - data[index++] = getColor(pt2[0], pt2[1]); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - } - - /** - * Returns a color for an arbitrary point. - */ - private int getColor(float x, float y) { - float pos; - if (mDx == 0) { - pos = (y - mY0) / mDy; - } else if (mDy == 0) { - pos = (x - mX0) / mDx; - } else { - // find the x position on the gradient vector. - float _x = (mDx*mDy*(y-mY0) + mDy*mDy*mX0 + mDx*mDx*x) / mDSize2; - // from it get the position relative to the vector - pos = (_x - mX0) / mDx; - } - - return getGradientColor(pos); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java deleted file mode 100644 index c2f27e4..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.MaskFilter - * - * Through the layoutlib_create tool, the original native methods of MaskFilter have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original MaskFilter class. - * - * This also serve as a base class for all MaskFilter delegate classes. - * - * @see DelegateManager - * - */ -public abstract class MaskFilter_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<MaskFilter_Delegate> sManager = - new DelegateManager<MaskFilter_Delegate>(MaskFilter_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static MaskFilter_Delegate getDelegate(int nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(int native_filter) { - sManager.removeJavaReferenceFor(native_filter); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java deleted file mode 100644 index 5df2a21..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Matrix.ScaleToFit; - -import java.awt.geom.AffineTransform; -import java.awt.geom.NoninvertibleTransformException; - -/** - * Delegate implementing the native methods of android.graphics.Matrix - * - * Through the layoutlib_create tool, the original native methods of Matrix have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Matrix class. - * - * @see DelegateManager - * - */ -public final class Matrix_Delegate { - - private final static int MATRIX_SIZE = 9; - - // ---- delegate manager ---- - private static final DelegateManager<Matrix_Delegate> sManager = - new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class); - - // ---- delegate data ---- - private float mValues[] = new float[MATRIX_SIZE]; - - // ---- Public Helper methods ---- - - public static Matrix_Delegate getDelegate(int native_instance) { - return sManager.getDelegate(native_instance); - } - - /** - * Returns an {@link AffineTransform} matching the given Matrix. - */ - public static AffineTransform getAffineTransform(Matrix m) { - Matrix_Delegate delegate = sManager.getDelegate(m.native_instance); - if (delegate == null) { - return null; - } - - return delegate.getAffineTransform(); - } - - public static boolean hasPerspective(Matrix m) { - Matrix_Delegate delegate = sManager.getDelegate(m.native_instance); - if (delegate == null) { - return false; - } - - return delegate.hasPerspective(); - } - - /** - * Sets the content of the matrix with the content of another matrix. - */ - public void set(Matrix_Delegate matrix) { - System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE); - } - - /** - * Sets the content of the matrix with the content of another matrix represented as an array - * of values. - */ - public void set(float[] values) { - System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE); - } - - /** - * Resets the matrix to be the identity matrix. - */ - public void reset() { - reset(mValues); - } - - /** - * Returns whether or not the matrix is identity. - */ - public boolean isIdentity() { - for (int i = 0, k = 0; i < 3; i++) { - for (int j = 0; j < 3; j++, k++) { - if (mValues[k] != ((i==j) ? 1 : 0)) { - return false; - } - } - } - - return true; - } - - public static float[] makeValues(AffineTransform matrix) { - float[] values = new float[MATRIX_SIZE]; - values[0] = (float) matrix.getScaleX(); - values[1] = (float) matrix.getShearX(); - values[2] = (float) matrix.getTranslateX(); - values[3] = (float) matrix.getShearY(); - values[4] = (float) matrix.getScaleY(); - values[5] = (float) matrix.getTranslateY(); - values[6] = 0.f; - values[7] = 0.f; - values[8] = 1.f; - - return values; - } - - public static Matrix_Delegate make(AffineTransform matrix) { - return new Matrix_Delegate(makeValues(matrix)); - } - - public boolean mapRect(RectF dst, RectF src) { - // array with 4 corners - float[] corners = new float[] { - src.left, src.top, - src.right, src.top, - src.right, src.bottom, - src.left, src.bottom, - }; - - // apply the transform to them. - mapPoints(corners); - - // now put the result in the rect. We take the min/max of Xs and min/max of Ys - dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6])); - dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6])); - - dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7])); - dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); - - - return (computeTypeMask() & kRectStaysRect_Mask) != 0; - } - - - /** - * Returns an {@link AffineTransform} matching the matrix. - */ - public AffineTransform getAffineTransform() { - return getAffineTransform(mValues); - } - - public boolean hasPerspective() { - return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1); - } - - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int native_create(int native_src_or_zero) { - // create the delegate - Matrix_Delegate newDelegate = new Matrix_Delegate(); - - // copy from values if needed. - if (native_src_or_zero > 0) { - Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero); - if (oldDelegate != null) { - System.arraycopy( - oldDelegate.mValues, 0, - newDelegate.mValues, 0, - MATRIX_SIZE); - } - } - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static boolean native_isIdentity(int native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - return d.isIdentity(); - } - - @LayoutlibDelegate - /*package*/ static boolean native_rectStaysRect(int native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return true; - } - - return (d.computeTypeMask() & kRectStaysRect_Mask) != 0; - } - - @LayoutlibDelegate - /*package*/ static void native_reset(int native_object) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - reset(d.mValues); - } - - @LayoutlibDelegate - /*package*/ static void native_set(int native_object, int other) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - Matrix_Delegate src = sManager.getDelegate(other); - if (src == null) { - return; - } - - System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE); - } - - @LayoutlibDelegate - /*package*/ static void native_setTranslate(int native_object, float dx, float dy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - setTranslate(d.mValues, dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void native_setScale(int native_object, float sx, float sy, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues = getScale(sx, sy, px, py); - } - - @LayoutlibDelegate - /*package*/ static void native_setScale(int native_object, float sx, float sy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues[0] = sx; - d.mValues[1] = 0; - d.mValues[2] = 0; - d.mValues[3] = 0; - d.mValues[4] = sy; - d.mValues[5] = 0; - d.mValues[6] = 0; - d.mValues[7] = 0; - d.mValues[8] = 1; - } - - @LayoutlibDelegate - /*package*/ static void native_setRotate(int native_object, float degrees, float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues = getRotate(degrees, px, py); - } - - @LayoutlibDelegate - /*package*/ static void native_setRotate(int native_object, float degrees) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - setRotate(d.mValues, degrees); - } - - @LayoutlibDelegate - /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - setTranslate(d.mValues, -px, -py); - - // scale - d.postTransform(getRotate(sinValue, cosValue)); - // translate back the pivot - d.postTransform(getTranslate(px, py)); - } - - @LayoutlibDelegate - /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - setRotate(d.mValues, sinValue, cosValue); - } - - @LayoutlibDelegate - /*package*/ static void native_setSkew(int native_object, float kx, float ky, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues = getSkew(kx, ky, px, py); - } - - @LayoutlibDelegate - /*package*/ static void native_setSkew(int native_object, float kx, float ky) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - d.mValues[0] = 1; - d.mValues[1] = kx; - d.mValues[2] = -0; - d.mValues[3] = ky; - d.mValues[4] = 1; - d.mValues[5] = 0; - d.mValues[6] = 0; - d.mValues[7] = 0; - d.mValues[8] = 1; - } - - @LayoutlibDelegate - /*package*/ static boolean native_setConcat(int native_object, int a, int b) { - if (a == native_object) { - return native_preConcat(native_object, b); - } else if (b == native_object) { - return native_postConcat(native_object, a); - } - - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - Matrix_Delegate a_mtx = sManager.getDelegate(a); - if (a_mtx == null) { - return false; - } - - Matrix_Delegate b_mtx = sManager.getDelegate(b); - if (b_mtx == null) { - return false; - } - - multiply(d.mValues, a_mtx.mValues, b_mtx.mValues); - - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preTranslate(int native_object, float dx, float dy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.preTransform(getTranslate(dx, dy)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preScale(int native_object, float sx, float sy, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.preTransform(getScale(sx, sy, px, py)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preScale(int native_object, float sx, float sy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.preTransform(getScale(sx, sy)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preRotate(int native_object, float degrees, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.preTransform(getRotate(degrees, px, py)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preRotate(int native_object, float degrees) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - double rad = Math.toRadians(degrees); - float sin = (float)Math.sin(rad); - float cos = (float)Math.cos(rad); - - d.preTransform(getRotate(sin, cos)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preSkew(int native_object, float kx, float ky, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.preTransform(getSkew(kx, ky, px, py)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preSkew(int native_object, float kx, float ky) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.preTransform(getSkew(kx, ky)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_preConcat(int native_object, int other_matrix) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - Matrix_Delegate other = sManager.getDelegate(other_matrix); - if (other == null) { - return false; - } - - d.preTransform(other.mValues); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postTranslate(int native_object, float dx, float dy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getTranslate(dx, dy)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postScale(int native_object, float sx, float sy, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getScale(sx, sy, px, py)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postScale(int native_object, float sx, float sy) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getScale(sx, sy)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postRotate(int native_object, float degrees, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getRotate(degrees, px, py)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postRotate(int native_object, float degrees) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getRotate(degrees)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postSkew(int native_object, float kx, float ky, - float px, float py) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getSkew(kx, ky, px, py)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postSkew(int native_object, float kx, float ky) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - d.postTransform(getSkew(kx, ky)); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_postConcat(int native_object, int other_matrix) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - Matrix_Delegate other = sManager.getDelegate(other_matrix); - if (other == null) { - return false; - } - - d.postTransform(other.mValues); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_setRectToRect(int native_object, RectF src, - RectF dst, int stf) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - if (src.isEmpty()) { - reset(d.mValues); - return false; - } - - if (dst.isEmpty()) { - d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5] - = d.mValues[6] = d.mValues[7] = 0; - d.mValues[8] = 1; - } else { - float tx, sx = dst.width() / src.width(); - float ty, sy = dst.height() / src.height(); - boolean xLarger = false; - - if (stf != ScaleToFit.FILL.nativeInt) { - if (sx > sy) { - xLarger = true; - sx = sy; - } else { - sy = sx; - } - } - - tx = dst.left - src.left * sx; - ty = dst.top - src.top * sy; - if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) { - float diff; - - if (xLarger) { - diff = dst.width() - src.width() * sy; - } else { - diff = dst.height() - src.height() * sy; - } - - if (stf == ScaleToFit.CENTER.nativeInt) { - diff = diff / 2; - } - - if (xLarger) { - tx += diff; - } else { - ty += diff; - } - } - - d.mValues[0] = sx; - d.mValues[4] = sy; - d.mValues[2] = tx; - d.mValues[5] = ty; - d.mValues[1] = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0; - - } - // shared cleanup - d.mValues[8] = 1; - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex, - float[] dst, int dstIndex, int pointCount) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Matrix.setPolyToPoly is not supported.", - null, null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean native_invert(int native_object, int inverse) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - Matrix_Delegate inv_mtx = sManager.getDelegate(inverse); - if (inv_mtx == null) { - return false; - } - - try { - AffineTransform affineTransform = d.getAffineTransform(); - AffineTransform inverseTransform = affineTransform.createInverse(); - inv_mtx.mValues[0] = (float)inverseTransform.getScaleX(); - inv_mtx.mValues[1] = (float)inverseTransform.getShearX(); - inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX(); - inv_mtx.mValues[3] = (float)inverseTransform.getScaleX(); - inv_mtx.mValues[4] = (float)inverseTransform.getShearY(); - inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY(); - - return true; - } catch (NoninvertibleTransformException e) { - return false; - } - } - - @LayoutlibDelegate - /*package*/ static void native_mapPoints(int native_object, float[] dst, int dstIndex, - float[] src, int srcIndex, int ptCount, boolean isPts) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - if (isPts) { - d.mapPoints(dst, dstIndex, src, srcIndex, ptCount); - } else { - d.mapVectors(dst, dstIndex, src, srcIndex, ptCount); - } - } - - @LayoutlibDelegate - /*package*/ static boolean native_mapRect(int native_object, RectF dst, RectF src) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - - return d.mapRect(dst, src); - } - - @LayoutlibDelegate - /*package*/ static float native_mapRadius(int native_object, float radius) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return 0.f; - } - - float[] src = new float[] { radius, 0.f, 0.f, radius }; - d.mapVectors(src, 0, src, 0, 2); - - float l1 = getPointLength(src, 0); - float l2 = getPointLength(src, 2); - - return (float) Math.sqrt(l1 * l2); - } - - @LayoutlibDelegate - /*package*/ static void native_getValues(int native_object, float[] values) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE); - } - - @LayoutlibDelegate - /*package*/ static void native_setValues(int native_object, float[] values) { - Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return; - } - - System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE); - } - - @LayoutlibDelegate - /*package*/ static boolean native_equals(int native_a, int native_b) { - Matrix_Delegate a = sManager.getDelegate(native_a); - if (a == null) { - return false; - } - - Matrix_Delegate b = sManager.getDelegate(native_b); - if (b == null) { - return false; - } - - for (int i = 0 ; i < MATRIX_SIZE ; i++) { - if (a.mValues[i] != b.mValues[i]) { - return false; - } - } - - return true; - } - - @LayoutlibDelegate - /*package*/ static void finalizer(int native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - // ---- Private helper methods ---- - - /*package*/ static AffineTransform getAffineTransform(float[] matrix) { - // the AffineTransform constructor takes the value in a different order - // for a matrix [ 0 1 2 ] - // [ 3 4 5 ] - // the order is 0, 3, 1, 4, 2, 5... - return new AffineTransform( - matrix[0], matrix[3], matrix[1], - matrix[4], matrix[2], matrix[5]); - } - - /** - * Reset a matrix to the identity - */ - private static void reset(float[] mtx) { - for (int i = 0, k = 0; i < 3; i++) { - for (int j = 0; j < 3; j++, k++) { - mtx[k] = ((i==j) ? 1 : 0); - } - } - } - - @SuppressWarnings("unused") - private final static int kIdentity_Mask = 0; - private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation - private final static int kScale_Mask = 0x02; //!< set if the matrix has X or Y scale - private final static int kAffine_Mask = 0x04; //!< set if the matrix skews or rotates - private final static int kPerspective_Mask = 0x08; //!< set if the matrix is in perspective - 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 | - kAffine_Mask | - kPerspective_Mask | - kRectStaysRect_Mask; - - // these guys align with the masks, so we can compute a mask from a variable 0/1 - @SuppressWarnings("unused") - private final static int kTranslate_Shift = 0; - @SuppressWarnings("unused") - private final static int kScale_Shift = 1; - @SuppressWarnings("unused") - private final static int kAffine_Shift = 2; - @SuppressWarnings("unused") - private final static int kPerspective_Shift = 3; - private final static int kRectStaysRect_Shift = 4; - - private int computeTypeMask() { - int mask = 0; - - 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; - } - - private Matrix_Delegate() { - reset(); - } - - private Matrix_Delegate(float[] values) { - System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE); - } - - /** - * Adds the given transformation to the current Matrix - * <p/>This in effect does this = this*matrix - * @param matrix - */ - private void postTransform(float[] matrix) { - float[] tmp = new float[9]; - multiply(tmp, mValues, matrix); - mValues = tmp; - } - - /** - * Adds the given transformation to the current Matrix - * <p/>This in effect does this = matrix*this - * @param matrix - */ - private void preTransform(float[] matrix) { - float[] tmp = new float[9]; - multiply(tmp, matrix, mValues); - mValues = tmp; - } - - /** - * 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 - * two arrays represent their "points" as pairs of floats [x, y]. - * - * @param dst The array of dst points (x,y pairs) - * @param dstIndex The index of the first [x,y] pair of dst floats - * @param src The array of src points (x,y pairs) - * @param srcIndex The index of the first [x,y] pair of src floats - * @param pointCount The number of points (x,y pairs) to transform - */ - - private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, - int pointCount) { - final int count = pointCount * 2; - - float[] tmpDest = dst; - boolean inPlace = dst == src; - if (inPlace) { - tmpDest = new float[dstIndex + count]; - } - - for (int i = 0 ; i < count ; i += 2) { - // just in case we are doing in place, we better put this in temp vars - float x = mValues[0] * src[i + srcIndex] + - mValues[1] * src[i + srcIndex + 1] + - mValues[2]; - float y = mValues[3] * src[i + srcIndex] + - mValues[4] * src[i + srcIndex + 1] + - mValues[5]; - - tmpDest[i + dstIndex] = x; - tmpDest[i + dstIndex + 1] = y; - } - - if (inPlace) { - System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count); - } - } - - /** - * Apply this matrix to the array of 2D points, and write the transformed - * points back into the array - * - * @param pts The array [x0, y0, x1, y1, ...] of points to transform. - */ - - private void mapPoints(float[] pts) { - mapPoints(pts, 0, pts, 0, pts.length >> 1); - } - - private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) { - if (hasPerspective()) { - // transform the (0,0) point - float[] origin = new float[] { 0.f, 0.f}; - mapPoints(origin); - - // translate the vector data as points - mapPoints(dst, dstIndex, src, srcIndex, ptCount); - - // then substract the transformed origin. - final int count = ptCount * 2; - for (int i = 0 ; i < count ; i += 2) { - dst[dstIndex + i] = dst[dstIndex + i] - origin[0]; - dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1]; - } - } else { - // make a copy of the matrix - Matrix_Delegate copy = new Matrix_Delegate(mValues); - - // remove the translation - setTranslate(copy.mValues, 0, 0); - - // map the content as points. - copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount); - } - } - - private static float getPointLength(float[] src, int index) { - return (float) Math.sqrt(src[index] * src[index] + src[index + 1] * src[index + 1]); - } - - /** - * multiply two matrices and store them in a 3rd. - * <p/>This in effect does dest = a*b - * dest cannot be the same as a or b. - */ - /*package*/ static void multiply(float dest[], float[] a, float[] b) { - // first row - dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6]; - dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7]; - dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8]; - - // 2nd row - dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6]; - dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7]; - dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8]; - - // 3rd row - dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6]; - dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7]; - dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8]; - } - - /** - * Returns a matrix that represents a given translate - * @param dx - * @param dy - * @return - */ - /*package*/ static float[] getTranslate(float dx, float dy) { - return setTranslate(new float[9], dx, dy); - } - - /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) { - dest[0] = 1; - dest[1] = 0; - dest[2] = dx; - dest[3] = 0; - dest[4] = 1; - dest[5] = dy; - dest[6] = 0; - dest[7] = 0; - dest[8] = 1; - return dest; - } - - /*package*/ static float[] getScale(float sx, float sy) { - return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; - } - - /** - * Returns a matrix that represents the given scale info. - * @param sx - * @param sy - * @param px - * @param py - */ - /*package*/ static float[] getScale(float sx, float sy, float px, float py) { - float[] tmp = new float[9]; - float[] tmp2 = new float[9]; - - // TODO: do it in one pass - - // translate tmp so that the pivot is in 0,0 - setTranslate(tmp, -px, -py); - - // scale into tmp2 - multiply(tmp2, tmp, getScale(sx, sy)); - - // translate back the pivot back into tmp - multiply(tmp, tmp2, getTranslate(px, py)); - - return tmp; - } - - - /*package*/ static float[] getRotate(float degrees) { - double rad = Math.toRadians(degrees); - float sin = (float)Math.sin(rad); - float cos = (float)Math.cos(rad); - - return getRotate(sin, cos); - } - - /*package*/ static float[] getRotate(float sin, float cos) { - return setRotate(new float[9], sin, cos); - } - - /*package*/ static float[] setRotate(float[] dest, float degrees) { - double rad = Math.toRadians(degrees); - float sin = (float)Math.sin(rad); - float cos = (float)Math.cos(rad); - - return setRotate(dest, sin, cos); - } - - /*package*/ static float[] setRotate(float[] dest, float sin, float cos) { - dest[0] = cos; - dest[1] = -sin; - dest[2] = 0; - dest[3] = sin; - dest[4] = cos; - dest[5] = 0; - dest[6] = 0; - dest[7] = 0; - dest[8] = 1; - return dest; - } - - /*package*/ static float[] getRotate(float degrees, float px, float py) { - float[] tmp = new float[9]; - float[] tmp2 = new float[9]; - - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - setTranslate(tmp, -px, -py); - - // rotate into tmp2 - double rad = Math.toRadians(degrees); - float cos = (float)Math.cos(rad); - float sin = (float)Math.sin(rad); - multiply(tmp2, tmp, getRotate(sin, cos)); - - // translate back the pivot back into tmp - multiply(tmp, tmp2, getTranslate(px, py)); - - return tmp; - } - - /*package*/ static float[] getSkew(float kx, float ky) { - return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }; - } - - /*package*/ static float[] getSkew(float kx, float ky, float px, float py) { - float[] tmp = new float[9]; - float[] tmp2 = new float[9]; - - // TODO: do it in one pass - - // translate so that the pivot is in 0,0 - setTranslate(tmp, -px, -py); - - // skew into tmp2 - multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); - // translate back the pivot back into tmp - multiply(tmp, tmp2, getTranslate(px, py)); - - return tmp; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java deleted file mode 100644 index be27b54..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.GcSnapshot; -import com.android.ninepatch.NinePatchChunk; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.drawable.NinePatchDrawable; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.lang.ref.SoftReference; -import java.util.HashMap; -import java.util.Map; - -/** - * Delegate implementing the native methods of android.graphics.NinePatch - * - * Through the layoutlib_create tool, the original native methods of NinePatch have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -public final class NinePatch_Delegate { - - /** - * Cache map for {@link NinePatchChunk}. - * When the chunks are created they are serialized into a byte[], and both are put - * in the cache, using a {@link SoftReference} for the chunk. The default Java classes - * for {@link NinePatch} and {@link NinePatchDrawable} only reference to the byte[] data, and - * provide this for drawing. - * Using the cache map allows us to not have to deserialize the byte[] back into a - * {@link NinePatchChunk} every time a rendering is done. - */ - private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache = - new HashMap<byte[], SoftReference<NinePatchChunk>>(); - - // ---- Public Helper methods ---- - - /** - * Serializes the given chunk. - * - * @return the serialized data for the chunk. - */ - public static byte[] serialize(NinePatchChunk chunk) { - // serialize the chunk to get a byte[] - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(baos); - oos.writeObject(chunk); - } catch (IOException e) { - Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e, null /*data*/); - return null; - } finally { - if (oos != null) { - try { - oos.close(); - } catch (IOException e) { - } - } - } - - // get the array and add it to the cache - byte[] array = baos.toByteArray(); - sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); - return array; - } - - /** - * Returns a {@link NinePatchChunk} object for the given serialized representation. - * - * If the chunk is present in the cache then the object from the cache is returned, otherwise - * the array is deserialized into a {@link NinePatchChunk} object. - * - * @param array the serialized representation of the chunk. - * @return the NinePatchChunk or null if deserialization failed. - */ - public static NinePatchChunk getChunk(byte[] array) { - SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array); - NinePatchChunk chunk = chunkRef.get(); - if (chunk == null) { - ByteArrayInputStream bais = new ByteArrayInputStream(array); - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(bais); - chunk = (NinePatchChunk) ois.readObject(); - - // put back the chunk in the cache - if (chunk != null) { - sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); - } - } catch (IOException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk content.", e, null /*data*/); - return null; - } catch (ClassNotFoundException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk class.", e, null /*data*/); - return null; - } finally { - if (ois != null) { - try { - ois.close(); - } catch (IOException e) { - } - } - } - } - - return chunk; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static boolean isNinePatchChunk(byte[] chunk) { - NinePatchChunk chunkObject = getChunk(chunk); - if (chunkObject != null) { - return true; - } - - return false; - } - - @LayoutlibDelegate - /*package*/ static void validateNinePatchChunk(int bitmap, byte[] chunk) { - // the default JNI implementation only checks that the byte[] has the same - // size as the C struct it represent. Since we cannot do the same check (serialization - // will return different size depending on content), we do nothing. - } - - @LayoutlibDelegate - /*package*/ static void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance, - byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) { - draw(canvas_instance, - (int) loc.left, (int) loc.top, (int) loc.width(), (int) loc.height(), - bitmap_instance, c, paint_instance_or_null, - destDensity, srcDensity); - } - - @LayoutlibDelegate - /*package*/ static void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance, - byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) { - draw(canvas_instance, - loc.left, loc.top, loc.width(), loc.height(), - bitmap_instance, c, paint_instance_or_null, - destDensity, srcDensity); - } - - @LayoutlibDelegate - /*package*/ static int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location) { - return 0; - } - - // ---- Private Helper methods ---- - - private static void draw(int canvas_instance, - final int left, final int top, final int right, final int bottom, - int bitmap_instance, byte[] c, int paint_instance_or_null, - final int destDensity, final int srcDensity) { - // get the delegate from the native int. - final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance); - if (bitmap_delegate == null) { - return; - } - - if (c == null) { - // not a 9-patch? - BufferedImage image = bitmap_delegate.getImage(); - Canvas_Delegate.native_drawBitmap(canvas_instance, bitmap_instance, - new Rect(0, 0, image.getWidth(), image.getHeight()), - new Rect(left, top, right, bottom), - paint_instance_or_null, destDensity, srcDensity); - return; - } - - final NinePatchChunk chunkObject = getChunk(c); - assert chunkObject != null; - if (chunkObject == null) { - return; - } - - Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance); - if (canvas_delegate == null) { - return; - } - - // this one can be null - Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null); - - canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() { - @Override - public void draw(Graphics2D graphics, Paint_Delegate paint) { - chunkObject.draw(bitmap_delegate.getImage(), graphics, - left, top, right - left, bottom - top, destDensity, srcDensity); - } - }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/); - - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java deleted file mode 100644 index 71d346a..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.PaintFlagsDrawFilter - * - * Through the layoutlib_create tool, the original native methods of PaintFlagsDrawFilter have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original PaintFlagsDrawFilter class. - * - * Because this extends {@link DrawFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the DrawFilter classes will be added to the manager owned by - * {@link DrawFilter_Delegate}. - * - * @see DrawFilter_Delegate - * - */ -public class PaintFlagsDrawFilter_Delegate extends DrawFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Paint Flags Draw Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeConstructor(int clearBits, int setBits) { - PaintFlagsDrawFilter_Delegate newDelegate = new PaintFlagsDrawFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java deleted file mode 100644 index c9c9800..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Paint.FontMetrics; -import android.graphics.Paint.FontMetricsInt; -import android.text.TextUtils; - -import java.awt.BasicStroke; -import java.awt.Font; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.Toolkit; -import java.awt.font.FontRenderContext; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -/** - * Delegate implementing the native methods of android.graphics.Paint - * - * Through the layoutlib_create tool, the original native methods of Paint have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Paint class. - * - * @see DelegateManager - * - */ -public class Paint_Delegate { - - /** - * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}. - */ - /*package*/ static final class FontInfo { - Font mFont; - java.awt.FontMetrics mMetrics; - } - - // ---- delegate manager ---- - private static final DelegateManager<Paint_Delegate> sManager = - new DelegateManager<Paint_Delegate>(Paint_Delegate.class); - - // ---- delegate helper data ---- - private List<FontInfo> mFonts; - private final FontRenderContext mFontContext = new FontRenderContext( - new AffineTransform(), true, true); - - // ---- delegate data ---- - private int mFlags; - private int mColor; - private int mStyle; - private int mCap; - private int mJoin; - private int mTextAlign; - private Typeface_Delegate mTypeface; - private float mStrokeWidth; - private float mStrokeMiter; - private float mTextSize; - private float mTextScaleX; - private float mTextSkewX; - private int mHintingMode = Paint.HINTING_ON; - - private Xfermode_Delegate mXfermode; - private ColorFilter_Delegate mColorFilter; - private Shader_Delegate mShader; - private PathEffect_Delegate mPathEffect; - private MaskFilter_Delegate mMaskFilter; - private Rasterizer_Delegate mRasterizer; - - private Locale mLocale = Locale.getDefault(); - - - // ---- Public Helper methods ---- - - public static Paint_Delegate getDelegate(int native_paint) { - return sManager.getDelegate(native_paint); - } - - /** - * Returns the list of {@link Font} objects. The first item is the main font, the rest - * are fall backs for characters not present in the main font. - */ - public List<FontInfo> getFonts() { - return mFonts; - } - - public boolean isAntiAliased() { - return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0; - } - - public boolean isFilterBitmap() { - return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0; - } - - public int getStyle() { - return mStyle; - } - - public int getColor() { - return mColor; - } - - public int getAlpha() { - return mColor >>> 24; - } - - public void setAlpha(int alpha) { - mColor = (alpha << 24) | (mColor & 0x00FFFFFF); - } - - public int getTextAlign() { - return mTextAlign; - } - - public float getStrokeWidth() { - return mStrokeWidth; - } - - /** - * returns the value of stroke miter needed by the java api. - */ - public float getJavaStrokeMiter() { - float miter = mStrokeMiter * mStrokeWidth; - if (miter < 1.f) { - miter = 1.f; - } - return miter; - } - - public int getJavaCap() { - switch (Paint.sCapArray[mCap]) { - case BUTT: - return BasicStroke.CAP_BUTT; - case ROUND: - return BasicStroke.CAP_ROUND; - default: - case SQUARE: - return BasicStroke.CAP_SQUARE; - } - } - - public int getJavaJoin() { - switch (Paint.sJoinArray[mJoin]) { - default: - case MITER: - return BasicStroke.JOIN_MITER; - case ROUND: - return BasicStroke.JOIN_ROUND; - case BEVEL: - return BasicStroke.JOIN_BEVEL; - } - } - - public Stroke getJavaStroke() { - if (mPathEffect != null) { - if (mPathEffect.isSupported()) { - Stroke stroke = mPathEffect.getStroke(this); - assert stroke != null; - if (stroke != null) { - return stroke; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT, - mPathEffect.getSupportMessage(), - null, null /*data*/); - } - } - - // if no custom stroke as been set, set the default one. - return new BasicStroke( - getStrokeWidth(), - getJavaCap(), - getJavaJoin(), - getJavaStrokeMiter()); - } - - /** - * Returns the {@link Xfermode} delegate or null if none have been set - * - * @return the delegate or null. - */ - public Xfermode_Delegate getXfermode() { - return mXfermode; - } - - /** - * Returns the {@link ColorFilter} delegate or null if none have been set - * - * @return the delegate or null. - */ - public ColorFilter_Delegate getColorFilter() { - return mColorFilter; - } - - /** - * Returns the {@link Shader} delegate or null if none have been set - * - * @return the delegate or null. - */ - public Shader_Delegate getShader() { - return mShader; - } - - /** - * Returns the {@link MaskFilter} delegate or null if none have been set - * - * @return the delegate or null. - */ - public MaskFilter_Delegate getMaskFilter() { - return mMaskFilter; - } - - /** - * Returns the {@link Rasterizer} delegate or null if none have been set - * - * @return the delegate or null. - */ - public Rasterizer_Delegate getRasterizer() { - return mRasterizer; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int getFlags(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - return delegate.mFlags; - } - - - - @LayoutlibDelegate - /*package*/ static void setFlags(Paint thisPaint, int flags) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mFlags = flags; - } - - @LayoutlibDelegate - /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) { - setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter); - } - - @LayoutlibDelegate - /*package*/ static int getHinting(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return Paint.HINTING_ON; - } - - return delegate.mHintingMode; - } - - @LayoutlibDelegate - /*package*/ static void setHinting(Paint thisPaint, int mode) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mHintingMode = mode; - } - - @LayoutlibDelegate - /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) { - setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa); - } - - @LayoutlibDelegate - /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) { - setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText); - } - - @LayoutlibDelegate - /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) { - setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText); - } - - @LayoutlibDelegate - /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) { - setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText); - } - - @LayoutlibDelegate - /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) { - setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText); - } - - @LayoutlibDelegate - /*package*/ static void setDither(Paint thisPaint, boolean dither) { - setFlag(thisPaint, Paint.DITHER_FLAG, dither); - } - - @LayoutlibDelegate - /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) { - setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText); - } - - @LayoutlibDelegate - /*package*/ static int getColor(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - return delegate.mColor; - } - - @LayoutlibDelegate - /*package*/ static void setColor(Paint thisPaint, int color) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mColor = color; - } - - @LayoutlibDelegate - /*package*/ static int getAlpha(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - return delegate.getAlpha(); - } - - @LayoutlibDelegate - /*package*/ static void setAlpha(Paint thisPaint, int a) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.setAlpha(a); - } - - @LayoutlibDelegate - /*package*/ static float getStrokeWidth(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mStrokeWidth; - } - - @LayoutlibDelegate - /*package*/ static void setStrokeWidth(Paint thisPaint, float width) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mStrokeWidth = width; - } - - @LayoutlibDelegate - /*package*/ static float getStrokeMiter(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mStrokeMiter; - } - - @LayoutlibDelegate - /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mStrokeMiter = miter; - } - - @LayoutlibDelegate - /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy, - int color) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.setShadowLayer is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static float getTextSize(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mTextSize; - } - - @LayoutlibDelegate - /*package*/ static void setTextSize(Paint thisPaint, float textSize) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mTextSize = textSize; - delegate.updateFontObject(); - } - - @LayoutlibDelegate - /*package*/ static float getTextScaleX(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mTextScaleX; - } - - @LayoutlibDelegate - /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mTextScaleX = scaleX; - delegate.updateFontObject(); - } - - @LayoutlibDelegate - /*package*/ static float getTextSkewX(Paint thisPaint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 1.f; - } - - return delegate.mTextSkewX; - } - - @LayoutlibDelegate - /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - delegate.mTextSkewX = skewX; - delegate.updateFontObject(); - } - - @LayoutlibDelegate - /*package*/ static float ascent(Paint thisPaint) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics; - // Android expects negative ascent so we invert the value from Java. - return - javaMetrics.getAscent(); - } - - return 0; - } - - @LayoutlibDelegate - /*package*/ static float descent(Paint thisPaint) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics; - return javaMetrics.getDescent(); - } - - return 0; - - } - - @LayoutlibDelegate - /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - return delegate.getFontMetrics(metrics); - } - - @LayoutlibDelegate - /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics; - if (fmi != null) { - // Android expects negative ascent so we invert the value from Java. - fmi.top = - javaMetrics.getMaxAscent(); - fmi.ascent = - javaMetrics.getAscent(); - fmi.descent = javaMetrics.getDescent(); - fmi.bottom = javaMetrics.getMaxDescent(); - fmi.leading = javaMetrics.getLeading(); - } - - return javaMetrics.getHeight(); - } - - return 0; - } - - @LayoutlibDelegate - /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index, - int count, int bidiFlags) { - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - return delegate.measureText(text, index, count, bidiFlags); - } - - @LayoutlibDelegate - /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end, - int bidiFlags) { - return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags); - } - - @LayoutlibDelegate - /*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) { - return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags); - } - - @LayoutlibDelegate - /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count, - float maxWidth, int bidiFlags, float[] measuredWidth) { - - // get the delegate - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return 0; - } - - int inc = count > 0 ? 1 : -1; - - int measureIndex = 0; - float measureAcc = 0; - for (int i = index; i != index + count; i += inc, measureIndex++) { - int start, end; - if (i < index) { - start = i; - end = index; - } else { - start = index; - end = i; - } - - // measure from start to end - float res = delegate.measureText(text, start, end - start + 1, bidiFlags); - - if (measuredWidth != null) { - measuredWidth[measureIndex] = res; - } - - measureAcc += res; - if (res > maxWidth) { - // we should not return this char index, but since it's 0-based - // and we need to return a count, we simply return measureIndex; - return measureIndex; - } - - } - - return measureIndex; - } - - @LayoutlibDelegate - /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards, - float maxWidth, int bidiFlags, float[] measuredWidth) { - return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth, - bidiFlags, measuredWidth); - } - - @LayoutlibDelegate - /*package*/ static int native_init() { - Paint_Delegate newDelegate = new Paint_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int native_initWithPaint(int paint) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(paint); - if (delegate == null) { - return 0; - } - - Paint_Delegate newDelegate = new Paint_Delegate(delegate); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void native_reset(int native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.reset(); - } - - @LayoutlibDelegate - /*package*/ static void native_set(int native_dst, int native_src) { - // get the delegate from the native int. - Paint_Delegate delegate_dst = sManager.getDelegate(native_dst); - if (delegate_dst == null) { - return; - } - - // get the delegate from the native int. - Paint_Delegate delegate_src = sManager.getDelegate(native_src); - if (delegate_src == null) { - return; - } - - delegate_dst.set(delegate_src); - } - - @LayoutlibDelegate - /*package*/ static int native_getStyle(int native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mStyle; - } - - @LayoutlibDelegate - /*package*/ static void native_setStyle(int native_object, int style) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.mStyle = style; - } - - @LayoutlibDelegate - /*package*/ static int native_getStrokeCap(int native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mCap; - } - - @LayoutlibDelegate - /*package*/ static void native_setStrokeCap(int native_object, int cap) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.mCap = cap; - } - - @LayoutlibDelegate - /*package*/ static int native_getStrokeJoin(int native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mJoin; - } - - @LayoutlibDelegate - /*package*/ static void native_setStrokeJoin(int native_object, int join) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.mJoin = join; - } - - @LayoutlibDelegate - /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) { - Paint_Delegate paint = sManager.getDelegate(native_object); - if (paint == null) { - return false; - } - - Path_Delegate srcPath = Path_Delegate.getDelegate(src); - if (srcPath == null) { - return true; - } - - Path_Delegate dstPath = Path_Delegate.getDelegate(dst); - if (dstPath == null) { - return true; - } - - Stroke stroke = paint.getJavaStroke(); - Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape()); - - dstPath.setJavaShape(strokeShape); - - // FIXME figure out the return value? - return true; - } - - @LayoutlibDelegate - /*package*/ static int native_setShader(int native_object, int shader) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return shader; - } - - delegate.mShader = Shader_Delegate.getDelegate(shader); - - return shader; - } - - @LayoutlibDelegate - /*package*/ static int native_setColorFilter(int native_object, int filter) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return filter; - } - - delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);; - - // since none of those are supported, display a fidelity warning right away - if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER, - delegate.mColorFilter.getSupportMessage(), null, null /*data*/); - } - - return filter; - } - - @LayoutlibDelegate - /*package*/ static int native_setXfermode(int native_object, int xfermode) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return xfermode; - } - - delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode); - - return xfermode; - } - - @LayoutlibDelegate - /*package*/ static int native_setPathEffect(int native_object, int effect) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return effect; - } - - delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect); - - return effect; - } - - @LayoutlibDelegate - /*package*/ static int native_setMaskFilter(int native_object, int maskfilter) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return maskfilter; - } - - delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter); - - // since none of those are supported, display a fidelity warning right away - if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER, - delegate.mMaskFilter.getSupportMessage(), null, null /*data*/); - } - - return maskfilter; - } - - @LayoutlibDelegate - /*package*/ static int native_setTypeface(int native_object, int typeface) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - delegate.mTypeface = Typeface_Delegate.getDelegate(typeface); - delegate.updateFontObject(); - return typeface; - } - - @LayoutlibDelegate - /*package*/ static int native_setRasterizer(int native_object, int rasterizer) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return rasterizer; - } - - delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer); - - // since none of those are supported, display a fidelity warning right away - if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER, - delegate.mRasterizer.getSupportMessage(), null, null /*data*/); - } - - return rasterizer; - } - - @LayoutlibDelegate - /*package*/ static int native_getTextAlign(int native_object) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - return delegate.mTextAlign; - } - - @LayoutlibDelegate - /*package*/ static void native_setTextAlign(int native_object, int align) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.mTextAlign = align; - } - - @LayoutlibDelegate - /*package*/ static void native_setTextLocale(int native_object, String locale) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return; - } - - delegate.setTextLocale(locale); - } - - @LayoutlibDelegate - /*package*/ static int native_getTextWidths(int native_object, char[] text, int index, - int count, int bidiFlags, float[] widths) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0; - } - - if (delegate.mFonts.size() > 0) { - // FIXME: handle multi-char characters (see measureText) - float totalAdvance = 0; - for (int i = 0; i < count; i++) { - char c = text[i + index]; - boolean found = false; - for (FontInfo info : delegate.mFonts) { - if (info.mFont.canDisplay(c)) { - float adv = info.mMetrics.charWidth(c); - totalAdvance += adv; - if (widths != null) { - widths[i] = adv; - } - - found = true; - break; - } - } - - if (found == false) { - // no advance for this char. - if (widths != null) { - widths[i] = 0.f; - } - } - } - - return (int) totalAdvance; - } - - return 0; - } - - @LayoutlibDelegate - /*package*/ static int native_getTextWidths(int native_object, String text, int start, - int end, int bidiFlags, float[] widths) { - return native_getTextWidths(native_object, text.toCharArray(), start, end - start, - bidiFlags, widths); - } - - @LayoutlibDelegate - /* package */static int native_getTextGlyphs(int native_object, String text, int start, - int end, int contextStart, int contextEnd, int flags, char[] glyphs) { - // FIXME - return 0; - } - - @LayoutlibDelegate - /*package*/ static float native_getTextRunAdvances(int native_object, - char[] text, int index, int count, int contextIndex, int contextCount, - int flags, float[] advances, int advancesIndex) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(native_object); - if (delegate == null) { - return 0.f; - } - - if (delegate.mFonts.size() > 0) { - // FIXME: handle multi-char characters (see measureText) - float totalAdvance = 0; - for (int i = 0; i < count; i++) { - char c = text[i + index]; - boolean found = false; - for (FontInfo info : delegate.mFonts) { - if (info.mFont.canDisplay(c)) { - float adv = info.mMetrics.charWidth(c); - totalAdvance += adv; - if (advances != null) { - advances[i] = adv; - } - - found = true; - break; - } - } - - if (found == false) { - // no advance for this char. - if (advances != null) { - advances[i] = 0.f; - } - } - } - - return totalAdvance; - } - - return 0; - - } - - @LayoutlibDelegate - /*package*/ static float native_getTextRunAdvances(int native_object, - String text, int start, int end, int contextStart, int contextEnd, - int flags, float[] advances, int advancesIndex) { - // FIXME: support contextStart, contextEnd and direction flag - int count = end - start; - char[] buffer = TemporaryBuffer.obtain(count); - TextUtils.getChars(text, start, end, buffer, 0); - - return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart, - contextEnd - contextStart, flags, advances, advancesIndex); - } - - @LayoutlibDelegate - /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text, - int contextStart, int contextLength, int flags, int offset, int cursorOpt) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.getTextRunCursor is not supported.", null, null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text, - int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.getTextRunCursor is not supported.", null, null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*package*/ static void native_getTextPath(int native_object, int bidiFlags, - char[] text, int index, int count, float x, float y, int path) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.getTextPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void native_getTextPath(int native_object, int bidiFlags, - String text, int start, int end, float x, float y, int path) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Paint.getTextPath is not supported.", null, null /*data*/); - } - - @LayoutlibDelegate - /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start, - int end, int bidiFlags, Rect bounds) { - nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bidiFlags, - bounds); - } - - @LayoutlibDelegate - /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index, - int count, int bidiFlags, Rect bounds) { - - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(nativePaint); - if (delegate == null) { - return; - } - - // FIXME should test if the main font can display all those characters. - // See MeasureText - if (delegate.mFonts.size() > 0) { - FontInfo mainInfo = delegate.mFonts.get(0); - - Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count, - delegate.mFontContext); - bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight()); - } - } - - @LayoutlibDelegate - /*package*/ static void finalizer(int nativePaint) { - sManager.removeJavaReferenceFor(nativePaint); - } - - // ---- Private delegate/helper methods ---- - - /*package*/ Paint_Delegate() { - reset(); - } - - private Paint_Delegate(Paint_Delegate paint) { - set(paint); - } - - private void set(Paint_Delegate paint) { - mFlags = paint.mFlags; - mColor = paint.mColor; - mStyle = paint.mStyle; - mCap = paint.mCap; - mJoin = paint.mJoin; - mTextAlign = paint.mTextAlign; - mTypeface = paint.mTypeface; - mStrokeWidth = paint.mStrokeWidth; - mStrokeMiter = paint.mStrokeMiter; - mTextSize = paint.mTextSize; - mTextScaleX = paint.mTextScaleX; - mTextSkewX = paint.mTextSkewX; - mXfermode = paint.mXfermode; - mColorFilter = paint.mColorFilter; - mShader = paint.mShader; - mPathEffect = paint.mPathEffect; - mMaskFilter = paint.mMaskFilter; - mRasterizer = paint.mRasterizer; - mHintingMode = paint.mHintingMode; - updateFontObject(); - } - - private void reset() { - mFlags = Paint.DEFAULT_PAINT_FLAGS; - mColor = 0xFF000000; - mStyle = Paint.Style.FILL.nativeInt; - mCap = Paint.Cap.BUTT.nativeInt; - mJoin = Paint.Join.MITER.nativeInt; - mTextAlign = 0; - mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance); - mStrokeWidth = 1.f; - mStrokeMiter = 4.f; - mTextSize = 20.f; - mTextScaleX = 1.f; - mTextSkewX = 0.f; - mXfermode = null; - mColorFilter = null; - mShader = null; - mPathEffect = null; - mMaskFilter = null; - mRasterizer = null; - updateFontObject(); - mHintingMode = Paint.HINTING_ON; - } - - /** - * Update the {@link Font} object from the typeface, text size and scaling - */ - @SuppressWarnings("deprecation") - private void updateFontObject() { - if (mTypeface != null) { - // Get the fonts from the TypeFace object. - List<Font> fonts = mTypeface.getFonts(); - - // create new font objects as well as FontMetrics, based on the current text size - // and skew info. - ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size()); - for (Font font : fonts) { - FontInfo info = new FontInfo(); - info.mFont = font.deriveFont(mTextSize); - if (mTextScaleX != 1.0 || mTextSkewX != 0) { - // TODO: support skew - info.mFont = info.mFont.deriveFont(new AffineTransform( - mTextScaleX, mTextSkewX, 0, 1, 0, 0)); - } - info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont); - - infoList.add(info); - } - - mFonts = Collections.unmodifiableList(infoList); - } - } - - /*package*/ float measureText(char[] text, int index, int count, int bidiFlags) { - // TODO: find out what bidiFlags actually does. - - // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText - // Any change to this method should be reflected there as well - - if (mFonts.size() > 0) { - FontInfo mainFont = mFonts.get(0); - int i = index; - int lastIndex = index + count; - float total = 0f; - while (i < lastIndex) { - // always start with the main font. - int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); - if (upTo == -1) { - // shortcut to exit - return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i); - } else if (upTo > 0) { - total += mainFont.mMetrics.charsWidth(text, i, upTo - i); - i = upTo; - // don't call continue at this point. Since it is certain the main font - // cannot display the font a index upTo (now ==i), we move on to the - // fallback fonts directly. - } - - // no char supported, attempt to read the next char(s) with the - // fallback font. In this case we only test the first character - // and then go back to test with the main font. - // Special test for 2-char characters. - boolean foundFont = false; - for (int f = 1 ; f < mFonts.size() ; f++) { - FontInfo fontInfo = mFonts.get(f); - - // need to check that the font can display the character. We test - // differently if the char is a high surrogate. - int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; - upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); - if (upTo == -1) { - total += fontInfo.mMetrics.charsWidth(text, i, charCount); - i += charCount; - foundFont = true; - break; - - } - } - - // in case no font can display the char, measure it with the main font. - if (foundFont == false) { - int size = Character.isHighSurrogate(text[i]) ? 2 : 1; - total += mainFont.mMetrics.charsWidth(text, i, size); - i += size; - } - } - - return total; - } - - return 0; - } - - private float getFontMetrics(FontMetrics metrics) { - if (mFonts.size() > 0) { - java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; - if (metrics != null) { - // Android expects negative ascent so we invert the value from Java. - metrics.top = - javaMetrics.getMaxAscent(); - metrics.ascent = - javaMetrics.getAscent(); - metrics.descent = javaMetrics.getDescent(); - metrics.bottom = javaMetrics.getMaxDescent(); - metrics.leading = javaMetrics.getLeading(); - } - - return javaMetrics.getHeight(); - } - - return 0; - } - - private void setTextLocale(String locale) { - mLocale = new Locale(locale); - } - - private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) { - // get the delegate from the native int. - Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); - if (delegate == null) { - return; - } - - if (flagValue) { - delegate.mFlags |= flagMask; - } else { - delegate.mFlags &= ~flagMask; - } - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java deleted file mode 100644 index c448f0e..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.PathDashPathEffect - * - * Through the layoutlib_create tool, the original native methods of PathDashPathEffect have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original PathDashPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class PathDashPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Path Dash Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(int native_path, float advance, float phase, - int native_style) { - PathDashPathEffect_Delegate newDelegate = new PathDashPathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java deleted file mode 100644 index bd2b6de..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.PathEffect - * - * Through the layoutlib_create tool, the original native methods of PathEffect have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original PathEffect class. - * - * This also serve as a base class for all PathEffect delegate classes. - * - * @see DelegateManager - * - */ -public abstract class PathEffect_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<PathEffect_Delegate> sManager = - new DelegateManager<PathEffect_Delegate>(PathEffect_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static PathEffect_Delegate getDelegate(int nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract Stroke getStroke(Paint_Delegate paint); - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(int native_patheffect) { - sManager.removeJavaReferenceFor(native_patheffect); - } - - // ---- Private delegate/helper methods ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java deleted file mode 100644 index 64f19d3..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ /dev/null @@ -1,815 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Path.Direction; -import android.graphics.Path.FillType; - -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Arc2D; -import java.awt.geom.Area; -import java.awt.geom.Ellipse2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.geom.RoundRectangle2D; - -/** - * Delegate implementing the native methods of android.graphics.Path - * - * Through the layoutlib_create tool, the original native methods of Path have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Path class. - * - * @see DelegateManager - * - */ -public final class Path_Delegate { - - // ---- delegate manager ---- - private static final DelegateManager<Path_Delegate> sManager = - new DelegateManager<Path_Delegate>(Path_Delegate.class); - - // ---- delegate data ---- - private FillType mFillType = FillType.WINDING; - private GeneralPath mPath = new GeneralPath(); - - private float mLastX = 0; - private float mLastY = 0; - - // ---- Public Helper methods ---- - - public static Path_Delegate getDelegate(int nPath) { - return sManager.getDelegate(nPath); - } - - public Shape getJavaShape() { - return mPath; - } - - public void setJavaShape(Shape shape) { - mPath.reset(); - mPath.append(shape, false /*connect*/); - } - - public void reset() { - mPath.reset(); - } - - public void setPathIterator(PathIterator iterator) { - mPath.reset(); - mPath.append(iterator, false /*connect*/); - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int init1() { - // create the delegate - Path_Delegate newDelegate = new Path_Delegate(); - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int init2(int nPath) { - // create the delegate - Path_Delegate newDelegate = new Path_Delegate(); - - // get the delegate to copy, which could be null if nPath is 0 - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate != null) { - newDelegate.set(pathDelegate); - } - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void native_reset(int nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mPath.reset(); - } - - @LayoutlibDelegate - /*package*/ static void native_rewind(int nPath) { - // call out to reset since there's nothing to optimize in - // terms of data structs. - native_reset(nPath); - } - - @LayoutlibDelegate - /*package*/ static void native_set(int native_dst, int native_src) { - Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst); - if (pathDstDelegate == null) { - return; - } - - Path_Delegate pathSrcDelegate = sManager.getDelegate(native_src); - if (pathSrcDelegate == null) { - return; - } - - pathDstDelegate.set(pathSrcDelegate); - } - - @LayoutlibDelegate - /*package*/ static int native_getFillType(int nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return 0; - } - - return pathDelegate.mFillType.nativeInt; - } - - @LayoutlibDelegate - /*package*/ static void native_setFillType(int nPath, int ft) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mFillType = Path.sFillTypeArray[ft]; - } - - @LayoutlibDelegate - /*package*/ static boolean native_isEmpty(int nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return true; - } - - return pathDelegate.isEmpty(); - } - - @LayoutlibDelegate - /*package*/ static boolean native_isRect(int nPath, RectF rect) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return false; - } - - // create an Area that can test if the path is a rect - Area area = new Area(pathDelegate.mPath); - if (area.isRectangular()) { - if (rect != null) { - pathDelegate.fillBounds(rect); - } - - return true; - } - - return false; - } - - @LayoutlibDelegate - /*package*/ static void native_computeBounds(int nPath, RectF bounds) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.fillBounds(bounds); - } - - @LayoutlibDelegate - /*package*/ static void native_incReserve(int nPath, int extraPtCount) { - // since we use a java2D path, there's no way to pre-allocate new points, - // so we do nothing. - } - - @LayoutlibDelegate - /*package*/ static void native_moveTo(int nPath, float x, float y) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.moveTo(x, y); - } - - @LayoutlibDelegate - /*package*/ static void native_rMoveTo(int nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rMoveTo(dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void native_lineTo(int nPath, float x, float y) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.lineTo(x, y); - } - - @LayoutlibDelegate - /*package*/ static void native_rLineTo(int nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rLineTo(dx, dy); - } - - @LayoutlibDelegate - /*package*/ static void native_quadTo(int nPath, float x1, float y1, float x2, float y2) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.quadTo(x1, y1, x2, y2); - } - - @LayoutlibDelegate - /*package*/ static void native_rQuadTo(int nPath, float dx1, float dy1, float dx2, float dy2) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rQuadTo(dx1, dy1, dx2, dy2); - } - - @LayoutlibDelegate - /*package*/ static void native_cubicTo(int nPath, float x1, float y1, - float x2, float y2, float x3, float y3) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.cubicTo(x1, y1, x2, y2, x3, y3); - } - - @LayoutlibDelegate - /*package*/ static void native_rCubicTo(int nPath, float x1, float y1, - float x2, float y2, float x3, float y3) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.rCubicTo(x1, y1, x2, y2, x3, y3); - } - - @LayoutlibDelegate - /*package*/ static void native_arcTo(int nPath, RectF oval, - float startAngle, float sweepAngle, boolean forceMoveTo) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.arcTo(oval, startAngle, sweepAngle, forceMoveTo); - } - - @LayoutlibDelegate - /*package*/ static void native_close(int nPath) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.close(); - } - - @LayoutlibDelegate - /*package*/ static void native_addRect(int nPath, RectF rect, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.addRect(rect.left, rect.top, rect.right, rect.bottom, dir); - } - - @LayoutlibDelegate - /*package*/ static void native_addRect(int nPath, - float left, float top, float right, float bottom, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.addRect(left, top, right, bottom, dir); - } - - @LayoutlibDelegate - /*package*/ static void native_addOval(int nPath, RectF oval, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mPath.append(new Ellipse2D.Float( - oval.left, oval.top, oval.width(), oval.height()), false); - } - - @LayoutlibDelegate - /*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - // because x/y is the center of the circle, need to offset this by the radius - pathDelegate.mPath.append(new Ellipse2D.Float( - x - radius, y - radius, radius * 2, radius * 2), false); - } - - @LayoutlibDelegate - /*package*/ static void native_addArc(int nPath, RectF oval, - float startAngle, float sweepAngle) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - // because x/y is the center of the circle, need to offset this by the radius - pathDelegate.mPath.append(new Arc2D.Float( - oval.left, oval.top, oval.width(), oval.height(), - -startAngle, -sweepAngle, Arc2D.OPEN), false); - } - - @LayoutlibDelegate - /*package*/ static void native_addRoundRect( - int nPath, RectF rect, float rx, float ry, int dir) { - - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mPath.append(new RoundRectangle2D.Float( - rect.left, rect.top, rect.width(), rect.height(), rx * 2, ry * 2), false); - } - - @LayoutlibDelegate - /*package*/ static void native_addRoundRect(int nPath, RectF rect, float[] radii, int dir) { - // Java2D doesn't support different rounded corners in each corner, so just use the - // first value. - native_addRoundRect(nPath, rect, radii[0], radii[1], dir); - - // there can be a case where this API is used but with similar values for all corners, so - // in that case we don't warn. - // we only care if 2 corners are different so just compare to the next one. - for (int i = 0 ; i < 3 ; i++) { - if (radii[i * 2] != radii[(i + 1) * 2] || radii[i * 2 + 1] != radii[(i + 1) * 2 + 1]) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Different corner sizes are not supported in Path.addRoundRect.", - null, null /*data*/); - break; - } - } - } - - @LayoutlibDelegate - /*package*/ static void native_addPath(int nPath, int src, float dx, float dy) { - addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy)); - } - - @LayoutlibDelegate - /*package*/ static void native_addPath(int nPath, int src) { - addPath(nPath, src, null /*transform*/); - } - - @LayoutlibDelegate - /*package*/ static void native_addPath(int nPath, int src, int matrix) { - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); - if (matrixDelegate == null) { - return; - } - - addPath(nPath, src, matrixDelegate.getAffineTransform()); - } - - @LayoutlibDelegate - /*package*/ static void native_offset(int nPath, float dx, float dy, int dst_path) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - // could be null if the int is 0; - Path_Delegate dstDelegate = sManager.getDelegate(dst_path); - - pathDelegate.offset(dx, dy, dstDelegate); - } - - @LayoutlibDelegate - /*package*/ static void native_offset(int nPath, float dx, float dy) { - native_offset(nPath, dx, dy, 0); - } - - @LayoutlibDelegate - /*package*/ static void native_setLastPoint(int nPath, float dx, float dy) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.mLastX = dx; - pathDelegate.mLastY = dy; - } - - @LayoutlibDelegate - /*package*/ static void native_transform(int nPath, int matrix, - int dst_path) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); - if (matrixDelegate == null) { - return; - } - - // this can be null if dst_path is 0 - Path_Delegate dstDelegate = sManager.getDelegate(dst_path); - - pathDelegate.transform(matrixDelegate, dstDelegate); - } - - @LayoutlibDelegate - /*package*/ static void native_transform(int nPath, int matrix) { - native_transform(nPath, matrix, 0); - } - - @LayoutlibDelegate - /*package*/ static void finalizer(int nPath) { - sManager.removeJavaReferenceFor(nPath); - } - - - // ---- Private helper methods ---- - - private void set(Path_Delegate delegate) { - mPath.reset(); - setFillType(delegate.mFillType); - mPath.append(delegate.mPath, false /*connect*/); - } - - private void setFillType(FillType fillType) { - mFillType = fillType; - mPath.setWindingRule(getWindingRule(fillType)); - } - - /** - * Returns the Java2D winding rules matching a given Android {@link FillType}. - * @param type the android fill type - * @return the matching java2d winding rule. - */ - private static int getWindingRule(FillType type) { - switch (type) { - case WINDING: - case INVERSE_WINDING: - return GeneralPath.WIND_NON_ZERO; - case EVEN_ODD: - case INVERSE_EVEN_ODD: - return GeneralPath.WIND_EVEN_ODD; - } - - assert false; - throw new IllegalArgumentException(); - } - - private static Direction getDirection(int direction) { - for (Direction d : Direction.values()) { - if (direction == d.nativeInt) { - return d; - } - } - - assert false; - return null; - } - - private static void addPath(int destPath, int srcPath, AffineTransform transform) { - Path_Delegate destPathDelegate = sManager.getDelegate(destPath); - if (destPathDelegate == null) { - return; - } - - Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath); - if (srcPathDelegate == null) { - return; - } - - if (transform != null) { - destPathDelegate.mPath.append( - srcPathDelegate.mPath.getPathIterator(transform), false); - } else { - destPathDelegate.mPath.append(srcPathDelegate.mPath, false); - } - } - - - /** - * Returns whether the path is empty. - * @return true if the path is empty. - */ - private boolean isEmpty() { - return mPath.getCurrentPoint() == null; - } - - /** - * Fills the given {@link RectF} with the path bounds. - * @param bounds the RectF to be filled. - */ - private void fillBounds(RectF bounds) { - Rectangle2D rect = mPath.getBounds2D(); - bounds.left = (float)rect.getMinX(); - bounds.right = (float)rect.getMaxX(); - bounds.top = (float)rect.getMinY(); - bounds.bottom = (float)rect.getMaxY(); - } - - /** - * Set the beginning of the next contour to the point (x,y). - * - * @param x The x-coordinate of the start of a new contour - * @param y The y-coordinate of the start of a new contour - */ - private void moveTo(float x, float y) { - mPath.moveTo(mLastX = x, mLastY = y); - } - - /** - * Set the beginning of the next contour relative to the last point on the - * previous contour. If there is no previous contour, this is treated the - * same as moveTo(). - * - * @param dx The amount to add to the x-coordinate of the end of the - * previous contour, to specify the start of a new contour - * @param dy The amount to add to the y-coordinate of the end of the - * previous contour, to specify the start of a new contour - */ - private void rMoveTo(float dx, float dy) { - dx += mLastX; - dy += mLastY; - mPath.moveTo(mLastX = dx, mLastY = dy); - } - - /** - * Add a line from the last point to the specified point (x,y). - * If no moveTo() call has been made for this contour, the first point is - * automatically set to (0,0). - * - * @param x The x-coordinate of the end of a line - * @param y The y-coordinate of the end of a line - */ - private void lineTo(float x, float y) { - mPath.lineTo(mLastX = x, mLastY = y); - } - - /** - * Same as lineTo, but the coordinates are considered relative to the last - * point on this contour. If there is no previous point, then a moveTo(0,0) - * is inserted automatically. - * - * @param dx The amount to add to the x-coordinate of the previous point on - * this contour, to specify a line - * @param dy The amount to add to the y-coordinate of the previous point on - * this contour, to specify a line - */ - private void rLineTo(float dx, float dy) { - if (isEmpty()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - dx += mLastX; - dy += mLastY; - mPath.lineTo(mLastX = dx, mLastY = dy); - } - - /** - * Add a quadratic bezier from the last point, approaching control point - * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for - * this contour, the first point is automatically set to (0,0). - * - * @param x1 The x-coordinate of the control point on a quadratic curve - * @param y1 The y-coordinate of the control point on a quadratic curve - * @param x2 The x-coordinate of the end point on a quadratic curve - * @param y2 The y-coordinate of the end point on a quadratic curve - */ - private void quadTo(float x1, float y1, float x2, float y2) { - mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2); - } - - /** - * Same as quadTo, but the coordinates are considered relative to the last - * point on this contour. If there is no previous point, then a moveTo(0,0) - * is inserted automatically. - * - * @param dx1 The amount to add to the x-coordinate of the last point on - * this contour, for the control point of a quadratic curve - * @param dy1 The amount to add to the y-coordinate of the last point on - * this contour, for the control point of a quadratic curve - * @param dx2 The amount to add to the x-coordinate of the last point on - * this contour, for the end point of a quadratic curve - * @param dy2 The amount to add to the y-coordinate of the last point on - * this contour, for the end point of a quadratic curve - */ - private void rQuadTo(float dx1, float dy1, float dx2, float dy2) { - if (isEmpty()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - dx1 += mLastX; - dy1 += mLastY; - dx2 += mLastX; - dy2 += mLastY; - mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2); - } - - /** - * Add a cubic bezier from the last point, approaching control points - * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been - * made for this contour, the first point is automatically set to (0,0). - * - * @param x1 The x-coordinate of the 1st control point on a cubic curve - * @param y1 The y-coordinate of the 1st control point on a cubic curve - * @param x2 The x-coordinate of the 2nd control point on a cubic curve - * @param y2 The y-coordinate of the 2nd control point on a cubic curve - * @param x3 The x-coordinate of the end point on a cubic curve - * @param y3 The y-coordinate of the end point on a cubic curve - */ - private void cubicTo(float x1, float y1, float x2, float y2, - float x3, float y3) { - mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3); - } - - /** - * Same as cubicTo, but the coordinates are considered relative to the - * current point on this contour. If there is no previous point, then a - * moveTo(0,0) is inserted automatically. - */ - private void rCubicTo(float dx1, float dy1, float dx2, float dy2, - float dx3, float dy3) { - if (isEmpty()) { - mPath.moveTo(mLastX = 0, mLastY = 0); - } - dx1 += mLastX; - dy1 += mLastY; - dx2 += mLastX; - dy2 += mLastY; - dx3 += mLastX; - dy3 += mLastY; - mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3); - } - - /** - * Append the specified arc to the path as a new contour. If the start of - * the path is different from the path's current last point, then an - * automatic lineTo() is added to connect the current contour to the - * start of the arc. However, if the path is empty, then we call moveTo() - * with the first point of the arc. The sweep angle is tread mod 360. - * - * @param oval The bounds of oval defining shape and size of the arc - * @param startAngle Starting angle (in degrees) where the arc begins - * @param sweepAngle Sweep angle (in degrees) measured clockwise, treated - * mod 360. - * @param forceMoveTo If true, always begin a new contour with the arc - */ - private void arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) { - Arc2D arc = new Arc2D.Float(oval.left, oval.top, oval.width(), oval.height(), -startAngle, - -sweepAngle, Arc2D.OPEN); - mPath.append(arc, true /*connect*/); - - resetLastPointFromPath(); - } - - /** - * Close the current contour. If the current point is not equal to the - * first point of the contour, a line segment is automatically added. - */ - private void close() { - mPath.closePath(); - } - - private void resetLastPointFromPath() { - Point2D last = mPath.getCurrentPoint(); - mLastX = (float) last.getX(); - mLastY = (float) last.getY(); - } - - /** - * Add a closed rectangle contour to the path - * - * @param left The left side of a rectangle to add to the path - * @param top The top of a rectangle to add to the path - * @param right The right side of a rectangle to add to the path - * @param bottom The bottom of a rectangle to add to the path - * @param dir The direction to wind the rectangle's contour - */ - private void addRect(float left, float top, float right, float bottom, - int dir) { - moveTo(left, top); - - Direction direction = getDirection(dir); - - switch (direction) { - case CW: - lineTo(right, top); - lineTo(right, bottom); - lineTo(left, bottom); - break; - case CCW: - lineTo(left, bottom); - lineTo(right, bottom); - lineTo(right, top); - break; - } - - close(); - - resetLastPointFromPath(); - } - - /** - * Offset the path by (dx,dy), returning true on success - * - * @param dx The amount in the X direction to offset the entire path - * @param dy The amount in the Y direction to offset the entire path - * @param dst The translated path is written here. If this is null, then - * the original path is modified. - */ - public void offset(float dx, float dy, Path_Delegate dst) { - GeneralPath newPath = new GeneralPath(); - - PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy)); - - newPath.append(iterator, false /*connect*/); - - if (dst != null) { - dst.mPath = newPath; - } else { - mPath = newPath; - } - } - - /** - * Transform the points in this path by matrix, and write the answer - * into dst. If dst is null, then the the original path is modified. - * - * @param matrix The matrix to apply to the path - * @param dst The transformed path is written here. If dst is null, - * then the the original path is modified - */ - public void transform(Matrix_Delegate matrix, Path_Delegate dst) { - if (matrix.hasPerspective()) { - assert false; - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE, - "android.graphics.Path#transform() only " + - "supports affine transformations.", null, null /*data*/); - } - - GeneralPath newPath = new GeneralPath(); - - PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform()); - - newPath.append(iterator, false /*connect*/); - - if (dst != null) { - dst.mPath = newPath; - } else { - mPath = newPath; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java deleted file mode 100644 index 4ab044b..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Composite; - -/** - * Delegate implementing the native methods of android.graphics.PixelXorXfermode - * - * Through the layoutlib_create tool, the original native methods of PixelXorXfermode have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original PixelXorXfermode class. - * - * Because this extends {@link Xfermode_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by - * {@link Xfermode_Delegate}. - * - * @see Xfermode_Delegate - */ -public class PixelXorXfermode_Delegate extends Xfermode_Delegate { - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Composite getComposite(int alpha) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Pixel XOR Xfermodes are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(int opColor) { - PixelXorXfermode_Delegate newDelegate = new PixelXorXfermode_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java deleted file mode 100644 index c45dbaa..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter - * - * Through the layoutlib_create tool, the original native methods of PorterDuffColorFilter have - * been replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original PorterDuffColorFilter class. - * - * Because this extends {@link ColorFilter_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the Shader classes will be added to the manager - * owned by {@link ColorFilter_Delegate}. - * - * @see ColorFilter_Delegate - * - */ -public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "PorterDuff Color Filters are not supported."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) { - PorterDuffColorFilter_Delegate newDelegate = new PorterDuffColorFilter_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nCreatePorterDuffFilter(int nativeFilter, int srcColor, - int porterDuffMode) { - // pass - return 0; - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java deleted file mode 100644 index 4301c1a..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.AlphaComposite; -import java.awt.Composite; - -/** - * Delegate implementing the native methods of android.graphics.PorterDuffXfermode - * - * Through the layoutlib_create tool, the original native methods of PorterDuffXfermode have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original PorterDuffXfermode class. - * - * Because this extends {@link Xfermode_Delegate}, there's no need to use a - * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by - * {@link Xfermode_Delegate}. - * - */ -public class PorterDuffXfermode_Delegate extends Xfermode_Delegate { - - // ---- delegate data ---- - - private final int mMode; - - // ---- Public Helper methods ---- - - public PorterDuff.Mode getMode() { - return getPorterDuffMode(mMode); - } - - @Override - public Composite getComposite(int alpha) { - return getComposite(getPorterDuffMode(mMode), alpha); - } - - @Override - public boolean isSupported() { - return true; - } - - @Override - public String getSupportMessage() { - // no message since isSupported returns true; - return null; - } - - public static PorterDuff.Mode getPorterDuffMode(int mode) { - for (PorterDuff.Mode m : PorterDuff.Mode.values()) { - if (m.nativeInt == mode) { - return m; - } - } - - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/); - assert false; - return PorterDuff.Mode.SRC_OVER; - } - - public static Composite getComposite(PorterDuff.Mode mode, int alpha) { - float falpha = alpha != 0xFF ? (float)alpha / 255.f : 1.f; - switch (mode) { - case CLEAR: - return AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha); - case DARKEN: - break; - case DST: - return AlphaComposite.getInstance(AlphaComposite.DST, falpha); - case DST_ATOP: - return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha); - case DST_IN: - return AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha); - case DST_OUT: - return AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha); - case DST_OVER: - return AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha); - case LIGHTEN: - break; - case MULTIPLY: - break; - case SCREEN: - break; - case SRC: - return AlphaComposite.getInstance(AlphaComposite.SRC, falpha); - case SRC_ATOP: - return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha); - case SRC_IN: - return AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha); - case SRC_OUT: - return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha); - case SRC_OVER: - return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha); - case XOR: - return AlphaComposite.getInstance(AlphaComposite.XOR, falpha); - } - - Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN, - String.format("Unsupported PorterDuff Mode: %s", mode.name()), - null, null /*data*/); - - return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha); - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreateXfermode(int mode) { - PorterDuffXfermode_Delegate newDelegate = new PorterDuffXfermode_Delegate(mode); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- - - private PorterDuffXfermode_Delegate(int mode) { - mMode = mode; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java deleted file mode 100644 index 3fe45fa..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Shader.TileMode; - -/** - * Delegate implementing the native methods of android.graphics.RadialGradient - * - * Through the layoutlib_create tool, the original native methods of RadialGradient have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original RadialGradient class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class RadialGradient_Delegate extends Gradient_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate1(float x, float y, float radius, - int colors[], float positions[], int tileMode) { - RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius, - colors, positions, Shader_Delegate.getTileMode(tileMode)); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nativeCreate2(float x, float y, float radius, - int color0, int color1, int tileMode) { - return nativeCreate1(x, y, radius, new int[] { color0, color1 }, null /*positions*/, - tileMode); - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate1(int native_shader, float x, float y, float radius, - int colors[], float positions[], int tileMode) { - // nothing to be done here. - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate2(int native_shader, float x, float y, float radius, - int color0, int color1, int tileMode) { - // nothing to be done here. - return 0; - } - - // ---- Private delegate/helper methods ---- - - /** - * Create a shader that draws a radial gradient given the center and radius. - * - * @param x The x-coordinate of the center of the radius - * @param y The y-coordinate of the center of the radius - * @param radius Must be positive. The radius of the circle for this - * gradient - * @param colors The colors to be distributed between the center and edge of - * the circle - * @param positions May be NULL. The relative position of each corresponding - * color in the colors array. If this is NULL, the the colors are - * distributed evenly between the center and edge of the circle. - * @param tile The Shader tiling mode - */ - private RadialGradient_Delegate(float x, float y, float radius, int colors[], float positions[], - TileMode tile) { - super(colors, positions); - mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile); - } - - private class RadialGradientPaint extends GradientPaint { - - private final float mX; - private final float mY; - private final float mRadius; - - public RadialGradientPaint(float x, float y, float radius, - int[] colors, float[] positions, TileMode mode) { - super(colors, positions, mode); - mX = x; - mY = y; - mRadius = radius; - } - - @Override - public java.awt.PaintContext createContext( - java.awt.image.ColorModel colorModel, - java.awt.Rectangle deviceBounds, - java.awt.geom.Rectangle2D userBounds, - java.awt.geom.AffineTransform xform, - java.awt.RenderingHints hints) { - precomputeGradientColors(); - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in RadialGradient", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in RadialGradient", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel); - } - - private class RadialGradientPaintContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - public RadialGradientPaintContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel; - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.ColorModel getColorModel() { - return mColorModel; - } - - @Override - public java.awt.image.Raster getRaster(int x, int y, int w, int h) { - java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h, - java.awt.image.BufferedImage.TYPE_INT_ARGB); - - int[] data = new int[w*h]; - - // compute distance from each point to the center, and figure out the distance from - // it. - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix - pt1[0] = pt2[0] - mX; - pt1[1] = pt2[1] - mY; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - float _x = pt2[0]; - float _y = pt2[1]; - float distance = (float) Math.sqrt(_x * _x + _y * _y); - - data[index++] = getGradientColor(distance / mRadius); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - - } - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java deleted file mode 100644 index 2812b6b..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.Rasterizer - * - * Through the layoutlib_create tool, the original native methods of Rasterizer have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Rasterizer class. - * - * This also serve as a base class for all Rasterizer delegate classes. - * - * @see DelegateManager - * - */ -public abstract class Rasterizer_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Rasterizer_Delegate> sManager = - new DelegateManager<Rasterizer_Delegate>(Rasterizer_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static Rasterizer_Delegate getDelegate(int nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void finalizer(int native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java deleted file mode 100644 index cb31b8f..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.os.Parcel; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; - -/** - * Delegate implementing the native methods of android.graphics.Region - * - * Through the layoutlib_create tool, the original native methods of Region have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Region class. - * - * This also serve as a base class for all Region delegate classes. - * - * @see DelegateManager - * - */ -public class Region_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Region_Delegate> sManager = - new DelegateManager<Region_Delegate>(Region_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - private Area mArea = new Area(); - - // ---- Public Helper methods ---- - - public static Region_Delegate getDelegate(int nativeShader) { - return sManager.getDelegate(nativeShader); - } - - public Area getJavaArea() { - return mArea; - } - - /** - * Combines two {@link Shape} into another one (actually an {@link Area}), according - * to the given {@link Region.Op}. - * - * If the Op is not one that combines two shapes, then this return null - * - * @param shape1 the firt shape to combine which can be null if there's no original clip. - * @param shape2 the 2nd shape to combine - * @param regionOp the operande for the combine - * @return a new area or null. - */ - public static Area combineShapes(Shape shape1, Shape shape2, int regionOp) { - if (regionOp == Region.Op.DIFFERENCE.nativeInt) { - // if shape1 is null (empty), then the result is null. - if (shape1 == null) { - return null; - } - - // result is always a new area. - Area result = new Area(shape1); - result.subtract(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.INTERSECT.nativeInt) { - // if shape1 is null, then the result is simply shape2. - if (shape1 == null) { - return new Area(shape2); - } - - // result is always a new area. - Area result = new Area(shape1); - result.intersect(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.UNION.nativeInt) { - // if shape1 is null, then the result is simply shape2. - if (shape1 == null) { - return new Area(shape2); - } - - // result is always a new area. - Area result = new Area(shape1); - result.add(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.XOR.nativeInt) { - // if shape1 is null, then the result is simply shape2 - if (shape1 == null) { - return new Area(shape2); - } - - // result is always a new area. - Area result = new Area(shape1); - result.exclusiveOr(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); - return result; - - } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) { - // result is always a new area. - Area result = new Area(shape2); - - if (shape1 != null) { - result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1)); - } - - return result; - } - - return null; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static boolean isEmpty(Region thisRegion) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return true; - } - - return regionDelegate.mArea.isEmpty(); - } - - @LayoutlibDelegate - /*package*/ static boolean isRect(Region thisRegion) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return true; - } - - return regionDelegate.mArea.isRectangular(); - } - - @LayoutlibDelegate - /*package*/ static boolean isComplex(Region thisRegion) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return true; - } - - return regionDelegate.mArea.isSingular() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean contains(Region thisRegion, int x, int y) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - return regionDelegate.mArea.contains(x, y); - } - - @LayoutlibDelegate - /*package*/ static boolean quickContains(Region thisRegion, - int left, int top, int right, int bottom) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - return regionDelegate.mArea.isRectangular() && - regionDelegate.mArea.contains(left, top, right - left, bottom - top); - } - - @LayoutlibDelegate - /*package*/ static boolean quickReject(Region thisRegion, - int left, int top, int right, int bottom) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - return regionDelegate.mArea.isEmpty() || - regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false; - } - - @LayoutlibDelegate - /*package*/ static boolean quickReject(Region thisRegion, Region rgn) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return false; - } - - Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion); - if (targetRegionDelegate == null) { - return false; - } - - return regionDelegate.mArea.isEmpty() || - regionDelegate.mArea.getBounds().intersects( - targetRegionDelegate.mArea.getBounds()) == false; - - } - - @LayoutlibDelegate - /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return; - } - - Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion); - if (targetRegionDelegate == null) { - return; - } - - if (regionDelegate.mArea.isEmpty()) { - targetRegionDelegate.mArea = new Area(); - } else { - targetRegionDelegate.mArea = new Area(regionDelegate.mArea); - AffineTransform mtx = new AffineTransform(); - mtx.translate(dx, dy); - targetRegionDelegate.mArea.transform(mtx); - } - } - - @LayoutlibDelegate - /*package*/ static void scale(Region thisRegion, float scale, Region dst) { - Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion); - if (regionDelegate == null) { - return; - } - - Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion); - if (targetRegionDelegate == null) { - return; - } - - if (regionDelegate.mArea.isEmpty()) { - targetRegionDelegate.mArea = new Area(); - } else { - targetRegionDelegate.mArea = new Area(regionDelegate.mArea); - AffineTransform mtx = new AffineTransform(); - mtx.scale(scale, scale); - targetRegionDelegate.mArea.transform(mtx); - } - } - - @LayoutlibDelegate - /*package*/ static int nativeConstructor() { - Region_Delegate newDelegate = new Region_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(int native_region) { - sManager.removeJavaReferenceFor(native_region); - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSetRegion(int native_dst, int native_src) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - Region_Delegate srcRegion = sManager.getDelegate(native_src); - if (srcRegion == null) { - return true; - } - - dstRegion.mArea.reset(); - dstRegion.mArea.add(srcRegion.mArea); - - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSetRect(int native_dst, - int left, int top, int right, int bottom) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - dstRegion.mArea = new Area(new Rectangle2D.Float(left, top, right - left, bottom - top)); - return dstRegion.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeSetPath(int native_dst, int native_path, int native_clip) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - Path_Delegate path = Path_Delegate.getDelegate(native_path); - if (path == null) { - return true; - } - - dstRegion.mArea = new Area(path.getJavaShape()); - - Region_Delegate clip = sManager.getDelegate(native_clip); - if (clip != null) { - dstRegion.mArea.subtract(clip.getJavaArea()); - } - - return dstRegion.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeGetBounds(int native_region, Rect rect) { - Region_Delegate region = sManager.getDelegate(native_region); - if (region == null) { - return true; - } - - Rectangle bounds = region.mArea.getBounds(); - if (bounds.isEmpty()) { - rect.left = rect.top = rect.right = rect.bottom = 0; - return false; - } - - rect.left = bounds.x; - rect.top = bounds.y; - rect.right = bounds.x + bounds.width; - rect.bottom = bounds.y + bounds.height; - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeGetBoundaryPath(int native_region, int native_path) { - Region_Delegate region = sManager.getDelegate(native_region); - if (region == null) { - return false; - } - - Path_Delegate path = Path_Delegate.getDelegate(native_path); - if (path == null) { - return false; - } - - if (region.mArea.isEmpty()) { - path.reset(); - return false; - } - - path.setPathIterator(region.mArea.getPathIterator(new AffineTransform())); - return true; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeOp(int native_dst, - int left, int top, int right, int bottom, int op) { - Region_Delegate region = sManager.getDelegate(native_dst); - if (region == null) { - return false; - } - - region.mArea = combineShapes(region.mArea, - new Rectangle2D.Float(left, top, right - left, bottom - top), op); - - assert region.mArea != null; - if (region.mArea != null) { - region.mArea = new Area(); - } - - return region.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeOp(int native_dst, Rect rect, int native_region, int op) { - Region_Delegate region = sManager.getDelegate(native_dst); - if (region == null) { - return false; - } - - region.mArea = combineShapes(region.mArea, - new Rectangle2D.Float(rect.left, rect.top, rect.width(), rect.height()), op); - - assert region.mArea != null; - if (region.mArea != null) { - region.mArea = new Area(); - } - - return region.mArea.getBounds().isEmpty() == false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeOp(int native_dst, - int native_region1, int native_region2, int op) { - Region_Delegate dstRegion = sManager.getDelegate(native_dst); - if (dstRegion == null) { - return true; - } - - Region_Delegate region1 = sManager.getDelegate(native_region1); - if (region1 == null) { - return false; - } - - Region_Delegate region2 = sManager.getDelegate(native_region2); - if (region2 == null) { - return false; - } - - dstRegion.mArea = combineShapes(region1.mArea, region2.mArea, op); - - assert dstRegion.mArea != null; - if (dstRegion.mArea != null) { - dstRegion.mArea = new Area(); - } - - return dstRegion.mArea.getBounds().isEmpty() == false; - - } - - @LayoutlibDelegate - /*package*/ static int nativeCreateFromParcel(Parcel p) { - // This is only called by Region.CREATOR (Parcelable.Creator<Region>), which is only - // used during aidl call so really this should not be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Regions cannot be created from parcels.", - null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeWriteToParcel(int native_region, - Parcel p) { - // This is only called when sending a region through aidl, so really this should not - // be called. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "AIDL is not suppored, and therefore Regions cannot be written to parcels.", - null /*data*/); - return false; - } - - @LayoutlibDelegate - /*package*/ static boolean nativeEquals(int native_r1, int native_r2) { - Region_Delegate region1 = sManager.getDelegate(native_r1); - if (region1 == null) { - return false; - } - - Region_Delegate region2 = sManager.getDelegate(native_r2); - if (region2 == null) { - return false; - } - - return region1.mArea.equals(region2.mArea); - } - - @LayoutlibDelegate - /*package*/ static String nativeToString(int native_region) { - Region_Delegate region = sManager.getDelegate(native_region); - if (region == null) { - return "not found"; - } - - return region.mArea.toString(); - } - - // ---- Private delegate/helper methods ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java deleted file mode 100644 index 368c0384..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.graphics.Shader.TileMode; - -/** - * Delegate implementing the native methods of android.graphics.Shader - * - * Through the layoutlib_create tool, the original native methods of Shader have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Shader class. - * - * This also serve as a base class for all Shader delegate classes. - * - * @see DelegateManager - * - */ -public abstract class Shader_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Shader_Delegate> sManager = - new DelegateManager<Shader_Delegate>(Shader_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - private Matrix_Delegate mLocalMatrix = null; - - // ---- Public Helper methods ---- - - public static Shader_Delegate getDelegate(int nativeShader) { - return sManager.getDelegate(nativeShader); - } - - /** - * Returns the {@link TileMode} matching the given int. - * @param tileMode the tile mode int value - * @return the TileMode enum. - */ - public static TileMode getTileMode(int tileMode) { - for (TileMode tm : TileMode.values()) { - if (tm.nativeInt == tileMode) { - return tm; - } - } - - assert false; - return TileMode.CLAMP; - } - - public abstract java.awt.Paint getJavaPaint(); - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void nativeDestructor(int native_shader, int native_skiaShader) { - sManager.removeJavaReferenceFor(native_shader); - } - - @LayoutlibDelegate - /*package*/ static void nativeSetLocalMatrix(int native_shader, int native_skiaShader, - int matrix_instance) { - // get the delegate from the native int. - Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader); - if (shaderDelegate == null) { - return; - } - - shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance); - } - - // ---- Private delegate/helper methods ---- - - protected java.awt.geom.AffineTransform getLocalMatrix() { - if (mLocalMatrix != null) { - return mLocalMatrix.getAffineTransform(); - } - - return new java.awt.geom.AffineTransform(); - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java deleted file mode 100644 index 410df0c..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Stroke; - -/** - * Delegate implementing the native methods of android.graphics.SumPathEffect - * - * Through the layoutlib_create tool, the original native methods of SumPathEffect have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original SumPathEffect class. - * - * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}. - * - * @see PathEffect_Delegate - * - */ -public class SumPathEffect_Delegate extends PathEffect_Delegate { - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - @Override - public Stroke getStroke(Paint_Delegate paint) { - // FIXME - return null; - } - - @Override - public boolean isSupported() { - return false; - } - - @Override - public String getSupportMessage() { - return "Sum Path Effects are not supported in Layout Preview mode."; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate(int first, int second) { - SumPathEffect_Delegate newDelegate = new SumPathEffect_Delegate(); - return sManager.addNewDelegate(newDelegate); - } - - // ---- Private delegate/helper methods ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java deleted file mode 100644 index 13ae12e..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.graphics.SweepGradient - * - * Through the layoutlib_create tool, the original native methods of SweepGradient have been - * replaced by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original SweepGradient class. - * - * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, - * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. - * - * @see Shader_Delegate - * - */ -public class SweepGradient_Delegate extends Gradient_Delegate { - - // ---- delegate data ---- - private java.awt.Paint mJavaPaint; - - // ---- Public Helper methods ---- - - @Override - public java.awt.Paint getJavaPaint() { - return mJavaPaint; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static int nativeCreate1(float x, float y, int colors[], float positions[]) { - SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(x, y, colors, positions); - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static int nativeCreate2(float x, float y, int color0, int color1) { - return nativeCreate1(x, y, new int[] { color0, color1 }, null /*positions*/); - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate1(int native_shader, float cx, float cy, - int[] colors, float[] positions) { - // nothing to be done here. - return 0; - } - - @LayoutlibDelegate - /*package*/ static int nativePostCreate2(int native_shader, float cx, float cy, - int color0, int color1) { - // nothing to be done here. - return 0; - } - - // ---- Private delegate/helper methods ---- - - /** - * A subclass of Shader that draws a sweep gradient around a center point. - * - * @param cx The x-coordinate of the center - * @param cy The y-coordinate of the center - * @param colors The colors to be distributed between around the center. - * There must be at least 2 colors in the array. - * @param positions May be NULL. The relative position of - * each corresponding color in the colors array, beginning - * with 0 and ending with 1.0. If the values are not - * monotonic, the drawing may produce unexpected results. - * If positions is NULL, then the colors are automatically - * spaced evenly. - */ - private SweepGradient_Delegate(float cx, float cy, - int colors[], float positions[]) { - super(colors, positions); - mJavaPaint = new SweepGradientPaint(cx, cy, mColors, mPositions); - } - - private class SweepGradientPaint extends GradientPaint { - - private final float mCx; - private final float mCy; - - public SweepGradientPaint(float cx, float cy, int[] colors, - float[] positions) { - super(colors, positions, null /*tileMode*/); - mCx = cx; - mCy = cy; - } - - @Override - public java.awt.PaintContext createContext( - java.awt.image.ColorModel colorModel, - java.awt.Rectangle deviceBounds, - java.awt.geom.Rectangle2D userBounds, - java.awt.geom.AffineTransform xform, - java.awt.RenderingHints hints) { - precomputeGradientColors(); - - java.awt.geom.AffineTransform canvasMatrix; - try { - canvasMatrix = xform.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in SweepGradient", e, null /*data*/); - canvasMatrix = new java.awt.geom.AffineTransform(); - } - - java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); - try { - localMatrix = localMatrix.createInverse(); - } catch (java.awt.geom.NoninvertibleTransformException e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, - "Unable to inverse matrix in SweepGradient", e, null /*data*/); - localMatrix = new java.awt.geom.AffineTransform(); - } - - return new SweepGradientPaintContext(canvasMatrix, localMatrix, colorModel); - } - - private class SweepGradientPaintContext implements java.awt.PaintContext { - - private final java.awt.geom.AffineTransform mCanvasMatrix; - private final java.awt.geom.AffineTransform mLocalMatrix; - private final java.awt.image.ColorModel mColorModel; - - public SweepGradientPaintContext( - java.awt.geom.AffineTransform canvasMatrix, - java.awt.geom.AffineTransform localMatrix, - java.awt.image.ColorModel colorModel) { - mCanvasMatrix = canvasMatrix; - mLocalMatrix = localMatrix; - mColorModel = colorModel; - } - - @Override - public void dispose() { - } - - @Override - public java.awt.image.ColorModel getColorModel() { - return mColorModel; - } - - @Override - public java.awt.image.Raster getRaster(int x, int y, int w, int h) { - java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h, - java.awt.image.BufferedImage.TYPE_INT_ARGB); - - int[] data = new int[w*h]; - - // compute angle from each point to the center, and figure out the distance from - // it. - int index = 0; - float[] pt1 = new float[2]; - float[] pt2 = new float[2]; - for (int iy = 0 ; iy < h ; iy++) { - for (int ix = 0 ; ix < w ; ix++) { - // handle the canvas transform - pt1[0] = x + ix; - pt1[1] = y + iy; - mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); - - // handle the local matrix - pt1[0] = pt2[0] - mCx; - pt1[1] = pt2[1] - mCy; - mLocalMatrix.transform(pt1, 0, pt2, 0, 1); - - float dx = pt2[0]; - float dy = pt2[1]; - - float angle; - if (dx == 0) { - angle = (float) (dy < 0 ? 3 * Math.PI / 2 : Math.PI / 2); - } else if (dy == 0) { - angle = (float) (dx < 0 ? Math.PI : 0); - } else { - angle = (float) Math.atan(dy / dx); - if (dx > 0) { - if (dy < 0) { - angle += Math.PI * 2; - } - } else { - angle += Math.PI; - } - } - - // convert to 0-1. value and get color - data[index++] = getGradientColor((float) (angle / (2 * Math.PI))); - } - } - - image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); - - return image.getRaster(); - } - - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java deleted file mode 100644 index adad2ac..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.graphics; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class Typeface_Accessor { - - public static void resetDefaults() { - Typeface.sDefaults = null; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java deleted file mode 100644 index 8701cc8..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.layoutlib.bridge.impl.FontLoader; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.res.AssetManager; - -import java.awt.Font; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * Delegate implementing the native methods of android.graphics.Typeface - * - * Through the layoutlib_create tool, the original native methods of Typeface have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Typeface class. - * - * @see DelegateManager - * - */ -public final class Typeface_Delegate { - - private static final String SYSTEM_FONTS = "/system/fonts/"; - - // ---- delegate manager ---- - private static final DelegateManager<Typeface_Delegate> sManager = - new DelegateManager<Typeface_Delegate>(Typeface_Delegate.class); - - // ---- delegate helper data ---- - private static final String DEFAULT_FAMILY = "sans-serif"; - - private static FontLoader sFontLoader; - private static final List<Typeface_Delegate> sPostInitDelegate = - new ArrayList<Typeface_Delegate>(); - - // ---- delegate data ---- - - private final String mFamily; - private int mStyle; - private List<Font> mFonts; - - - // ---- Public Helper methods ---- - - public static synchronized void init(FontLoader fontLoader) { - sFontLoader = fontLoader; - - for (Typeface_Delegate delegate : sPostInitDelegate) { - delegate.init(); - } - sPostInitDelegate.clear(); - } - - public static Typeface_Delegate getDelegate(int nativeTypeface) { - return sManager.getDelegate(nativeTypeface); - } - - public static List<Font> getFonts(Typeface typeface) { - return getFonts(typeface.native_instance); - } - - public static List<Font> getFonts(int native_int) { - Typeface_Delegate delegate = sManager.getDelegate(native_int); - if (delegate == null) { - return null; - } - - return delegate.getFonts(); - } - - public List<Font> getFonts() { - return mFonts; - } - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static synchronized int nativeCreate(String familyName, int style) { - if (familyName == null) { - familyName = DEFAULT_FAMILY; - } - - Typeface_Delegate newDelegate = new Typeface_Delegate(familyName, style); - if (sFontLoader != null) { - newDelegate.init(); - } else { - // font loader has not been initialized yet, add the delegate to a list of delegates - // to init when the font loader is initialized. - // There won't be any rendering before this happens anyway. - sPostInitDelegate.add(newDelegate); - } - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static synchronized int nativeCreateFromTypeface(int native_instance, int style) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - return 0; - } - - Typeface_Delegate newDelegate = new Typeface_Delegate(delegate.mFamily, style); - if (sFontLoader != null) { - newDelegate.init(); - } else { - // font loader has not been initialized yet, add the delegate to a list of delegates - // to init when the font loader is initialized. - // There won't be any rendering before this happens anyway. - sPostInitDelegate.add(newDelegate); - } - - return sManager.addNewDelegate(newDelegate); - } - - @LayoutlibDelegate - /*package*/ static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Typeface.createFromAsset() is not supported.", null /*throwable*/, null /*data*/); - return 0; - } - - @LayoutlibDelegate - /*package*/ static synchronized int nativeCreateFromFile(String path) { - if (path.startsWith(SYSTEM_FONTS) ) { - String relativePath = path.substring(SYSTEM_FONTS.length()); - File f = new File(sFontLoader.getOsFontsLocation(), relativePath); - - try { - Font font = Font.createFont(Font.TRUETYPE_FONT, f); - if (font != null) { - Typeface_Delegate newDelegate = new Typeface_Delegate(font); - return sManager.addNewDelegate(newDelegate); - } - } catch (Exception e) { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN, - String.format("Unable to load font %1$s", relativePath), - null /*throwable*/, null /*data*/); - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Typeface.createFromFile() can only work with platform fonts located in " + - SYSTEM_FONTS, - null /*throwable*/, null /*data*/); - } - - - // return a copy of the base font - return nativeCreate(null, 0); - } - - @LayoutlibDelegate - /*package*/ static void nativeUnref(int native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - @LayoutlibDelegate - /*package*/ static int nativeGetStyle(int native_instance) { - Typeface_Delegate delegate = sManager.getDelegate(native_instance); - if (delegate == null) { - return 0; - } - - return delegate.mStyle; - } - - // ---- Private delegate/helper methods ---- - - private Typeface_Delegate(String family, int style) { - mFamily = family; - mStyle = style; - } - - private Typeface_Delegate(Font font) { - mFamily = font.getFamily(); - mStyle = Typeface.NORMAL; - - mFonts = sFontLoader.getFallbackFonts(mStyle); - - // insert the font glyph first. - mFonts.add(0, font); - } - - private void init() { - mFonts = sFontLoader.getFont(mFamily, mStyle); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java deleted file mode 100644 index 962d69c..0000000 --- a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package android.graphics; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.awt.Composite; - -/** - * Delegate implementing the native methods of android.graphics.Xfermode - * - * Through the layoutlib_create tool, the original native methods of Xfermode have been replaced - * by calls to methods of the same name in this delegate class. - * - * This class behaves like the original native implementation, but in Java, keeping previously - * native data into its own objects and mapping them to int that are sent back and forth between - * it and the original Xfermode class. - * - * This also serve as a base class for all Xfermode delegate classes. - * - * @see DelegateManager - * - */ -public abstract class Xfermode_Delegate { - - // ---- delegate manager ---- - protected static final DelegateManager<Xfermode_Delegate> sManager = - new DelegateManager<Xfermode_Delegate>(Xfermode_Delegate.class); - - // ---- delegate helper data ---- - - // ---- delegate data ---- - - // ---- Public Helper methods ---- - - public static Xfermode_Delegate getDelegate(int native_instance) { - return sManager.getDelegate(native_instance); - } - - public abstract Composite getComposite(int alpha); - public abstract boolean isSupported(); - public abstract String getSupportMessage(); - - - // ---- native methods ---- - - @LayoutlibDelegate - /*package*/ static void finalizer(int native_instance) { - sManager.removeJavaReferenceFor(native_instance); - } - - // ---- Private delegate/helper methods ---- - -} diff --git a/tools/layoutlib/bridge/src/android/os/Build_Delegate.java b/tools/layoutlib/bridge/src/android/os/Build_Delegate.java deleted file mode 100644 index ff82a5e..0000000 --- a/tools/layoutlib/bridge/src/android/os/Build_Delegate.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.os; - -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.util.Map; - -/** - * Delegate implementing the native methods of android.os.Build - * - * Through the layoutlib_create tool, the original native methods of Build have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -public class Build_Delegate { - - @LayoutlibDelegate - /*package*/ static String getString(String property) { - Map<String, String> properties = Bridge.getPlatformProperties(); - String value = properties.get(property); - if (value != null) { - return value; - } - - return Build.UNKNOWN; - } - -} diff --git a/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java b/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java deleted file mode 100644 index afbe97c..0000000 --- a/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.os; - -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.RenderAction; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Delegate overriding selected methods of android.os.HandlerThread - * - * Through the layoutlib_create tool, selected methods of Handler have been replaced - * by calls to methods of the same name in this delegate class. - * - * - */ -public class HandlerThread_Delegate { - - private static Map<BridgeContext, List<HandlerThread>> sThreads = - new HashMap<BridgeContext, List<HandlerThread>>(); - - public static void cleanUp(BridgeContext context) { - List<HandlerThread> list = sThreads.get(context); - if (list != null) { - for (HandlerThread thread : list) { - thread.quit(); - } - - list.clear(); - sThreads.remove(context); - } - } - - // -------- Delegate methods - - @LayoutlibDelegate - /*package*/ static void run(HandlerThread theThread) { - // record the thread so that it can be quit() on clean up. - BridgeContext context = RenderAction.getCurrentContext(); - List<HandlerThread> list = sThreads.get(context); - if (list == null) { - list = new ArrayList<HandlerThread>(); - sThreads.put(context, list); - } - - list.add(theThread); - - // ---- START DEFAULT IMPLEMENTATION. - - theThread.mTid = Process.myTid(); - Looper.prepare(); - synchronized (theThread) { - theThread.mLooper = Looper.myLooper(); - theThread.notifyAll(); - } - Process.setThreadPriority(theThread.mPriority); - theThread.onLooperPrepared(); - Looper.loop(); - theThread.mTid = -1; - } -} diff --git a/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java b/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java deleted file mode 100644 index 2152c8a..0000000 --- a/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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. - */ - -package android.os; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate overriding selected methods of android.os.Handler - * - * Through the layoutlib_create tool, selected methods of Handler have been replaced - * by calls to methods of the same name in this delegate class. - * - * - */ -public class Handler_Delegate { - - // -------- Delegate methods - - @LayoutlibDelegate - /*package*/ static boolean sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) { - // get the callback - IHandlerCallback callback = sCallbacks.get(); - if (callback != null) { - callback.sendMessageAtTime(handler, msg, uptimeMillis); - } - return true; - } - - // -------- Delegate implementation - - public interface IHandlerCallback { - void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis); - } - - private final static ThreadLocal<IHandlerCallback> sCallbacks = - new ThreadLocal<IHandlerCallback>(); - - public static void setCallback(IHandlerCallback callback) { - sCallbacks.set(callback); - } - -} diff --git a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java deleted file mode 100644 index 09f3e47..0000000 --- a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ -package android.os; - -import java.lang.reflect.Field; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class Looper_Accessor { - - public static void cleanupThread() { - // clean up the looper - Looper.sThreadLocal.remove(); - try { - Field sMainLooper = Looper.class.getDeclaredField("sMainLooper"); - sMainLooper.setAccessible(true); - sMainLooper.set(null, null); - } catch (SecurityException e) { - catchReflectionException(); - } catch (IllegalArgumentException e) { - catchReflectionException(); - } catch (NoSuchFieldException e) { - catchReflectionException(); - } catch (IllegalAccessException e) { - catchReflectionException(); - } - - } - - private static void catchReflectionException() { - assert(false); - } -} diff --git a/tools/layoutlib/bridge/src/android/os/ServiceManager.java b/tools/layoutlib/bridge/src/android/os/ServiceManager.java deleted file mode 100644 index 6a68ee2..0000000 --- a/tools/layoutlib/bridge/src/android/os/ServiceManager.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -package android.os; - -import java.util.Map; - -public final class ServiceManager { - - /** - * Returns a reference to a service with the given name. - * - * @param name the name of the service to get - * @return a reference to the service, or <code>null</code> if the service doesn't exist - */ - public static IBinder getService(String name) { - return null; - } - - /** - * Place a new @a service called @a name into the service - * manager. - * - * @param name the name of the new service - * @param service the service object - */ - public static void addService(String name, IBinder service) { - // pass - } - - /** - * Retrieve an existing service called @a name from the - * service manager. Non-blocking. - */ - public static IBinder checkService(String name) { - return null; - } - - /** - * Return a list of all currently running services. - */ - public static String[] listServices() throws RemoteException { - // actual implementation returns null sometimes, so it's ok - // to return null instead of an empty list. - return null; - } - - /** - * This is only intended to be called when the process is first being brought - * up and bound by the activity manager. There is only one thread in the process - * at that time, so no locking is done. - * - * @param cache the cache of service references - * @hide - */ - public static void initServiceCache(Map<String, IBinder> cache) { - // pass - } -} diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java deleted file mode 100644 index fd594f7..0000000 --- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -package android.os; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.os.SystemClock - * - * Through the layoutlib_create tool, the original native methods of SystemClock have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -public class SystemClock_Delegate { - private static long sBootTime = System.currentTimeMillis(); - private static long sBootTimeNano = System.nanoTime(); - - @LayoutlibDelegate - /*package*/ static boolean setCurrentTimeMillis(long millis) { - return true; - } - - /** - * Returns milliseconds since boot, not counting time spent in deep sleep. - * <b>Note:</b> This value may get reset occasionally (before it would - * otherwise wrap around). - * - * @return milliseconds of non-sleep uptime since boot. - */ - @LayoutlibDelegate - /*package*/ static long uptimeMillis() { - return System.currentTimeMillis() - sBootTime; - } - - /** - * Returns milliseconds since boot, including time spent in sleep. - * - * @return elapsed milliseconds since boot. - */ - @LayoutlibDelegate - /*package*/ static long elapsedRealtime() { - return System.currentTimeMillis() - sBootTime; - } - - /** - * Returns nanoseconds since boot, including time spent in sleep. - * - * @return elapsed nanoseconds since boot. - */ - @LayoutlibDelegate - /*package*/ static long elapsedRealtimeNanos() { - return System.nanoTime() - sBootTimeNano; - } - - /** - * Returns milliseconds running in the current thread. - * - * @return elapsed milliseconds in the thread - */ - @LayoutlibDelegate - /*package*/ static long currentThreadTimeMillis() { - return System.currentTimeMillis(); - } - - /** - * Returns microseconds running in the current thread. - * - * @return elapsed microseconds in the thread - * - * @hide - */ - @LayoutlibDelegate - /*package*/ static long currentThreadTimeMicro() { - return System.currentTimeMillis() * 1000; - } - - /** - * Returns current wall time in microseconds. - * - * @return elapsed microseconds in wall time - * - * @hide - */ - @LayoutlibDelegate - /*package*/ static long currentTimeMicro() { - return elapsedRealtime() * 1000; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java deleted file mode 100644 index 52b8f34..0000000 --- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.text; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate used to provide new implementation for the native methods of {@link AndroidBidi} - * - * Through the layoutlib_create tool, the original methods of AndroidBidi have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class AndroidBidi_Delegate { - - @LayoutlibDelegate - /*package*/ static int runBidi(int dir, char[] chs, byte[] chInfo, int n, boolean haveInfo) { - // return the equivalent of Layout.DIR_LEFT_TO_RIGHT - // TODO: actually figure the direction. - return 0; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java deleted file mode 100644 index 8cd1a69..0000000 --- a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -package android.text.format; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; - - -/** - * Delegate used to provide new implementation for the native methods of {@link DateFormat} - * - * Through the layoutlib_create tool, the original methods of DateFormat have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class DateFormat_Delegate { - - @LayoutlibDelegate - /*package*/ static boolean is24HourFormat(Context context) { - return false; - } -} diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java deleted file mode 100644 index 6ac5b02..0000000 --- a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.util; - -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.internal.util.XmlUtils; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.resources.ResourceType; - -import org.xmlpull.v1.XmlPullParser; - -/** - * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser - */ -public class BridgeXmlPullAttributes extends XmlPullAttributes { - - private final BridgeContext mContext; - private final boolean mPlatformFile; - - public BridgeXmlPullAttributes(XmlPullParser parser, BridgeContext context, - boolean platformFile) { - super(parser); - mContext = context; - mPlatformFile = platformFile; - } - - /* - * (non-Javadoc) - * @see android.util.XmlPullAttributes#getAttributeNameResource(int) - * - * This methods must return com.android.internal.R.attr.<name> matching - * the name of the attribute. - * It returns 0 if it doesn't find anything. - */ - @Override - public int getAttributeNameResource(int index) { - // get the attribute name. - String name = getAttributeName(index); - - // get the attribute namespace - String ns = mParser.getAttributeNamespace(index); - - if (BridgeConstants.NS_RESOURCES.equals(ns)) { - Integer v = Bridge.getResourceId(ResourceType.ATTR, name); - if (v != null) { - return v.intValue(); - } - - return 0; - } - - // this is not an attribute in the android namespace, we query the customviewloader, if - // the namespaces match. - if (mContext.getProjectCallback().getNamespace().equals(ns)) { - Integer v = mContext.getProjectCallback().getResourceId(ResourceType.ATTR, name); - if (v != null) { - return v.intValue(); - } - } - - return 0; - } - - @Override - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToList(value, options, defaultValue); - } - - return defaultValue; - } - - @Override - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToBoolean(value, defaultValue); - } - - return defaultValue; - } - - @Override - public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) { - String value = getAttributeValue(namespace, attribute); - - return resolveResourceValue(value, defaultValue); - } - - @Override - public int getAttributeIntValue(String namespace, String attribute, - int defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToInt(value, defaultValue); - } - - return defaultValue; - } - - @Override - public int getAttributeUnsignedIntValue(String namespace, String attribute, - int defaultValue) { - String value = getAttributeValue(namespace, attribute); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToUnsignedInt(value, defaultValue); - } - - return defaultValue; - } - - @Override - public float getAttributeFloatValue(String namespace, String attribute, - float defaultValue) { - String s = getAttributeValue(namespace, attribute); - if (s != null) { - ResourceValue r = getResourceValue(s); - - if (r != null) { - s = r.getValue(); - } - - return Float.parseFloat(s); - } - - return defaultValue; - } - - @Override - public int getAttributeListValue(int index, - String[] options, int defaultValue) { - return XmlUtils.convertValueToList( - getAttributeValue(index), options, defaultValue); - } - - @Override - public boolean getAttributeBooleanValue(int index, boolean defaultValue) { - String value = getAttributeValue(index); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToBoolean(value, defaultValue); - } - - return defaultValue; - } - - @Override - public int getAttributeResourceValue(int index, int defaultValue) { - String value = getAttributeValue(index); - - return resolveResourceValue(value, defaultValue); - } - - @Override - public int getAttributeIntValue(int index, int defaultValue) { - String value = getAttributeValue(index); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToInt(value, defaultValue); - } - - return defaultValue; - } - - @Override - public int getAttributeUnsignedIntValue(int index, int defaultValue) { - String value = getAttributeValue(index); - if (value != null) { - ResourceValue r = getResourceValue(value); - - if (r != null) { - value = r.getValue(); - } - - return XmlUtils.convertValueToUnsignedInt(value, defaultValue); - } - - return defaultValue; - } - - @Override - public float getAttributeFloatValue(int index, float defaultValue) { - String s = getAttributeValue(index); - if (s != null) { - ResourceValue r = getResourceValue(s); - - if (r != null) { - s = r.getValue(); - } - - return Float.parseFloat(s); - } - - return defaultValue; - } - - // -- private helper methods - - /** - * Returns a resolved {@link ResourceValue} from a given value. - */ - private ResourceValue getResourceValue(String value) { - // now look for this particular value - RenderResources resources = mContext.getRenderResources(); - return resources.resolveResValue(resources.findResValue(value, mPlatformFile)); - } - - /** - * Resolves and return a value to its associated integer. - */ - private int resolveResourceValue(String value, int defaultValue) { - ResourceValue resource = getResourceValue(value); - if (resource != null) { - Integer id = null; - if (mPlatformFile || resource.isFramework()) { - id = Bridge.getResourceId(resource.getResourceType(), resource.getName()); - } else { - id = mContext.getProjectCallback().getResourceId( - resource.getResourceType(), resource.getName()); - } - - if (id != null) { - return id; - } - } - - return defaultValue; - } -} diff --git a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java deleted file mode 100644 index 8b4c60b..0000000 --- a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -package android.util; - -import com.android.layoutlib.bridge.impl.DelegateManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate implementing the native methods of android.util.FloatMath - * - * Through the layoutlib_create tool, the original native methods of FloatMath have been replaced - * by calls to methods of the same name in this delegate class. - * - * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} - * around to map int to instance of the delegate. - * - */ -/*package*/ final class FloatMath_Delegate { - - /** Prevents instantiation. */ - private FloatMath_Delegate() {} - - /** - * Returns the float conversion of the most positive (i.e. closest to - * positive infinity) integer value which is less than the argument. - * - * @param value to be converted - * @return the floor of value - */ - @LayoutlibDelegate - /*package*/ static float floor(float value) { - return (float)Math.floor(value); - } - - /** - * Returns the float conversion of the most negative (i.e. closest to - * negative infinity) integer value which is greater than the argument. - * - * @param value to be converted - * @return the ceiling of value - */ - @LayoutlibDelegate - /*package*/ static float ceil(float value) { - return (float)Math.ceil(value); - } - - /** - * Returns the closest float approximation of the sine of the argument. - * - * @param angle to compute the cosine of, in radians - * @return the sine of angle - */ - @LayoutlibDelegate - /*package*/ static float sin(float angle) { - return (float)Math.sin(angle); - } - - /** - * Returns the closest float approximation of the cosine of the argument. - * - * @param angle to compute the cosine of, in radians - * @return the cosine of angle - */ - @LayoutlibDelegate - /*package*/ static float cos(float angle) { - return (float)Math.cos(angle); - } - - /** - * Returns the closest float approximation of the square root of the - * argument. - * - * @param value to compute sqrt of - * @return the square root of value - */ - @LayoutlibDelegate - /*package*/ static float sqrt(float value) { - return (float)Math.sqrt(value); - } - - /** - * Returns the closest float approximation of the raising "e" to the power - * of the argument. - * - * @param value to compute the exponential of - * @return the exponential of value - */ - @LayoutlibDelegate - /*package*/ static float exp(float value) { - return (float)Math.exp(value); - } - - /** - * Returns the closest float approximation of the result of raising {@code - * x} to the power of {@code y}. - * - * @param x the base of the operation. - * @param y the exponent of the operation. - * @return {@code x} to the power of {@code y}. - */ - @LayoutlibDelegate - /*package*/ static float pow(float x, float y) { - return (float)Math.pow(x, y); - } - - /** - * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i> - * {@code y}</i><sup>{@code 2}</sup>{@code )}. - * - * @param x a float number - * @param y a float number - * @return the hypotenuse - */ - @LayoutlibDelegate - /*package*/ static float hypot(float x, float y) { - return (float)Math.sqrt(x*x + y*y); - } -} diff --git a/tools/layoutlib/bridge/src/android/util/Log_Delegate.java b/tools/layoutlib/bridge/src/android/util/Log_Delegate.java deleted file mode 100644 index 7f432ab..0000000 --- a/tools/layoutlib/bridge/src/android/util/Log_Delegate.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.util; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -class Log_Delegate { - // to replicate prefix visible when using 'adb logcat' - private static char priorityChar(int priority) { - switch (priority) { - case Log.VERBOSE: - return 'V'; - case Log.DEBUG: - return 'D'; - case Log.INFO: - return 'I'; - case Log.WARN: - return 'W'; - case Log.ERROR: - return 'E'; - case Log.ASSERT: - return 'A'; - default: - return '?'; - } - } - - @LayoutlibDelegate - static int println_native(int bufID, int priority, String tag, String msgs) { - String prefix = priorityChar(priority) + "/" + tag + ": "; - for (String msg: msgs.split("\n")) { - System.out.println(prefix + msg); - } - return 0; - } - -} diff --git a/tools/layoutlib/bridge/src/android/util/LruCache.java b/tools/layoutlib/bridge/src/android/util/LruCache.java deleted file mode 100644 index 5208606..0000000 --- a/tools/layoutlib/bridge/src/android/util/LruCache.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.util; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * BEGIN LAYOUTLIB CHANGE - * This is a custom version that doesn't use the non standard LinkedHashMap#eldest. - * END LAYOUTLIB CHANGE - * - * A cache that holds strong references to a limited number of values. Each time - * a value is accessed, it is moved to the head of a queue. When a value is - * added to a full cache, the value at the end of that queue is evicted and may - * become eligible for garbage collection. - * - * <p>If your cached values hold resources that need to be explicitly released, - * override {@link #entryRemoved}. - * - * <p>If a cache miss should be computed on demand for the corresponding keys, - * override {@link #create}. This simplifies the calling code, allowing it to - * assume a value will always be returned, even when there's a cache miss. - * - * <p>By default, the cache size is measured in the number of entries. Override - * {@link #sizeOf} to size the cache in different units. For example, this cache - * is limited to 4MiB of bitmaps: - * <pre> {@code - * int cacheSize = 4 * 1024 * 1024; // 4MiB - * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) { - * protected int sizeOf(String key, Bitmap value) { - * return value.getByteCount(); - * } - * }}</pre> - * - * <p>This class is thread-safe. Perform multiple cache operations atomically by - * synchronizing on the cache: <pre> {@code - * synchronized (cache) { - * if (cache.get(key) == null) { - * cache.put(key, value); - * } - * }}</pre> - * - * <p>This class does not allow null to be used as a key or value. A return - * value of null from {@link #get}, {@link #put} or {@link #remove} is - * unambiguous: the key was not in the cache. - * - * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part - * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's - * Support Package</a> for earlier releases. - */ -public class LruCache<K, V> { - private final LinkedHashMap<K, V> map; - - /** Size of this cache in units. Not necessarily the number of elements. */ - private int size; - private int maxSize; - - private int putCount; - private int createCount; - private int evictionCount; - private int hitCount; - private int missCount; - - /** - * @param maxSize for caches that do not override {@link #sizeOf}, this is - * the maximum number of entries in the cache. For all other caches, - * this is the maximum sum of the sizes of the entries in this cache. - */ - public LruCache(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - this.maxSize = maxSize; - this.map = new LinkedHashMap<K, V>(0, 0.75f, true); - } - - /** - * Sets the size of the cache. - * @param maxSize The new maximum size. - * - * @hide - */ - public void resize(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - - synchronized (this) { - this.maxSize = maxSize; - } - trimToSize(maxSize); - } - - /** - * Returns the value for {@code key} if it exists in the cache or can be - * created by {@code #create}. If a value was returned, it is moved to the - * head of the queue. This returns null if a value is not cached and cannot - * be created. - */ - public final V get(K key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - V mapValue; - synchronized (this) { - mapValue = map.get(key); - if (mapValue != null) { - hitCount++; - return mapValue; - } - missCount++; - } - - /* - * Attempt to create a value. This may take a long time, and the map - * may be different when create() returns. If a conflicting value was - * added to the map while create() was working, we leave that value in - * the map and release the created value. - */ - - V createdValue = create(key); - if (createdValue == null) { - return null; - } - - synchronized (this) { - createCount++; - mapValue = map.put(key, createdValue); - - if (mapValue != null) { - // There was a conflict so undo that last put - map.put(key, mapValue); - } else { - size += safeSizeOf(key, createdValue); - } - } - - if (mapValue != null) { - entryRemoved(false, key, createdValue, mapValue); - return mapValue; - } else { - trimToSize(maxSize); - return createdValue; - } - } - - /** - * Caches {@code value} for {@code key}. The value is moved to the head of - * the queue. - * - * @return the previous value mapped by {@code key}. - */ - public final V put(K key, V value) { - if (key == null || value == null) { - throw new NullPointerException("key == null || value == null"); - } - - V previous; - synchronized (this) { - putCount++; - size += safeSizeOf(key, value); - previous = map.put(key, value); - if (previous != null) { - size -= safeSizeOf(key, previous); - } - } - - if (previous != null) { - entryRemoved(false, key, previous, value); - } - - trimToSize(maxSize); - return previous; - } - - /** - * @param maxSize the maximum size of the cache before returning. May be -1 - * to evict even 0-sized elements. - */ - private void trimToSize(int maxSize) { - while (true) { - K key; - V value; - synchronized (this) { - if (size < 0 || (map.isEmpty() && size != 0)) { - throw new IllegalStateException(getClass().getName() - + ".sizeOf() is reporting inconsistent results!"); - } - - if (size <= maxSize) { - break; - } - - // BEGIN LAYOUTLIB CHANGE - // get the last item in the linked list. - // This is not efficient, the goal here is to minimize the changes - // compared to the platform version. - Map.Entry<K, V> toEvict = null; - for (Map.Entry<K, V> entry : map.entrySet()) { - toEvict = entry; - } - // END LAYOUTLIB CHANGE - - if (toEvict == null) { - break; - } - - key = toEvict.getKey(); - value = toEvict.getValue(); - map.remove(key); - size -= safeSizeOf(key, value); - evictionCount++; - } - - entryRemoved(true, key, value, null); - } - } - - /** - * Removes the entry for {@code key} if it exists. - * - * @return the previous value mapped by {@code key}. - */ - public final V remove(K key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - V previous; - synchronized (this) { - previous = map.remove(key); - if (previous != null) { - size -= safeSizeOf(key, previous); - } - } - - if (previous != null) { - entryRemoved(false, key, previous, null); - } - - return previous; - } - - /** - * Called for entries that have been evicted or removed. This method is - * invoked when a value is evicted to make space, removed by a call to - * {@link #remove}, or replaced by a call to {@link #put}. The default - * implementation does nothing. - * - * <p>The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - * @param evicted true if the entry is being removed to make space, false - * if the removal was caused by a {@link #put} or {@link #remove}. - * @param newValue the new value for {@code key}, if it exists. If non-null, - * this removal was caused by a {@link #put}. Otherwise it was caused by - * an eviction or a {@link #remove}. - */ - protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} - - /** - * Called after a cache miss to compute a value for the corresponding key. - * Returns the computed value or null if no value can be computed. The - * default implementation returns null. - * - * <p>The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - * <p>If a value for {@code key} exists in the cache when this method - * returns, the created value will be released with {@link #entryRemoved} - * and discarded. This can occur when multiple threads request the same key - * at the same time (causing multiple values to be created), or when one - * thread calls {@link #put} while another is creating a value for the same - * key. - */ - protected V create(K key) { - return null; - } - - private int safeSizeOf(K key, V value) { - int result = sizeOf(key, value); - if (result < 0) { - throw new IllegalStateException("Negative size: " + key + "=" + value); - } - return result; - } - - /** - * Returns the size of the entry for {@code key} and {@code value} in - * user-defined units. The default implementation returns 1 so that size - * is the number of entries and max size is the maximum number of entries. - * - * <p>An entry's size must not change while it is in the cache. - */ - protected int sizeOf(K key, V value) { - return 1; - } - - /** - * Clear the cache, calling {@link #entryRemoved} on each removed entry. - */ - public final void evictAll() { - trimToSize(-1); // -1 will evict 0-sized elements - } - - /** - * For caches that do not override {@link #sizeOf}, this returns the number - * of entries in the cache. For all other caches, this returns the sum of - * the sizes of the entries in this cache. - */ - public synchronized final int size() { - return size; - } - - /** - * For caches that do not override {@link #sizeOf}, this returns the maximum - * number of entries in the cache. For all other caches, this returns the - * maximum sum of the sizes of the entries in this cache. - */ - public synchronized final int maxSize() { - return maxSize; - } - - /** - * Returns the number of times {@link #get} returned a value that was - * already present in the cache. - */ - public synchronized final int hitCount() { - return hitCount; - } - - /** - * Returns the number of times {@link #get} returned null or required a new - * value to be created. - */ - public synchronized final int missCount() { - return missCount; - } - - /** - * Returns the number of times {@link #create(Object)} returned a value. - */ - public synchronized final int createCount() { - return createCount; - } - - /** - * Returns the number of times {@link #put} was called. - */ - public synchronized final int putCount() { - return putCount; - } - - /** - * Returns the number of values that have been evicted. - */ - public synchronized final int evictionCount() { - return evictionCount; - } - - /** - * Returns a copy of the current contents of the cache, ordered from least - * recently accessed to most recently accessed. - */ - public synchronized final Map<K, V> snapshot() { - return new LinkedHashMap<K, V>(map); - } - - @Override public synchronized final String toString() { - int accesses = hitCount + missCount; - int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; - return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", - maxSize, hitCount, missCount, hitPercent); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java deleted file mode 100644 index 4901f72..0000000 --- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view; - -import com.android.layoutlib.bridge.android.BridgeWindow; -import com.android.layoutlib.bridge.android.BridgeWindowSession; - -import android.content.Context; -import android.os.Handler; -import android.view.View.AttachInfo; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class AttachInfo_Accessor { - - public static void setAttachInfo(View view) { - Context context = view.getContext(); - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - ViewRootImpl root = new ViewRootImpl(context, display); - AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(), - display, root, new Handler(), null); - info.mHasWindowFocus = true; - info.mWindowVisibility = View.VISIBLE; - info.mInTouchMode = false; // this is so that we can display selections. - info.mHardwareAccelerated = false; - view.dispatchAttachedToWindow(info, 0); - } - - public static void dispatchOnPreDraw(View view) { - view.mAttachInfo.mTreeObserver.dispatchOnPreDraw(); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java deleted file mode 100644 index 941f1ce6..0000000 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.view; - -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.MergeCookie; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.resources.ResourceType; -import com.android.util.Pair; - -import org.xmlpull.v1.XmlPullParser; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.InflateException; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import java.io.File; - -/** - * Custom implementation of {@link LayoutInflater} to handle custom views. - */ -public final class BridgeInflater extends LayoutInflater { - - private final IProjectCallback mProjectCallback; - private boolean mIsInMerge = false; - private ResourceReference mResourceReference; - - /** - * List of class prefixes which are tried first by default. - * <p/> - * This should match the list in com.android.internal.policy.impl.PhoneLayoutInflater. - */ - private static final String[] sClassPrefixList = { - "android.widget.", - "android.webkit." - }; - - protected BridgeInflater(LayoutInflater original, Context newContext) { - super(original, newContext); - mProjectCallback = null; - } - - /** - * Instantiate a new BridgeInflater with an {@link IProjectCallback} object. - * - * @param context The Android application context. - * @param projectCallback the {@link IProjectCallback} object. - */ - public BridgeInflater(Context context, IProjectCallback projectCallback) { - super(context); - mProjectCallback = projectCallback; - mConstructorArgs[0] = context; - } - - @Override - public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException { - View view = null; - - try { - // First try to find a class using the default Android prefixes - for (String prefix : sClassPrefixList) { - try { - view = createView(name, prefix, attrs); - if (view != null) { - break; - } - } catch (ClassNotFoundException e) { - // Ignore. We'll try again using the base class below. - } - } - - // Next try using the parent loader. This will most likely only work for - // fully-qualified class names. - try { - if (view == null) { - view = super.onCreateView(name, attrs); - } - } catch (ClassNotFoundException e) { - // Ignore. We'll try again using the custom view loader below. - } - - // Finally try again using the custom view loader - try { - if (view == null) { - view = loadCustomView(name, attrs); - } - } catch (ClassNotFoundException e) { - // If the class was not found, we throw the exception directly, because this - // method is already expected to throw it. - throw e; - } - } catch (Exception e) { - // Wrap the real exception in a ClassNotFoundException, so that the calling method - // can deal with it. - ClassNotFoundException exception = new ClassNotFoundException("onCreateView", e); - throw exception; - } - - setupViewInContext(view, attrs); - - return view; - } - - @Override - public View createViewFromTag(View parent, String name, AttributeSet attrs) { - View view = null; - try { - view = super.createViewFromTag(parent, name, attrs); - } catch (InflateException e) { - // try to load the class from using the custom view loader - try { - view = loadCustomView(name, attrs); - } catch (Exception e2) { - // Wrap the real exception in an InflateException so that the calling - // method can deal with it. - InflateException exception = new InflateException(); - if (e2.getClass().equals(ClassNotFoundException.class) == false) { - exception.initCause(e2); - } else { - exception.initCause(e); - } - throw exception; - } - } - - setupViewInContext(view, attrs); - - return view; - } - - @Override - public View inflate(int resource, ViewGroup root) { - Context context = getContext(); - if (context instanceof BridgeContext) { - BridgeContext bridgeContext = (BridgeContext)context; - - ResourceValue value = null; - - Pair<ResourceType, String> layoutInfo = Bridge.resolveResourceId(resource); - if (layoutInfo != null) { - value = bridgeContext.getRenderResources().getFrameworkResource( - ResourceType.LAYOUT, layoutInfo.getSecond()); - } else { - layoutInfo = mProjectCallback.resolveResourceId(resource); - - if (layoutInfo != null) { - value = bridgeContext.getRenderResources().getProjectResource( - ResourceType.LAYOUT, layoutInfo.getSecond()); - } - } - - if (value != null) { - File f = new File(value.getValue()); - if (f.isFile()) { - try { - XmlPullParser parser = ParserFactory.create(f); - - BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( - parser, bridgeContext, false); - - return inflate(bridgeParser, root); - } catch (Exception e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed to parse file " + f.getAbsolutePath(), e, null /*data*/); - - return null; - } - } - } - } - return null; - } - - private View loadCustomView(String name, AttributeSet attrs) throws ClassNotFoundException, - Exception{ - if (mProjectCallback != null) { - // first get the classname in case it's not the node name - if (name.equals("view")) { - name = attrs.getAttributeValue(null, "class"); - } - - mConstructorArgs[1] = attrs; - - Object customView = mProjectCallback.loadView(name, mConstructorSignature, - mConstructorArgs); - - if (customView instanceof View) { - return (View)customView; - } - } - - return null; - } - - private void setupViewInContext(View view, AttributeSet attrs) { - if (getContext() instanceof BridgeContext) { - BridgeContext bc = (BridgeContext) getContext(); - if (attrs instanceof BridgeXmlBlockParser) { - BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs; - - // get the view key - Object viewKey = parser.getViewCookie(); - - if (viewKey == null) { - int currentDepth = parser.getDepth(); - - // test whether we are in an included file or in a adapter binding view. - BridgeXmlBlockParser previousParser = bc.getPreviousParser(); - if (previousParser != null) { - // looks like we inside an embedded layout. - // only apply the cookie of the calling node (<include>) if we are at the - // top level of the embedded layout. If there is a merge tag, then - // skip it and look for the 2nd level - int testDepth = mIsInMerge ? 2 : 1; - if (currentDepth == testDepth) { - viewKey = previousParser.getViewCookie(); - // if we are in a merge, wrap the cookie in a MergeCookie. - if (viewKey != null && mIsInMerge) { - viewKey = new MergeCookie(viewKey); - } - } - } else if (mResourceReference != null && currentDepth == 1) { - // else if there's a resource reference, this means we are in an adapter - // binding case. Set the resource ref as the view cookie only for the top - // level view. - viewKey = mResourceReference; - } - } - - if (viewKey != null) { - bc.addViewKey(view, viewKey); - } - } - } - } - - public void setIsInMerge(boolean isInMerge) { - mIsInMerge = isInMerge; - } - - public void setResourceReference(ResourceReference reference) { - mResourceReference = reference; - } - - @Override - public LayoutInflater cloneInContext(Context newContext) { - return new BridgeInflater(this, newContext); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java deleted file mode 100644 index f75ee50..0000000 --- a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ -package android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of {@link Choreographer} - * - * Through the layoutlib_create tool, the original methods of Choreographer have been - * replaced by calls to methods of the same name in this delegate class. - * - */ -public class Choreographer_Delegate { - - @LayoutlibDelegate - public static float getRefreshRate() { - return 60.f; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java deleted file mode 100644 index 53dc821..0000000 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate used to provide new implementation of a select few methods of {@link Display} - * - * Through the layoutlib_create tool, the original methods of Display have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class Display_Delegate { - - @LayoutlibDelegate - static void updateDisplayInfoLocked(Display theDisplay) { - // do nothing - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java deleted file mode 100644 index f0c3a75..0000000 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view; - -import android.graphics.Point; -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodClient; - -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.IBinder; -import android.os.IRemoteCallback; -import android.os.RemoteException; -import android.util.DisplayMetrics; -import android.view.Display; -import android.view.Gravity; -import android.view.IApplicationToken; -import android.view.IInputFilter; -import android.view.IOnKeyguardExitResult; -import android.view.IRotationWatcher; -import android.view.IWindowManager; -import android.view.IWindowSession; - -import java.util.List; - -/** - * Basic implementation of {@link IWindowManager} so that {@link Display} (and - * {@link Display_Delegate}) can return a valid instance. - */ -public class IWindowManagerImpl implements IWindowManager { - - private final Configuration mConfig; - private final DisplayMetrics mMetrics; - private final int mRotation; - private final boolean mHasNavigationBar; - - public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation, - boolean hasNavigationBar) { - mConfig = config; - mMetrics = metrics; - mRotation = rotation; - mHasNavigationBar = hasNavigationBar; - } - - // custom API. - - public DisplayMetrics getMetrics() { - return mMetrics; - } - - // ---- implementation of IWindowManager that we care about ---- - - @Override - public int getRotation() throws RemoteException { - return mRotation; - } - - @Override - public boolean hasNavigationBar() { - return mHasNavigationBar; - } - - // ---- unused implementation of IWindowManager ---- - - @Override - public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4, - boolean arg5, boolean arg6, int arg7) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void addWindowToken(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void clearForcedDisplaySize(int displayId) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void clearForcedDisplayDensity(int displayId) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setOverscan(int displayId, int left, int top, int right, int bottom) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void closeSystemDialogs(String arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void startFreezingScreen(int exitAnim, int enterAnim) { - // TODO Auto-generated method stub - } - - @Override - public void stopFreezingScreen() { - // TODO Auto-generated method stub - } - - @Override - public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void executeAppTransition() throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void freezeRotation(int arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public float getAnimationScale(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public float[] getAnimationScales() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getAppOrientation(IApplicationToken arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getPendingAppTransition() throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public boolean inKeyguardRestrictedInputMode() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isKeyguardLocked() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isKeyguardSecure() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isViewServerRunning() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void overridePendingAppTransition(String arg0, int arg1, int arg2, - IRemoteCallback startedCallback) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth, - int startHeight) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, - IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void pauseKeyDispatching(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void reenableKeyguard(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void removeAppToken(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void removeWindowToken(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void resumeKeyDispatching(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1, int arg2) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setAnimationScale(int arg0, float arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAnimationScales(float[] arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3, - CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setAppVisibility(IBinder arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAppWillBeHidden(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setEventDispatching(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void getInitialDisplaySize(int displayId, Point size) { - // TODO Auto-generated method stub - } - - @Override - public void getBaseDisplaySize(int displayId, Point size) { - // TODO Auto-generated method stub - } - - @Override - public void setForcedDisplaySize(int displayId, int arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public int getInitialDisplayDensity(int displayId) { - return -1; - } - - @Override - public int getBaseDisplayDensity(int displayId) { - return -1; - } - - @Override - public void setForcedDisplayDensity(int displayId, int density) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setInTouchMode(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setNewConfiguration(Configuration arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void updateRotation(boolean arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void showStrictModeViolation(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void startAppFreezingScreen(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public boolean startViewServer(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void statusBarVisibilityChanged(int arg0) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void stopAppFreezingScreen(IBinder arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public boolean stopViewServer() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void thawRotation() throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int watchRotation(IRotationWatcher arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void removeRotationWatcher(IRotationWatcher arg0) throws RemoteException { - } - - @Override - public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { - return false; - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getPreferredOptionsPanelGravity() throws RemoteException { - return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; - } - - @Override - public void dismissKeyguard() { - } - - @Override - public void lockNow(Bundle options) { - // TODO Auto-generated method stub - } - - @Override - public boolean isSafeModeEnabled() { - return false; - } - - @Override - public void showAssistant() { - - } - - @Override - public IBinder getFocusedWindowToken() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setInputFilter(IInputFilter filter) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void getWindowFrame(IBinder token, Rect outFrame) { - // TODO Auto-generated method stub - } - - @Override - public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) { - // TODO Auto-generated method stub - } - - @Override - public void setMagnificationSpec(MagnificationSpec spec) { - // TODO Auto-generated method stub - } - - @Override - public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isRotationFrozen() throws RemoteException { - // TODO Auto-generated method stub - return false; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java deleted file mode 100644 index 3db3a1b..0000000 --- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.Xml; - -import java.io.IOException; - -/** - * Delegate used to provide new implementation of a select few methods of {@link LayoutInflater} - * - * Through the layoutlib_create tool, the original methods of LayoutInflater have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class LayoutInflater_Delegate { - - private static final String TAG_MERGE = "merge"; - - public static boolean sIsInInclude = false; - - /** - * Recursive method used to descend down the xml hierarchy and instantiate - * views, instantiate their children, and then call onFinishInflate(). - * - * This implementation just records the merge status before calling the default implementation. - */ - @LayoutlibDelegate - /*package*/ static void rInflate(LayoutInflater thisInflater, - XmlPullParser parser, View parent, final AttributeSet attrs, - boolean finishInflate) throws XmlPullParserException, IOException { - - if (finishInflate == false) { - // this is a merge rInflate! - if (thisInflater instanceof BridgeInflater) { - ((BridgeInflater) thisInflater).setIsInMerge(true); - } - } - - // ---- START DEFAULT IMPLEMENTATION. - - thisInflater.rInflate_Original(parser, parent, attrs, finishInflate); - - // ---- END DEFAULT IMPLEMENTATION. - - if (finishInflate == false) { - // this is a merge rInflate! - if (thisInflater instanceof BridgeInflater) { - ((BridgeInflater) thisInflater).setIsInMerge(false); - } - } - } - - @LayoutlibDelegate - public static void parseInclude( - LayoutInflater thisInflater, - XmlPullParser parser, View parent, AttributeSet attrs) - throws XmlPullParserException, IOException { - - int type; - - if (parent instanceof ViewGroup) { - final int layout = attrs.getAttributeResourceValue(null, "layout", 0); - if (layout == 0) { - final String value = attrs.getAttributeValue(null, "layout"); - if (value == null) { - throw new InflateException("You must specifiy a layout in the" - + " include tag: <include layout=\"@layout/layoutID\" />"); - } else { - throw new InflateException("You must specifiy a valid layout " - + "reference. The layout ID " + value + " is not valid."); - } - } else { - final XmlResourceParser childParser = - thisInflater.getContext().getResources().getLayout(layout); - - try { - final AttributeSet childAttrs = Xml.asAttributeSet(childParser); - - while ((type = childParser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty. - } - - if (type != XmlPullParser.START_TAG) { - throw new InflateException(childParser.getPositionDescription() + - ": No start tag found!"); - } - - final String childName = childParser.getName(); - - if (TAG_MERGE.equals(childName)) { - // Inflate all children. - thisInflater.rInflate(childParser, parent, childAttrs, false); - } else { - final View view = thisInflater.createViewFromTag(parent, childName, childAttrs); - final ViewGroup group = (ViewGroup) parent; - - // We try to load the layout params set in the <include /> tag. If - // they don't exist, we will rely on the layout params set in the - // included XML file. - // During a layoutparams generation, a runtime exception is thrown - // if either layout_width or layout_height is missing. We catch - // this exception and set localParams accordingly: true means we - // successfully loaded layout params from the <include /> tag, - // false means we need to rely on the included layout params. - ViewGroup.LayoutParams params = null; - try { - // ---- START CHANGES - sIsInInclude = true; - // ---- END CHANGES - - params = group.generateLayoutParams(attrs); - - } catch (RuntimeException e) { - // ---- START CHANGES - sIsInInclude = false; - // ---- END CHANGES - - params = group.generateLayoutParams(childAttrs); - } finally { - // ---- START CHANGES - sIsInInclude = false; - // ---- END CHANGES - - if (params != null) { - view.setLayoutParams(params); - } - } - - // Inflate all children. - thisInflater.rInflate(childParser, view, childAttrs, true); - - // Attempt to override the included layout's android:id with the - // one set on the <include /> tag itself. - TypedArray a = thisInflater.mContext.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.View, 0, 0); - int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID); - // While we're at it, let's try to override android:visibility. - int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1); - a.recycle(); - - if (id != View.NO_ID) { - view.setId(id); - } - - switch (visibility) { - case 0: - view.setVisibility(View.VISIBLE); - break; - case 1: - view.setVisibility(View.INVISIBLE); - break; - case 2: - view.setVisibility(View.GONE); - break; - } - - group.addView(view); - } - } finally { - childParser.close(); - } - } - } else { - throw new InflateException("<include /> can only be used inside of a ViewGroup"); - } - - final int currentDepth = parser.getDepth(); - while (((type = parser.next()) != XmlPullParser.END_TAG || - parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) { - // Empty - } - } - - -} diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java deleted file mode 100644 index 6aa4b3b..0000000 --- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2006 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. - */ - -package android.view; - -import com.android.layoutlib.bridge.MockView; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.util.AttributeSet; - -/** - * Mock version of the SurfaceView. - * Only non override public methods from the real SurfaceView have been added in there. - * Methods that take an unknown class as parameter or as return object, have been removed for now. - * - * TODO: generate automatically. - * - */ -public class SurfaceView extends MockView { - - public SurfaceView(Context context) { - this(context, null); - } - - public SurfaceView(Context context, AttributeSet attrs) { - this(context, attrs , 0); - } - - public SurfaceView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public SurfaceHolder getHolder() { - return mSurfaceHolder; - } - - private SurfaceHolder mSurfaceHolder = new SurfaceHolder() { - - @Override - public boolean isCreating() { - return false; - } - - @Override - public void addCallback(Callback callback) { - } - - @Override - public void removeCallback(Callback callback) { - } - - @Override - public void setFixedSize(int width, int height) { - } - - @Override - public void setSizeFromLayout() { - } - - @Override - public void setFormat(int format) { - } - - @Override - public void setType(int type) { - } - - @Override - public void setKeepScreenOn(boolean screenOn) { - } - - @Override - public Canvas lockCanvas() { - return null; - } - - @Override - public Canvas lockCanvas(Rect dirty) { - return null; - } - - @Override - public void unlockCanvasAndPost(Canvas canvas) { - } - - @Override - public Surface getSurface() { - return null; - } - - @Override - public Rect getSurfaceFrame() { - return null; - } - }; -} - diff --git a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java deleted file mode 100644 index c3533e0..0000000 --- a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class ViewConfiguration_Accessor { - - public static void clearConfigurations() { - // clear the stored ViewConfiguration since the map is per density and not per context. - ViewConfiguration.sConfigurations.clear(); - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java deleted file mode 100644 index 14b84ef..0000000 --- a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -package android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of {@link ViewRootImpl} - * - * Through the layoutlib_create tool, the original methods of ViewRootImpl have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class ViewRootImpl_Delegate { - - @LayoutlibDelegate - /*package*/ static boolean isInTouchMode() { - return false; // this allows displaying selection. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/View_Delegate.java b/tools/layoutlib/bridge/src/android/view/View_Delegate.java deleted file mode 100644 index 8215f7c..0000000 --- a/tools/layoutlib/bridge/src/android/view/View_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of {@link View} - * - * Through the layoutlib_create tool, the original methods of View have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class View_Delegate { - - @LayoutlibDelegate - /*package*/ static boolean isInEditMode(View thisView) { - return true; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java deleted file mode 100644 index 2606e55..0000000 --- a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -package android.view; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide new implementation of a select few methods of - * {@link WindowManagerGlobal} - * - * Through the layoutlib_create tool, the original methods of WindowManagerGlobal have been - * replaced by calls to methods of the same name in this delegate class. - * - */ -public class WindowManagerGlobal_Delegate { - - private static IWindowManager sService; - - @LayoutlibDelegate - public static IWindowManager getWindowManagerService() { - return sService; - } - - // ---- internal implementation stuff ---- - - public static void setWindowManagerService(IWindowManager service) { - sService = service; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java deleted file mode 100644 index 1fd7836..0000000 --- a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -package android.view.accessibility; - -import android.accessibilityservice.AccessibilityServiceInfo; -import android.content.Context; -import android.content.pm.ServiceInfo; -import android.view.IWindow; -import android.view.View; - -import java.util.Collections; -import java.util.List; - -/** - * System level service that serves as an event dispatch for {@link AccessibilityEvent}s. - * Such events are generated when something notable happens in the user interface, - * for example an {@link android.app.Activity} starts, the focus or selection of a - * {@link android.view.View} changes etc. Parties interested in handling accessibility - * events implement and register an accessibility service which extends - * {@link android.accessibilityservice.AccessibilityService}. - * - * @see AccessibilityEvent - * @see android.accessibilityservice.AccessibilityService - * @see android.content.Context#getSystemService - */ -public final class AccessibilityManager { - private static AccessibilityManager sInstance = new AccessibilityManager(); - - /** - * Listener for the accessibility state. - */ - public interface AccessibilityStateChangeListener { - - /** - * Called back on change in the accessibility state. - * - * @param enabled Whether accessibility is enabled. - */ - public void onAccessibilityStateChanged(boolean enabled); - } - - /** - * Get an AccessibilityManager instance (create one if necessary). - * - * @hide - */ - public static AccessibilityManager getInstance(Context context) { - return sInstance; - } - - /** - * Create an instance. - * - * @param context A {@link Context}. - */ - private AccessibilityManager() { - } - - /** - * Returns if the {@link AccessibilityManager} is enabled. - * - * @return True if this {@link AccessibilityManager} is enabled, false otherwise. - */ - public boolean isEnabled() { - return false; - } - - /** - * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not - * enabled the call is a NOOP. - * - * @param event The {@link AccessibilityEvent}. - * - * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent} - * while accessibility is not enabled. - */ - public void sendAccessibilityEvent(AccessibilityEvent event) { - } - - /** - * Requests interruption of the accessibility feedback from all accessibility services. - */ - public void interrupt() { - } - - /** - * Returns the {@link ServiceInfo}s of the installed accessibility services. - * - * @return An unmodifiable list with {@link ServiceInfo}s. - */ - public List<ServiceInfo> getAccessibilityServiceList() { - // normal implementation does this in some case, so let's do the same - // (unmodifiableList wrapped around null). - List<ServiceInfo> services = null; - return Collections.unmodifiableList(services); - } - - public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() { - // normal implementation does this in some case, so let's do the same - // (unmodifiableList wrapped around null). - List<AccessibilityServiceInfo> services = null; - return Collections.unmodifiableList(services); - } - - public boolean addAccessibilityStateChangeListener( - AccessibilityStateChangeListener listener) { - return true; - } - - public boolean removeAccessibilityStateChangeListener( - AccessibilityStateChangeListener listener) { - return true; - } - - public int addAccessibilityInteractionConnection(IWindow windowToken, - IAccessibilityInteractionConnection connection) { - return View.NO_ID; - } - - public void removeAccessibilityInteractionConnection(IWindow windowToken) { - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java deleted file mode 100644 index dc4f9c8..0000000 --- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view.inputmethod; - -/** - * Class allowing access to package-protected methods/fields. - */ -public class InputMethodManager_Accessor { - - public static void resetInstance() { - InputMethodManager.sInstance = null; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java deleted file mode 100644 index 7c98847..0000000 --- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package android.view.inputmethod; - -import com.android.layoutlib.bridge.android.BridgeIInputMethodManager; -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.content.Context; -import android.os.Looper; - - -/** - * Delegate used to provide new implementation of a select few methods of {@link InputMethodManager} - * - * Through the layoutlib_create tool, the original methods of InputMethodManager have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class InputMethodManager_Delegate { - - // ---- Overridden methods ---- - - @LayoutlibDelegate - /*package*/ static InputMethodManager getInstance() { - synchronized (InputMethodManager.class) { - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm == null) { - imm = new InputMethodManager( - new BridgeIInputMethodManager(), Looper.getMainLooper()); - InputMethodManager.sInstance = imm; - } - return imm; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java deleted file mode 100644 index 3b66188..0000000 --- a/tools/layoutlib/bridge/src/android/webkit/WebView.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.webkit; - -import com.android.layoutlib.bridge.MockView; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Picture; -import android.os.Bundle; -import android.os.Message; -import android.util.AttributeSet; -import android.view.View; - -/** - * Mock version of the WebView. - * Only non override public methods from the real WebView have been added in there. - * Methods that take an unknown class as parameter or as return object, have been removed for now. - * - * TODO: generate automatically. - * - */ -public class WebView extends MockView { - - /** - * Construct a new WebView with a Context object. - * @param context A Context object used to access application assets. - */ - public WebView(Context context) { - this(context, null); - } - - /** - * Construct a new WebView with layout parameters. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - */ - public WebView(Context context, AttributeSet attrs) { - this(context, attrs, com.android.internal.R.attr.webViewStyle); - } - - /** - * Construct a new WebView with layout parameters and a default style. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - * @param defStyle The default style resource ID. - */ - public WebView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - // START FAKE PUBLIC METHODS - - public void setHorizontalScrollbarOverlay(boolean overlay) { - } - - public void setVerticalScrollbarOverlay(boolean overlay) { - } - - public boolean overlayHorizontalScrollbar() { - return false; - } - - public boolean overlayVerticalScrollbar() { - return false; - } - - public void savePassword(String host, String username, String password) { - } - - public void setHttpAuthUsernamePassword(String host, String realm, - String username, String password) { - } - - public String[] getHttpAuthUsernamePassword(String host, String realm) { - return null; - } - - public void destroy() { - } - - public static void enablePlatformNotifications() { - } - - public static void disablePlatformNotifications() { - } - - public WebBackForwardList saveState(Bundle outState) { - return null; - } - - public WebBackForwardList restoreState(Bundle inState) { - return null; - } - - public void loadUrl(String url) { - } - - public void loadData(String data, String mimeType, String encoding) { - } - - public void loadDataWithBaseURL(String baseUrl, String data, - String mimeType, String encoding, String failUrl) { - } - - public void stopLoading() { - } - - public void reload() { - } - - public boolean canGoBack() { - return false; - } - - public void goBack() { - } - - public boolean canGoForward() { - return false; - } - - public void goForward() { - } - - public boolean canGoBackOrForward(int steps) { - return false; - } - - public void goBackOrForward(int steps) { - } - - public boolean pageUp(boolean top) { - return false; - } - - public boolean pageDown(boolean bottom) { - return false; - } - - public void clearView() { - } - - public Picture capturePicture() { - return null; - } - - public float getScale() { - return 0; - } - - public void setInitialScale(int scaleInPercent) { - } - - public void invokeZoomPicker() { - } - - public void requestFocusNodeHref(Message hrefMsg) { - } - - public void requestImageRef(Message msg) { - } - - public String getUrl() { - return null; - } - - public String getTitle() { - return null; - } - - public Bitmap getFavicon() { - return null; - } - - public int getProgress() { - return 0; - } - - public int getContentHeight() { - return 0; - } - - public void pauseTimers() { - } - - public void resumeTimers() { - } - - public void clearCache() { - } - - public void clearFormData() { - } - - public void clearHistory() { - } - - public void clearSslPreferences() { - } - - public WebBackForwardList copyBackForwardList() { - return null; - } - - public static String findAddress(String addr) { - return null; - } - - public void documentHasImages(Message response) { - } - - public void setWebViewClient(WebViewClient client) { - } - - public void setDownloadListener(DownloadListener listener) { - } - - public void setWebChromeClient(WebChromeClient client) { - } - - public void addJavascriptInterface(Object obj, String interfaceName) { - } - - public WebSettings getSettings() { - return null; - } - - public View getZoomControls() { - return null; - } - - public boolean zoomIn() { - return false; - } - - public boolean zoomOut() { - return false; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java b/tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java deleted file mode 100644 index 0100dc5..0000000 --- a/tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -package com.android.internal.policy; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.impl.RenderAction; - -import android.content.Context; -import android.view.BridgeInflater; -import android.view.FallbackEventHandler; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.Window; -import android.view.WindowManagerPolicy; - -/** - * Custom implementation of PolicyManager that does nothing to run in LayoutLib. - * - */ -public class PolicyManager { - - public static Window makeNewWindow(Context context) { - // this will likely crash somewhere beyond so we log it. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Call to PolicyManager.makeNewWindow is not supported", null); - return null; - } - - public static LayoutInflater makeNewLayoutInflater(Context context) { - return new BridgeInflater(context, RenderAction.getCurrentContext().getProjectCallback()); - } - - public static WindowManagerPolicy makeNewWindowManager() { - // this will likely crash somewhere beyond so we log it. - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, - "Call to PolicyManager.makeNewWindowManager is not supported", null); - return null; - } - - public static FallbackEventHandler makeNewFallbackEventHandler(Context context) { - return new FallbackEventHandler() { - @Override - public void setView(View v) { - } - - @Override - public void preDispatchKeyEvent(KeyEvent event) { - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - return false; - } - }; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/textservice/ITextServicesManager_Stub_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/textservice/ITextServicesManager_Stub_Delegate.java deleted file mode 100644 index 3017292..0000000 --- a/tools/layoutlib/bridge/src/com/android/internal/textservice/ITextServicesManager_Stub_Delegate.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.internal.textservice; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.view.textservice.SpellCheckerInfo; -import android.view.textservice.SpellCheckerSubtype; - - -/** - * Delegate used to provide new implementation of a select few methods of - * {@link ITextServicesManager$Stub} - * - * Through the layoutlib_create tool, the original methods of Stub have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class ITextServicesManager_Stub_Delegate { - - @LayoutlibDelegate - public static ITextServicesManager asInterface(IBinder obj) { - // ignore the obj and return a fake interface implementation - return new FakeTextServicesManager(); - } - - private static class FakeTextServicesManager implements ITextServicesManager { - - @Override - public void finishSpellCheckerService(ISpellCheckerSessionListener arg0) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public SpellCheckerInfo getCurrentSpellChecker(String arg0) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String arg0, boolean arg1) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public SpellCheckerInfo[] getEnabledSpellCheckers() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void getSpellCheckerService(String arg0, String arg1, - ITextServicesSessionListener arg2, ISpellCheckerSessionListener arg3, Bundle arg4) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean isSpellCheckerEnabled() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setCurrentSpellChecker(String arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setCurrentSpellCheckerSubtype(String arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setSpellCheckerEnabled(boolean arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } - - } - } diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java deleted file mode 100644 index bf998b8..0000000 --- a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.internal.util; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - - -/** - * Delegate used to provide new implementation of a select few methods of {@link XmlUtils} - * - * Through the layoutlib_create tool, the original methods of XmlUtils have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class XmlUtils_Delegate { - - @LayoutlibDelegate - /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) { - if (null == charSeq) - return defaultValue; - - String nm = charSeq.toString(); - - // This code is copied from the original implementation. The issue is that - // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX - // is > 80000000 but the Java VM cannot. - - int sign = 1; - int index = 0; - int len = nm.length(); - int base = 10; - - if ('-' == nm.charAt(0)) { - sign = -1; - index++; - } - - if ('0' == nm.charAt(index)) { - // Quick check for a zero by itself - if (index == (len - 1)) - return 0; - - char c = nm.charAt(index + 1); - - if ('x' == c || 'X' == c) { - index += 2; - base = 16; - } else { - index++; - base = 8; - } - } - else if ('#' == nm.charAt(index)) { - index++; - base = 16; - } - - return ((int)Long.parseLong(nm.substring(index), base)) * sign; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java deleted file mode 100644 index 42257c5..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge; - -import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; -import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; - -import com.android.ide.common.rendering.api.Capability; -import com.android.ide.common.rendering.api.DrawableParams; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.layoutlib.bridge.impl.FontLoader; -import com.android.layoutlib.bridge.impl.RenderDrawable; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; -import com.android.layoutlib.bridge.util.DynamicIdMap; -import com.android.ninepatch.NinePatchChunk; -import com.android.resources.ResourceType; -import com.android.tools.layoutlib.create.MethodAdapter; -import com.android.tools.layoutlib.create.OverrideMethod; -import com.android.util.Pair; - -import android.content.res.BridgeAssetManager; -import android.graphics.Bitmap; -import android.graphics.Typeface_Accessor; -import android.graphics.Typeface_Delegate; -import android.os.Looper; -import android.os.Looper_Accessor; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; - -import java.io.File; -import java.lang.ref.SoftReference; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Main entry point of the LayoutLib Bridge. - * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call - * {@link #createScene(SceneParams)} - */ -public final class Bridge extends com.android.ide.common.rendering.api.Bridge { - - public static class StaticMethodNotImplementedException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public StaticMethodNotImplementedException(String msg) { - super(msg); - } - } - - /** - * Lock to ensure only one rendering/inflating happens at a time. - * This is due to some singleton in the Android framework. - */ - private final static ReentrantLock sLock = new ReentrantLock(); - - /** - * Maps from id to resource type/name. This is for com.android.internal.R - */ - private final static Map<Integer, Pair<ResourceType, String>> sRMap = - new HashMap<Integer, Pair<ResourceType, String>>(); - - /** - * Same as sRMap except for int[] instead of int resources. This is for android.R only. - */ - private final static Map<IntArray, String> sRArrayMap = new HashMap<IntArray, String>(); - /** - * Reverse map compared to sRMap, resource type -> (resource name -> id). - * This is for com.android.internal.R. - */ - private final static Map<ResourceType, Map<String, Integer>> sRevRMap = - new EnumMap<ResourceType, Map<String,Integer>>(ResourceType.class); - - // framework resources are defined as 0x01XX#### where XX is the resource type (layout, - // drawable, etc...). Using FF as the type allows for 255 resource types before we get a - // collision which should be fine. - private final static int DYNAMIC_ID_SEED_START = 0x01ff0000; - private final static DynamicIdMap sDynamicIds = new DynamicIdMap(DYNAMIC_ID_SEED_START); - - 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<NinePatchChunk>>> sProject9PatchCache = - new HashMap<Object, Map<String, SoftReference<NinePatchChunk>>>(); - - private final static Map<String, SoftReference<Bitmap>> sFrameworkBitmapCache = - new HashMap<String, SoftReference<Bitmap>>(); - private final static Map<String, SoftReference<NinePatchChunk>> sFramework9PatchCache = - new HashMap<String, SoftReference<NinePatchChunk>>(); - - private static Map<String, Map<String, Integer>> sEnumValueMap; - private static Map<String, String> sPlatformProperties; - - /** - * int[] wrapper to use as keys in maps. - */ - private final static class IntArray { - private int[] mArray; - - private IntArray() { - // do nothing - } - - private IntArray(int[] a) { - mArray = a; - } - - private void set(int[] a) { - mArray = a; - } - - @Override - public int hashCode() { - return Arrays.hashCode(mArray); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - IntArray other = (IntArray) obj; - if (!Arrays.equals(mArray, other.mArray)) return false; - return true; - } - } - - /** Instance of IntArrayWrapper to be reused in {@link #resolveResourceId(int[])}. */ - private final static IntArray sIntArrayWrapper = new IntArray(); - - /** - * A default log than prints to stdout/stderr. - */ - private final static LayoutLog sDefaultLog = new LayoutLog() { - @Override - public void error(String tag, String message, Object data) { - System.err.println(message); - } - - @Override - public void error(String tag, String message, Throwable throwable, Object data) { - System.err.println(message); - } - - @Override - public void warning(String tag, String message, Object data) { - System.out.println(message); - } - }; - - /** - * Current log. - */ - private static LayoutLog sCurrentLog = sDefaultLog; - - private EnumSet<Capability> mCapabilities; - - @Override - public int getApiLevel() { - return com.android.ide.common.rendering.api.Bridge.API_CURRENT; - } - - @Override - public EnumSet<Capability> getCapabilities() { - return mCapabilities; - } - - @Override - public boolean init(Map<String,String> platformProperties, - File fontLocation, - Map<String, Map<String, Integer>> enumValueMap, - LayoutLog log) { - sPlatformProperties = platformProperties; - sEnumValueMap = enumValueMap; - - // don't use EnumSet.allOf(), because the bridge doesn't come with its specific version - // of layoutlib_api. It is provided by the client which could have a more recent version - // with newer, unsupported capabilities. - mCapabilities = EnumSet.of( - Capability.UNBOUND_RENDERING, - Capability.CUSTOM_BACKGROUND_COLOR, - Capability.RENDER, - Capability.LAYOUT_ONLY, - Capability.EMBEDDED_LAYOUT, - Capability.VIEW_MANIPULATION, - Capability.PLAY_ANIMATION, - Capability.ANIMATED_VIEW_MANIPULATION, - Capability.ADAPTER_BINDING, - Capability.EXTENDED_VIEWINFO, - Capability.FIXED_SCALABLE_NINE_PATCH); - - - BridgeAssetManager.initSystem(); - - // 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 - // 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. - // - // Currently layoutlib_create only overrides static native method. - // Static non-natives are not overridden and thus do not get here. - final String debug = System.getenv("DEBUG_LAYOUT"); - if (debug != null && !debug.equals("0") && !debug.equals("false")) { - - OverrideMethod.setDefaultListener(new MethodAdapter() { - @Override - public void onInvokeV(String signature, boolean isNative, Object caller) { - sDefaultLog.error(null, "Missing Stub: " + signature + - (isNative ? " (native)" : ""), null /*data*/); - - if (debug.equalsIgnoreCase("throw")) { - // Throwing this exception doesn't seem that useful. It breaks - // the layout editor yet doesn't display anything meaningful to the - // user. Having the error in the console is just as useful. We'll - // throw it only if the environment variable is "throw" or "THROW". - throw new StaticMethodNotImplementedException(signature); - } - } - }); - } - - // load the fonts. - FontLoader fontLoader = FontLoader.create(fontLocation.getAbsolutePath()); - if (fontLoader != null) { - Typeface_Delegate.init(fontLoader); - } else { - log.error(LayoutLog.TAG_BROKEN, - "Failed create FontLoader in layout lib.", null); - return false; - } - - // now parse com.android.internal.R (and only this one as android.R is a subset of - // the internal version), and put the content in the maps. - try { - Class<?> r = com.android.internal.R.class; - - for (Class<?> inner : r.getDeclaredClasses()) { - String resTypeName = inner.getSimpleName(); - ResourceType resType = ResourceType.getEnum(resTypeName); - if (resType != null) { - Map<String, Integer> fullMap = new HashMap<String, Integer>(); - sRevRMap.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 - int modifiers = f.getModifiers(); - if (Modifier.isStatic(modifiers)) { - Class<?> type = f.getType(); - if (type.isArray() && type.getComponentType() == int.class) { - // if the object is an int[] we put it in sRArrayMap using an IntArray - // wrapper that properly implements equals and hashcode for the array - // objects, as required by the map contract. - sRArrayMap.put(new IntArray((int[]) f.get(null)), f.getName()); - } else if (type == int.class) { - Integer value = (Integer) f.get(null); - sRMap.put(value, Pair.of(resType, f.getName())); - fullMap.put(f.getName(), value); - } else { - assert false; - } - } - } - } - } - } catch (Throwable throwable) { - if (log != null) { - log.error(LayoutLog.TAG_BROKEN, - "Failed to load com.android.internal.R from the layout library jar", - throwable); - } - return false; - } - - return true; - } - - @Override - public boolean dispose() { - BridgeAssetManager.clearSystem(); - - // dispose of the default typeface. - Typeface_Accessor.resetDefaults(); - - return true; - } - - /** - * Starts a layout session by inflating and rendering it. The method returns a - * {@link RenderSession} on which further actions can be taken. - * - * @param params the {@link SessionParams} object with all the information necessary to create - * the scene. - * @return a new {@link RenderSession} object that contains the result of the layout. - * @since 5 - */ - @Override - public RenderSession createSession(SessionParams params) { - try { - Result lastResult = SUCCESS.createResult(); - RenderSessionImpl scene = new RenderSessionImpl(params); - try { - prepareThread(); - lastResult = scene.init(params.getTimeout()); - if (lastResult.isSuccess()) { - lastResult = scene.inflate(); - if (lastResult.isSuccess()) { - lastResult = scene.render(true /*freshRender*/); - } - } - } finally { - scene.release(); - cleanupThread(); - } - - return new BridgeRenderSession(scene, lastResult); - } catch (Throwable t) { - // get the real cause of the exception. - Throwable t2 = t; - while (t2.getCause() != null) { - t2 = t.getCause(); - } - return new BridgeRenderSession(null, - ERROR_UNKNOWN.createResult(t2.getMessage(), t)); - } - } - - @Override - public Result renderDrawable(DrawableParams params) { - try { - Result lastResult = SUCCESS.createResult(); - RenderDrawable action = new RenderDrawable(params); - try { - prepareThread(); - lastResult = action.init(params.getTimeout()); - if (lastResult.isSuccess()) { - lastResult = action.render(); - } - } finally { - action.release(); - cleanupThread(); - } - - return lastResult; - } catch (Throwable t) { - // get the real cause of the exception. - Throwable t2 = t; - while (t2.getCause() != null) { - t2 = t.getCause(); - } - return ERROR_UNKNOWN.createResult(t2.getMessage(), t); - } - } - - @Override - public void clearCaches(Object projectKey) { - if (projectKey != null) { - sProjectBitmapCache.remove(projectKey); - sProject9PatchCache.remove(projectKey); - } - } - - @Override - public Result getViewParent(Object viewObject) { - if (viewObject instanceof View) { - return Status.SUCCESS.createResult(((View)viewObject).getParent()); - } - - throw new IllegalArgumentException("viewObject is not a View"); - } - - @Override - public Result getViewIndex(Object viewObject) { - if (viewObject instanceof View) { - View view = (View) viewObject; - ViewParent parentView = view.getParent(); - - if (parentView instanceof ViewGroup) { - Status.SUCCESS.createResult(((ViewGroup) parentView).indexOfChild(view)); - } - - return Status.SUCCESS.createResult(); - } - - throw new IllegalArgumentException("viewObject is not a View"); - } - - /** - * Returns the lock for the bridge - */ - public static ReentrantLock getLock() { - return sLock; - } - - /** - * Prepares the current thread for rendering. - * - * Note that while this can be called several time, the first call to {@link #cleanupThread()} - * will do the clean-up, and make the thread unable to do further scene actions. - */ - public static void prepareThread() { - // 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.prepareMainLooper(); - } - } - - /** - * Cleans up thread-specific data. After this, the thread cannot be used for scene actions. - * <p> - * Note that it doesn't matter how many times {@link #prepareThread()} was called, a single - * call to this will prevent the thread from doing further scene actions - */ - public static void cleanupThread() { - // clean up the looper - Looper_Accessor.cleanupThread(); - } - - public static LayoutLog getLog() { - return sCurrentLog; - } - - public static void setLog(LayoutLog log) { - // check only the thread currently owning the lock can do this. - if (sLock.isHeldByCurrentThread() == false) { - throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); - } - - if (log != null) { - sCurrentLog = log; - } else { - sCurrentLog = sDefaultLog; - } - } - - /** - * Returns details of a framework resource from its integer value. - * @param value the integer value - * @return a Pair containing the resource type and name, or null if the id - * does not match any resource. - */ - public static Pair<ResourceType, String> resolveResourceId(int value) { - Pair<ResourceType, String> pair = sRMap.get(value); - if (pair == null) { - pair = sDynamicIds.resolveId(value); - if (pair == null) { - //System.out.println(String.format("Missing id: %1$08X (%1$d)", value)); - } - } - return pair; - } - - /** - * Returns the name of a framework resource whose value is an int array. - * @param array - */ - public static String resolveResourceId(int[] array) { - sIntArrayWrapper.set(array); - return sRArrayMap.get(sIntArrayWrapper); - } - - /** - * Returns the integer id of a framework resource, from a given resource type and resource name. - * @param type the type of the resource - * @param name the name of the resource. - * @return an {@link Integer} containing the resource id, or null if no resource were found. - */ - public static Integer getResourceId(ResourceType type, String name) { - Map<String, Integer> map = sRevRMap.get(type); - Integer value = null; - if (map != null) { - value = map.get(name); - } - - if (value == null) { - value = sDynamicIds.getId(type, name); - } - - return value; - } - - /** - * Returns the list of possible enums for a given attribute name. - */ - public static Map<String, Integer> getEnumValues(String attributeName) { - if (sEnumValueMap != null) { - return sEnumValueMap.get(attributeName); - } - - return null; - } - - /** - * Returns the platform build properties. - */ - public static Map<String, String> getPlatformProperties() { - return sPlatformProperties; - } - - /** - * Returns the bitmap for a specific path, from a specific project cache, or from the - * framework cache. - * @param value the path of the bitmap - * @param projectKey the key of the project, or null to query the framework cache. - * @return the cached Bitmap or null if not found. - */ - public static Bitmap getCachedBitmap(String value, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey); - if (map != null) { - SoftReference<Bitmap> ref = map.get(value); - if (ref != null) { - return ref.get(); - } - } - } else { - SoftReference<Bitmap> ref = sFrameworkBitmapCache.get(value); - if (ref != null) { - return ref.get(); - } - } - - return null; - } - - /** - * Sets a bitmap in a project cache or in the framework cache. - * @param value the path of the bitmap - * @param bmp the Bitmap object - * @param projectKey the key of the project, or null to put the bitmap in the framework cache. - */ - public static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey); - - if (map == null) { - 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)); - } - } - - /** - * Returns the 9 patch chunk for a specific path, from a specific project cache, or from the - * framework cache. - * @param value the path of the 9 patch - * @param projectKey the key of the project, or null to query the framework cache. - * @return the cached 9 patch or null if not found. - */ - public static NinePatchChunk getCached9Patch(String value, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); - - if (map != null) { - SoftReference<NinePatchChunk> ref = map.get(value); - if (ref != null) { - return ref.get(); - } - } - } else { - SoftReference<NinePatchChunk> ref = sFramework9PatchCache.get(value); - if (ref != null) { - return ref.get(); - } - } - - return null; - } - - /** - * Sets a 9 patch chunk in a project cache or in the framework cache. - * @param value the path of the 9 patch - * @param ninePatch the 9 patch object - * @param projectKey the key of the project, or null to put the bitmap in the framework cache. - */ - public static void setCached9Patch(String value, NinePatchChunk ninePatch, Object projectKey) { - if (projectKey != null) { - Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); - - if (map == null) { - map = new HashMap<String, SoftReference<NinePatchChunk>>(); - sProject9PatchCache.put(projectKey, map); - } - - map.put(value, new SoftReference<NinePatchChunk>(ninePatch)); - } else { - sFramework9PatchCache.put(value, new SoftReference<NinePatchChunk>(ninePatch)); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java deleted file mode 100644 index eb9e7f1..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge; - -/** - * Constant definition class.<br> - * <br> - * Most constants have a prefix defining the content. - * <ul> - * <li><code>WS_</code> Workspace path constant. Those are absolute paths, - * from the project root.</li> - * <li><code>OS_</code> OS path constant. These paths are different depending on the platform.</li> - * <li><code>FN_</code> File name constant.</li> - * <li><code>FD_</code> Folder name constant.</li> - * <li><code>EXT_</code> File extension constant. This does NOT include a dot.</li> - * <li><code>DOT_</code> File extension constant. This start with a dot.</li> - * <li><code>RE_</code> Regexp constant.</li> - * <li><code>NS_</code> Namespace constant.</li> - * <li><code>CLASS_</code> Fully qualified class name.</li> - * </ul> - * - */ -public class BridgeConstants { - - /** Namespace for the resource XML */ - public final static String NS_RESOURCES = "http://schemas.android.com/apk/res/android"; - - /** App auto namespace */ - public final static String NS_APP_RES_AUTO = "http://schemas.android.com/apk/res-auto"; - - public final static String R = "com.android.internal.R"; - - - public final static String MATCH_PARENT = "match_parent"; - public final static String FILL_PARENT = "fill_parent"; - public final static String WRAP_CONTENT = "wrap_content"; -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java deleted file mode 100644 index f9f4b3a..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge; - -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.RenderParams; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; - -import android.view.View; -import android.view.ViewGroup; - -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.Map; - -/** - * An implementation of {@link RenderSession}. - * - * This is a pretty basic class that does almost nothing. All of the work is done in - * {@link RenderSessionImpl}. - * - */ -public class BridgeRenderSession extends RenderSession { - - private final RenderSessionImpl mSession; - private Result mLastResult; - - @Override - public Result getResult() { - return mLastResult; - } - - @Override - public BufferedImage getImage() { - return mSession.getImage(); - } - - @Override - public boolean isAlphaChannelImage() { - return mSession.isAlphaChannelImage(); - } - - @Override - public List<ViewInfo> getRootViews() { - return mSession.getViewInfos(); - } - - @Override - public Map<String, String> getDefaultProperties(Object viewObject) { - return mSession.getDefaultProperties(viewObject); - } - - @Override - public Result getProperty(Object objectView, String propertyName) { - // pass - return super.getProperty(objectView, propertyName); - } - - @Override - public Result setProperty(Object objectView, String propertyName, String propertyValue) { - // pass - return super.setProperty(objectView, propertyName, propertyValue); - } - - @Override - public Result render(long timeout) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(timeout); - if (mLastResult.isSuccess()) { - mLastResult = mSession.render(false /*freshRender*/); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - - return mLastResult; - } - - @Override - public Result animate(Object targetObject, String animationName, - boolean isFrameworkAnimation, IAnimationListener listener) { - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation, - listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - - return mLastResult; - } - - @Override - public Result insertChild(Object parentView, ILayoutPullParser childXml, int index, - IAnimationListener listener) { - if (parentView instanceof ViewGroup == false) { - throw new IllegalArgumentException("parentView is not a ViewGroup"); - } - - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.insertChild((ViewGroup) parentView, childXml, index, - listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - - return mLastResult; - } - - - @Override - public Result moveChild(Object parentView, Object childView, int index, - Map<String, String> layoutParams, IAnimationListener listener) { - if (parentView instanceof ViewGroup == false) { - throw new IllegalArgumentException("parentView is not a ViewGroup"); - } - if (childView instanceof View == false) { - throw new IllegalArgumentException("childView is not a View"); - } - - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index, - layoutParams, listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - - return mLastResult; - } - - @Override - public Result removeChild(Object childView, IAnimationListener listener) { - if (childView instanceof View == false) { - throw new IllegalArgumentException("childView is not a View"); - } - - try { - Bridge.prepareThread(); - mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT); - if (mLastResult.isSuccess()) { - mLastResult = mSession.removeChild((View) childView, listener); - } - } finally { - mSession.release(); - Bridge.cleanupThread(); - } - - return mLastResult; - } - - @Override - public void dispose() { - } - - /*package*/ BridgeRenderSession(RenderSessionImpl scene, Result lastResult) { - mSession = scene; - if (scene != null) { - mSession.setScene(this); - } - mLastResult = lastResult; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java deleted file mode 100644 index 3d50b2a..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge; - -import android.content.Context; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.view.Gravity; -import android.widget.TextView; - -/** - * Base class for mocked views. - * - * TODO: implement onDraw and draw a rectangle in a random color with the name of the class - * (or better the id of the view). - */ -public class MockView extends TextView { - - public MockView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - setText(this.getClass().getSimpleName()); - setTextColor(0xFF000000); - setGravity(Gravity.CENTER); - } - - @Override - public void onDraw(Canvas canvas) { - canvas.drawARGB(0xFF, 0x7F, 0x7F, 0x7F); - - super.onDraw(canvas); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java deleted file mode 100644 index 688cc87..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentValues; -import android.content.IContentProvider; -import android.content.OperationApplicationException; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ICancellationSignal; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; - -import java.io.FileNotFoundException; -import java.util.ArrayList; - -/** - * Mock implementation of {@link IContentProvider}. - * - * TODO: never return null when the method is not supposed to. Return fake data instead. - */ -public final class BridgeContentProvider implements IContentProvider { - @Override - public ContentProviderResult[] applyBatch(String callingPackage, - ArrayList<ContentProviderOperation> arg0) - throws RemoteException, OperationApplicationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int bulkInsert(String callingPackage, Uri arg0, ContentValues[] arg1) - throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public Bundle call(String callingPackage, String arg0, String arg1, Bundle arg2) - throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int delete(String callingPackage, Uri arg0, String arg1, String[] arg2) - throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getType(Uri arg0) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Uri insert(String callingPackage, Uri arg0, ContentValues arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public AssetFileDescriptor openAssetFile( - String callingPackage, Uri arg0, String arg1, ICancellationSignal signal) - throws RemoteException, FileNotFoundException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ParcelFileDescriptor openFile( - String callingPackage, Uri arg0, String arg1, ICancellationSignal signal) - throws RemoteException, FileNotFoundException { - // TODO Auto-generated method stub - return null; - } - - @Override - public Cursor query(String callingPackage, Uri arg0, String[] arg1, String arg2, String[] arg3, - String arg4, ICancellationSignal arg5) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int update(String callingPackage, Uri arg0, ContentValues arg1, String arg2, - String[] arg3) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri arg0, String arg1, - Bundle arg2, ICancellationSignal signal) throws RemoteException, FileNotFoundException { - // TODO Auto-generated method stub - return null; - } - - @Override - public ICancellationSignal createCancellationSignal() throws RemoteException { - // TODO Auto-generated method stub - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java deleted file mode 100644 index 8d259d7..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.IContentProvider; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Bundle; - -/** - * A mock content resolver for the LayoutLib Bridge. - * <p/> - * It won't serve any actual data but it's good enough for all - * the widgets which expect to have a content resolver available via - * {@link BridgeContext#getContentResolver()}. - */ -public class BridgeContentResolver extends ContentResolver { - - private BridgeContentProvider mProvider = null; - - public BridgeContentResolver(Context context) { - super(context); - } - - @Override - public IContentProvider acquireProvider(Context c, String name) { - if (mProvider == null) { - mProvider = new BridgeContentProvider(); - } - - return mProvider; - } - - @Override - public IContentProvider acquireExistingProvider(Context c, String name) { - if (mProvider == null) { - mProvider = new BridgeContentProvider(); - } - - return mProvider; - } - - @Override - public boolean releaseProvider(IContentProvider icp) { - // ignore - return false; - } - - @Override - protected IContentProvider acquireUnstableProvider(Context c, String name) { - return acquireProvider(c, name); - } - - @Override - public boolean releaseUnstableProvider(IContentProvider icp) { - return releaseProvider(icp); - } - - /** @hide */ - @Override - public void unstableProviderDied(IContentProvider icp) { - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void registerContentObserver(Uri uri, boolean notifyForDescendents, - ContentObserver observer) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void unregisterContentObserver(ContentObserver observer) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void startSync(Uri uri, Bundle extras) { - // pass - } - - /** - * Stub for the layoutlib bridge content resolver. - */ - @Override - public void cancelSync(Uri uri) { - // pass - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java deleted file mode 100644 index d63dcac..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ /dev/null @@ -1,1427 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; -import com.android.layoutlib.bridge.android.view.WindowManagerImpl; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.Stack; -import com.android.resources.ResourceType; -import com.android.util.Pair; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.IntentSender; -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.BridgeResources; -import android.content.res.BridgeTypedArray; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.Resources.Theme; -import android.content.res.TypedArray; -import android.database.DatabaseErrorHandler; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.PowerManager; -import android.os.UserHandle; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.BridgeInflater; -import android.view.Display; -import android.view.DisplayAdjustments; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.view.textservice.TextServicesManager; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; - -/** - * Custom implementation of Context/Activity to handle non compiled resources. - */ -public final class BridgeContext extends Context { - - private Resources mSystemResources; - private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>(); - private final Object mProjectKey; - private final DisplayMetrics mMetrics; - private final RenderResources mRenderResources; - private final Configuration mConfig; - private final ApplicationInfo mApplicationInfo; - private final IProjectCallback mProjectCallback; - private final WindowManager mWindowManager; - - private Resources.Theme mTheme; - - private final Map<Object, Map<String, String>> mDefaultPropMaps = - new IdentityHashMap<Object, Map<String,String>>(); - - // maps for dynamically generated id representing style objects (StyleResourceValue) - private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; - private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; - private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style - - // cache for TypedArray generated from IStyleResourceValue object - private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache; - private BridgeInflater mBridgeInflater; - - private BridgeContentResolver mContentResolver; - - private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); - - /** - * @param projectKey An Object identifying the project. This is used for the cache mechanism. - * @param metrics the {@link DisplayMetrics}. - * @param renderResources the configured resources (both framework and projects) for this - * render. - * @param projectCallback - * @param config the Configuration object for this render. - * @param targetSdkVersion the targetSdkVersion of the application. - */ - public BridgeContext(Object projectKey, DisplayMetrics metrics, - RenderResources renderResources, - IProjectCallback projectCallback, - Configuration config, - int targetSdkVersion) { - mProjectKey = projectKey; - mMetrics = metrics; - mProjectCallback = projectCallback; - - mRenderResources = renderResources; - mConfig = config; - - mApplicationInfo = new ApplicationInfo(); - mApplicationInfo.targetSdkVersion = targetSdkVersion; - - mWindowManager = new WindowManagerImpl(mMetrics); - } - - /** - * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its - * {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}. - * - * @see #disposeResources() - */ - public void initResources() { - AssetManager assetManager = AssetManager.getSystem(); - - mSystemResources = BridgeResources.initSystem( - this, - assetManager, - mMetrics, - mConfig, - mProjectCallback); - mTheme = mSystemResources.newTheme(); - } - - /** - * Disposes the {@link Resources} singleton. - */ - public void disposeResources() { - BridgeResources.disposeSystem(); - } - - public void setBridgeInflater(BridgeInflater inflater) { - mBridgeInflater = inflater; - } - - public void addViewKey(View view, Object viewKey) { - mViewKeyMap.put(view, viewKey); - } - - public Object getViewKey(View view) { - return mViewKeyMap.get(view); - } - - public Object getProjectKey() { - return mProjectKey; - } - - public DisplayMetrics getMetrics() { - return mMetrics; - } - - public IProjectCallback getProjectCallback() { - return mProjectCallback; - } - - public RenderResources getRenderResources() { - return mRenderResources; - } - - public Map<String, String> getDefaultPropMap(Object key) { - return mDefaultPropMaps.get(key); - } - - public Configuration getConfiguration() { - return mConfig; - } - - /** - * Adds a parser to the stack. - * @param parser the parser to add. - */ - public void pushParser(BridgeXmlBlockParser parser) { - if (ParserFactory.LOG_PARSER) { - System.out.println("PUSH " + parser.getParser().toString()); - } - mParserStack.push(parser); - } - - /** - * Removes the parser at the top of the stack - */ - public void popParser() { - BridgeXmlBlockParser parser = mParserStack.pop(); - if (ParserFactory.LOG_PARSER) { - System.out.println("POPD " + parser.getParser().toString()); - } - } - - /** - * Returns the current parser at the top the of the stack. - * @return a parser or null. - */ - public BridgeXmlBlockParser getCurrentParser() { - return mParserStack.peek(); - } - - /** - * Returns the previous parser. - * @return a parser or null if there isn't any previous parser - */ - public BridgeXmlBlockParser getPreviousParser() { - if (mParserStack.size() < 2) { - return null; - } - return mParserStack.get(mParserStack.size() - 2); - } - - public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) { - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid); - boolean isFrameworkRes = true; - if (resourceInfo == null) { - resourceInfo = mProjectCallback.resolveResourceId(resid); - isFrameworkRes = false; - } - - if (resourceInfo == null) { - return false; - } - - ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(), - isFrameworkRes); - if (resolveRefs) { - value = mRenderResources.resolveResValue(value); - } - - // check if this is a style resource - if (value instanceof StyleResourceValue) { - // get the id that will represent this style. - outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value); - return true; - } - - - int a; - // if this is a framework value. - if (value.isFramework()) { - // look for idName in the android R classes. - // use 0 a default res value as it's not a valid id value. - a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); - } else { - // look for idName in the project R class. - // use 0 a default res value as it's not a valid id value. - a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/); - } - - if (a != 0) { - outValue.resourceId = a; - return true; - } - - return false; - } - - - public ResourceReference resolveId(int id) { - // first get the String related to this id in the framework - Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); - - if (resourceInfo != null) { - return new ResourceReference(resourceInfo.getSecond(), true); - } - - // didn't find a match in the framework? look in the project. - if (mProjectCallback != null) { - resourceInfo = mProjectCallback.resolveResourceId(id); - - if (resourceInfo != null) { - return new ResourceReference(resourceInfo.getSecond(), false); - } - } - - return null; - } - - public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent, - boolean attachToRoot, boolean skipCallbackParser) { - boolean isPlatformLayout = resource.isFramework(); - - if (isPlatformLayout == false && skipCallbackParser == false) { - // check if the project callback can provide us with a custom parser. - ILayoutPullParser parser = getParser(resource); - - if (parser != null) { - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, - this, resource.isFramework()); - try { - pushParser(blockParser); - return Pair.of( - mBridgeInflater.inflate(blockParser, parent, attachToRoot), - true); - } finally { - popParser(); - } - } - } - - ResourceValue resValue; - if (resource instanceof ResourceValue) { - resValue = (ResourceValue) resource; - } else { - if (isPlatformLayout) { - resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT, - resource.getName()); - } else { - resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT, - resource.getName()); - } - } - - if (resValue != null) { - - File xml = new File(resValue.getValue()); - if (xml.isFile()) { - // we need to create a pull parser around the layout XML file, and then - // give that to our XmlBlockParser - try { - XmlPullParser parser = ParserFactory.create(xml); - - // set the resource ref to have correct view cookies - mBridgeInflater.setResourceReference(resource); - - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser, - this, resource.isFramework()); - try { - pushParser(blockParser); - return Pair.of( - mBridgeInflater.inflate(blockParser, parent, attachToRoot), - false); - } finally { - popParser(); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + xml, e, null /*data*/); - // we'll return null below. - } catch (FileNotFoundException e) { - // this shouldn't happen since we check above. - } finally { - mBridgeInflater.setResourceReference(null); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("File %s is missing!", xml), null); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "", - resource.getName()), null); - } - - return Pair.of(null, false); - } - - @SuppressWarnings("deprecation") - private ILayoutPullParser getParser(ResourceReference resource) { - ILayoutPullParser parser; - if (resource instanceof ResourceValue) { - parser = mProjectCallback.getParser((ResourceValue) resource); - } else { - parser = mProjectCallback.getParser(resource.getName()); - } - return parser; - } - - // ------------ Context methods - - @Override - public Resources getResources() { - return mSystemResources; - } - - @Override - public Theme getTheme() { - return mTheme; - } - - @Override - public ClassLoader getClassLoader() { - return this.getClass().getClassLoader(); - } - - @Override - public Object getSystemService(String service) { - if (LAYOUT_INFLATER_SERVICE.equals(service)) { - return mBridgeInflater; - } - - if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) { - // we need to return a valid service to avoid NPE - return TextServicesManager.getInstance(); - } - - if (WINDOW_SERVICE.equals(service)) { - return mWindowManager; - } - - // needed by SearchView - if (INPUT_METHOD_SERVICE.equals(service)) { - return null; - } - - if (POWER_SERVICE.equals(service)) { - return new PowerManager(this, new BridgePowerManager(), new Handler()); - } - - throw new UnsupportedOperationException("Unsupported Service: " + service); - } - - - @Override - public final TypedArray obtainStyledAttributes(int[] attrs) { - return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs); - } - - @Override - public final TypedArray obtainStyledAttributes(int resid, int[] attrs) - throws Resources.NotFoundException { - // get the StyleResourceValue based on the resId; - StyleResourceValue style = getStyleByDynamicId(resid); - - if (style == null) { - throw new Resources.NotFoundException(); - } - - if (mTypedArrayCache == null) { - mTypedArrayCache = new HashMap<int[], Map<Integer,TypedArray>>(); - - Map<Integer, TypedArray> map = new HashMap<Integer, TypedArray>(); - mTypedArrayCache.put(attrs, map); - - BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs); - map.put(resid, ta); - - return ta; - } - - // get the 2nd map - Map<Integer, TypedArray> map = mTypedArrayCache.get(attrs); - if (map == null) { - map = new HashMap<Integer, TypedArray>(); - mTypedArrayCache.put(attrs, map); - } - - // get the array from the 2nd map - TypedArray ta = map.get(resid); - - if (ta == null) { - ta = createStyleBasedTypedArray(style, attrs); - map.put(resid, ta); - } - - return ta; - } - - @Override - public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { - return obtainStyledAttributes(set, attrs, 0, 0); - } - - @Override - public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, - int defStyleAttr, int defStyleRes) { - - Map<String, String> defaultPropMap = null; - boolean isPlatformFile = true; - - // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java - if (set instanceof BridgeXmlBlockParser) { - BridgeXmlBlockParser parser = null; - parser = (BridgeXmlBlockParser)set; - - isPlatformFile = parser.isPlatformFile(); - - Object key = parser.getViewCookie(); - if (key != null) { - defaultPropMap = mDefaultPropMaps.get(key); - if (defaultPropMap == null) { - defaultPropMap = new HashMap<String, String>(); - mDefaultPropMaps.put(key, defaultPropMap); - } - } - - } else if (set instanceof BridgeLayoutParamsMapAttributes) { - // this is only for temp layout params generated dynamically, so this is never - // platform content. - isPlatformFile = false; - } else if (set != null) { // null parser is ok - // really this should not be happening since its instantiated in Bridge - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Parser is not a BridgeXmlBlockParser!", null /*data*/); - return null; - } - - List<Pair<String, Boolean>> attributeList = searchAttrs(attrs); - - BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, - isPlatformFile); - - // look for a custom style. - String customStyle = null; - if (set != null) { - customStyle = set.getAttributeValue(null /* namespace*/, "style"); - } - - StyleResourceValue customStyleValues = null; - if (customStyle != null) { - ResourceValue item = mRenderResources.findResValue(customStyle, - false /*forceFrameworkOnly*/); - - // resolve it in case it links to something else - item = mRenderResources.resolveResValue(item); - - if (item instanceof StyleResourceValue) { - customStyleValues = (StyleResourceValue)item; - } - } - - // resolve the defStyleAttr value into a IStyleResourceValue - StyleResourceValue defStyleValues = null; - - if (defStyleAttr != 0) { - // get the name from the int. - Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr); - - if (defaultPropMap != null) { - String defStyleName = defStyleAttribute.getFirst(); - if (defStyleAttribute.getSecond()) { - defStyleName = "android:" + defStyleName; - } - defaultPropMap.put("style", defStyleName); - } - - // look for the style in the current theme, and its parent: - ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(), - defStyleAttribute.getSecond()); - - if (item != null) { - // item is a reference to a style entry. Search for it. - item = mRenderResources.findResValue(item.getValue(), - false /*forceFrameworkOnly*/); - - if (item instanceof StyleResourceValue) { - defStyleValues = (StyleResourceValue)item; - } - } else { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, - String.format( - "Failed to find style '%s' in current theme", - defStyleAttribute.getFirst()), - null /*data*/); - } - } else if (defStyleRes != 0) { - boolean isFrameworkRes = true; - Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes); - if (value == null) { - value = mProjectCallback.resolveResourceId(defStyleRes); - isFrameworkRes = false; - } - - if (value != null) { - if (value.getFirst() == ResourceType.STYLE) { - // look for the style in the current theme, and its parent: - ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(), - isFrameworkRes); - if (item != null) { - if (item instanceof StyleResourceValue) { - if (defaultPropMap != null) { - defaultPropMap.put("style", item.getName()); - } - - defStyleValues = (StyleResourceValue)item; - } - } else { - Bridge.getLog().error(null, - String.format( - "Style with id 0x%x (resolved to '%s') does not exist.", - defStyleRes, value.getSecond()), - null /*data*/); - } - } else { - Bridge.getLog().error(null, - String.format( - "Resouce id 0x%x is not of type STYLE (instead %s)", - defStyleRes, value.getFirst().toString()), - null /*data*/); - } - } else { - Bridge.getLog().error(null, - String.format( - "Failed to find style with id 0x%x in current theme", - defStyleRes), - null /*data*/); - } - } - - String appNamespace = mProjectCallback.getNamespace(); - - if (attributeList != null) { - for (int index = 0 ; index < attributeList.size() ; index++) { - Pair<String, Boolean> attribute = attributeList.get(index); - - if (attribute == null) { - continue; - } - - String attrName = attribute.getFirst(); - boolean frameworkAttr = attribute.getSecond().booleanValue(); - String value = null; - if (set != null) { - value = set.getAttributeValue( - frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, - attrName); - - // if this is an app attribute, and the first get fails, try with the - // new res-auto namespace as well - if (frameworkAttr == false && value == null) { - value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName); - } - } - - // if there's no direct value for this attribute in the XML, we look for default - // values in the widget defStyle, and then in the theme. - if (value == null) { - ResourceValue resValue = null; - - // look for the value in the custom style first (and its parent if needed) - if (customStyleValues != null) { - resValue = mRenderResources.findItemInStyle(customStyleValues, - attrName, frameworkAttr); - } - - // then look for the value in the default Style (and its parent if needed) - if (resValue == null && defStyleValues != null) { - resValue = mRenderResources.findItemInStyle(defStyleValues, - attrName, frameworkAttr); - } - - // if the item is not present in the defStyle, we look in the main theme (and - // its parent themes) - if (resValue == null) { - resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); - } - - // if we found a value, we make sure this doesn't reference another value. - // So we resolve it. - if (resValue != null) { - // put the first default value, before the resolution. - if (defaultPropMap != null) { - defaultPropMap.put(attrName, resValue.getValue()); - } - - resValue = mRenderResources.resolveResValue(resValue); - } - - ta.bridgeSetValue(index, attrName, frameworkAttr, resValue); - } else { - // there is a value in the XML, but we need to resolve it in case it's - // referencing another resource or a theme value. - ta.bridgeSetValue(index, attrName, frameworkAttr, - mRenderResources.resolveValue(null, attrName, value, isPlatformFile)); - } - } - } - - ta.sealArray(); - - return ta; - } - - @Override - public Looper getMainLooper() { - return Looper.myLooper(); - } - - - // ------------- private new methods - - /** - * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the - * values found in the given style. - * @see #obtainStyledAttributes(int, int[]) - */ - private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs) - throws Resources.NotFoundException { - - List<Pair<String, Boolean>> attributes = searchAttrs(attrs); - - BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, - false); - - // for each attribute, get its name so that we can search it in the style - for (int i = 0 ; i < attrs.length ; i++) { - Pair<String, Boolean> attribute = attributes.get(i); - - if (attribute != null) { - // look for the value in the given style - ResourceValue resValue = mRenderResources.findItemInStyle(style, - attribute.getFirst(), attribute.getSecond()); - - if (resValue != null) { - // resolve it to make sure there are no references left. - ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(), - mRenderResources.resolveResValue(resValue)); - } - } - } - - ta.sealArray(); - - return ta; - } - - - /** - * The input int[] attrs is a list of attributes. The returns a list of information about - * each attributes. The information is (name, isFramework) - * <p/> - * - * @param attrs An attribute array reference given to obtainStyledAttributes. - * @return List of attribute information. - */ - private List<Pair<String, Boolean>> searchAttrs(int[] attrs) { - List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length); - - // for each attribute, get its name so that we can search it in the style - for (int i = 0 ; i < attrs.length ; i++) { - Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]); - boolean isFramework = false; - if (resolvedResource != null) { - isFramework = true; - } else { - resolvedResource = mProjectCallback.resolveResourceId(attrs[i]); - } - - if (resolvedResource != null) { - results.add(Pair.of(resolvedResource.getSecond(), isFramework)); - } else { - results.add(null); - } - } - - return results; - } - - /** - * Searches for the attribute referenced by its internal id. - * - * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. - * @return A (name, isFramework) pair describing the attribute if found. Returns null - * if nothing is found. - */ - public Pair<String, Boolean> searchAttr(int attr) { - Pair<ResourceType, String> info = Bridge.resolveResourceId(attr); - if (info != null) { - return Pair.of(info.getSecond(), Boolean.TRUE); - } - - info = mProjectCallback.resolveResourceId(attr); - if (info != null) { - return Pair.of(info.getSecond(), Boolean.FALSE); - } - - return null; - } - - public int getDynamicIdByStyle(StyleResourceValue resValue) { - if (mDynamicIdToStyleMap == null) { - // create the maps. - mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>(); - mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>(); - } - - // look for an existing id - Integer id = mStyleToDynamicIdMap.get(resValue); - - if (id == null) { - // generate a new id - id = Integer.valueOf(++mDynamicIdGenerator); - - // and add it to the maps. - mDynamicIdToStyleMap.put(id, resValue); - mStyleToDynamicIdMap.put(resValue, id); - } - - return id; - } - - private StyleResourceValue getStyleByDynamicId(int i) { - if (mDynamicIdToStyleMap != null) { - return mDynamicIdToStyleMap.get(i); - } - - return null; - } - - public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) { - Integer value = Bridge.getResourceId(resType, resName); - if (value != null) { - return value.intValue(); - } - - return defValue; - } - - public int getProjectResourceValue(ResourceType resType, String resName, int defValue) { - if (mProjectCallback != null) { - Integer value = mProjectCallback.getResourceId(resType, resName); - if (value != null) { - return value.intValue(); - } - } - - return defValue; - } - - //------------ NOT OVERRIDEN -------------------- - - @Override - public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) { - // pass - return false; - } - - @Override - public int checkCallingOrSelfPermission(String arg0) { - // pass - return 0; - } - - @Override - public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) { - // pass - return 0; - } - - @Override - public int checkCallingPermission(String arg0) { - // pass - return 0; - } - - @Override - public int checkCallingUriPermission(Uri arg0, int arg1) { - // pass - return 0; - } - - @Override - public int checkPermission(String arg0, int arg1, int arg2) { - // pass - return 0; - } - - @Override - public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) { - // pass - return 0; - } - - @Override - public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3, - int arg4, int arg5) { - // pass - return 0; - } - - @Override - public void clearWallpaper() { - // pass - - } - - @Override - public Context createPackageContext(String arg0, int arg1) { - // pass - return null; - } - - @Override - public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) { - // pass - return null; - } - - @Override - public Context createConfigurationContext(Configuration overrideConfiguration) { - // pass - return null; - } - - @Override - public Context createDisplayContext(Display display) { - // pass - return null; - } - - @Override - public String[] databaseList() { - // pass - return null; - } - - @Override - public boolean deleteDatabase(String arg0) { - // pass - return false; - } - - @Override - public boolean deleteFile(String arg0) { - // pass - return false; - } - - @Override - public void enforceCallingOrSelfPermission(String arg0, String arg1) { - // pass - - } - - @Override - public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, - String arg2) { - // pass - - } - - @Override - public void enforceCallingPermission(String arg0, String arg1) { - // pass - - } - - @Override - public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { - // pass - - } - - @Override - public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { - // pass - - } - - @Override - public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, - String arg4) { - // pass - - } - - @Override - public void enforceUriPermission(Uri arg0, String arg1, String arg2, - int arg3, int arg4, int arg5, String arg6) { - // pass - - } - - @Override - public String[] fileList() { - // pass - return null; - } - - @Override - public AssetManager getAssets() { - // pass - return null; - } - - @Override - public File getCacheDir() { - // pass - return null; - } - - @Override - public File getExternalCacheDir() { - // pass - return null; - } - - @Override - public ContentResolver getContentResolver() { - if (mContentResolver == null) { - mContentResolver = new BridgeContentResolver(this); - } - return mContentResolver; - } - - @Override - public File getDatabasePath(String arg0) { - // pass - return null; - } - - @Override - public File getDir(String arg0, int arg1) { - // pass - return null; - } - - @Override - public File getFileStreamPath(String arg0) { - // pass - return null; - } - - @Override - public File getFilesDir() { - // pass - return null; - } - - @Override - public File getExternalFilesDir(String type) { - // pass - return null; - } - - @Override - public String getPackageCodePath() { - // pass - return null; - } - - @Override - public PackageManager getPackageManager() { - // pass - return null; - } - - @Override - public String getPackageName() { - // pass - return null; - } - - @Override - public String getBasePackageName() { - // pass - return null; - } - - @Override - public ApplicationInfo getApplicationInfo() { - return mApplicationInfo; - } - - @Override - public String getPackageResourcePath() { - // pass - return null; - } - - @Override - public File getSharedPrefsFile(String name) { - // pass - return null; - } - - @Override - public SharedPreferences getSharedPreferences(String arg0, int arg1) { - // pass - return null; - } - - @Override - public Drawable getWallpaper() { - // pass - return null; - } - - @Override - public int getWallpaperDesiredMinimumWidth() { - return -1; - } - - @Override - public int getWallpaperDesiredMinimumHeight() { - return -1; - } - - @Override - public void grantUriPermission(String arg0, Uri arg1, int arg2) { - // pass - - } - - @Override - public FileInputStream openFileInput(String arg0) throws FileNotFoundException { - // pass - return null; - } - - @Override - public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException { - // pass - return null; - } - - @Override - public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) { - // pass - return null; - } - - @Override - public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, - CursorFactory arg2, DatabaseErrorHandler arg3) { - // pass - return null; - } - - @Override - public Drawable peekWallpaper() { - // pass - return null; - } - - @Override - public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) { - // pass - return null; - } - - @Override - public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, - String arg2, Handler arg3) { - // pass - return null; - } - - @Override - public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, - IntentFilter arg1, String arg2, Handler arg3) { - // pass - return null; - } - - @Override - public void removeStickyBroadcast(Intent arg0) { - // pass - - } - - @Override - public void revokeUriPermission(Uri arg0, int arg1) { - // pass - - } - - @Override - public void sendBroadcast(Intent arg0) { - // pass - - } - - @Override - public void sendBroadcast(Intent arg0, String arg1) { - // pass - - } - - @Override - public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { - // pass - } - - @Override - public void sendOrderedBroadcast(Intent arg0, String arg1) { - // pass - - } - - @Override - public void sendOrderedBroadcast(Intent arg0, String arg1, - BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, - Bundle arg6) { - // pass - - } - - @Override - public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, - BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, - String initialData, Bundle initialExtras) { - // pass - } - - @Override - public void sendBroadcastAsUser(Intent intent, UserHandle user) { - // pass - } - - @Override - public void sendBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission) { - // pass - } - - @Override - public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, - String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, - int initialCode, String initialData, Bundle initialExtras) { - // pass - } - - @Override - public void sendStickyBroadcast(Intent arg0) { - // pass - - } - - @Override - public void sendStickyOrderedBroadcast(Intent intent, - BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { - // pass - } - - @Override - public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { - // pass - } - - @Override - public void sendStickyOrderedBroadcastAsUser(Intent intent, - UserHandle user, BroadcastReceiver resultReceiver, - Handler scheduler, int initialCode, String initialData, - Bundle initialExtras) { - // pass - } - - @Override - public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { - // pass - } - - @Override - public void setTheme(int arg0) { - // pass - - } - - @Override - public void setWallpaper(Bitmap arg0) throws IOException { - // pass - - } - - @Override - public void setWallpaper(InputStream arg0) throws IOException { - // pass - - } - - @Override - public void startActivity(Intent arg0) { - // pass - } - - @Override - public void startActivity(Intent arg0, Bundle arg1) { - // pass - } - - @Override - public void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) - throws IntentSender.SendIntentException { - // pass - } - - @Override - public void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, - Bundle options) throws IntentSender.SendIntentException { - // pass - } - - @Override - public boolean startInstrumentation(ComponentName arg0, String arg1, - Bundle arg2) { - // pass - return false; - } - - @Override - public ComponentName startService(Intent arg0) { - // pass - return null; - } - - @Override - public boolean stopService(Intent arg0) { - // pass - return false; - } - - @Override - public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) { - // pass - return null; - } - - @Override - public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) { - // pass - return false; - } - - @Override - public void unbindService(ServiceConnection arg0) { - // pass - - } - - @Override - public void unregisterReceiver(BroadcastReceiver arg0) { - // pass - - } - - @Override - public Context getApplicationContext() { - return this; - } - - @Override - public void startActivities(Intent[] arg0) { - // pass - - } - - @Override - public void startActivities(Intent[] arg0, Bundle arg1) { - // pass - - } - - @Override - public boolean isRestricted() { - return false; - } - - @Override - public File getObbDir() { - Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null); - return null; - } - - @Override - public DisplayAdjustments getDisplayAdjustments(int displayId) { - // pass - return null; - } - - /** - * @hide - */ - @Override - public int getUserId() { - return 0; // not used - } - - @Override - public File[] getExternalFilesDirs(String type) { - // pass - return new File[0]; - } - - @Override - public File[] getObbDirs() { - // pass - return new File[0]; - } - - @Override - public File[] getExternalCacheDirs() { - // pass - return new File[0]; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java deleted file mode 100644 index 3cf5ed5..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodClient; -import com.android.internal.view.IInputMethodManager; -import com.android.internal.view.InputBindResult; - -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.text.style.SuggestionSpan; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodSubtype; - -import java.util.List; - -/** - * Basic implementation of IInputMethodManager that does nothing. - * - */ -public class BridgeIInputMethodManager implements IInputMethodManager { - - @Override - public void addClient(IInputMethodClient arg0, IInputContext arg1, int arg2, int arg3) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void finishInput(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public InputMethodSubtype getCurrentInputMethodSubtype() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<InputMethodInfo> getEnabledInputMethodList() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String arg0, - boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List<InputMethodInfo> getInputMethodList() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public InputMethodSubtype getLastInputMethodSubtype() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List getShortcutInputMethodsAndSubtypes() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void hideMySoftInput(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean hideSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean notifySuggestionPicked(SuggestionSpan arg0, String arg1, int arg2) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void registerSuggestionSpansForNotification(SuggestionSpan[] arg0) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void removeClient(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1) - throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setImeWindowStatus(IBinder arg0, int arg1, int arg2) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setInputMethod(IBinder arg0, String arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void setInputMethodAndSubtype(IBinder arg0, String arg1, InputMethodSubtype arg2) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean setInputMethodEnabled(String arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void showInputMethodAndSubtypeEnablerFromClient(IInputMethodClient arg0, String arg1) - throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void showInputMethodPickerFromClient(IInputMethodClient arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public void showMySoftInput(IBinder arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public boolean showSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2) - throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public InputBindResult startInput(IInputMethodClient client, IInputContext inputContext, - EditorInfo attribute, int controlFlags) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean switchToNextInputMethod(IBinder arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean shouldOfferSwitchingToNextInputMethod(IBinder arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override - public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken, - int controlFlags, int softInputMode, int windowFlags, EditorInfo attribute, - IInputContext inputContext) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public IBinder asBinder() { - // TODO Auto-generated method stub - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java deleted file mode 100644 index f5912e7..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.layoutlib.bridge.BridgeConstants; - -import android.util.AttributeSet; - -import java.util.Map; - -/** - * An implementation of the {@link AttributeSet} interface on top of a map of attribute in the form - * of (name, value). - * - * This is meant to be called only from {@link BridgeContext#obtainStyledAttributes(AttributeSet, int[], int, int)} - * in the case of LayoutParams and therefore isn't a full implementation. - */ -public class BridgeLayoutParamsMapAttributes implements AttributeSet { - - private final Map<String, String> mAttributes; - - public BridgeLayoutParamsMapAttributes(Map<String, String> attributes) { - mAttributes = attributes; - } - - @Override - public String getAttributeValue(String namespace, String name) { - if (BridgeConstants.NS_RESOURCES.equals(namespace)) { - return mAttributes.get(name); - } - - return null; - } - - // ---- the following methods are not called from - // BridgeContext#obtainStyledAttributes(AttributeSet, int[], int, int) - // Should they ever be called, we'll just implement them on a need basis. - - @Override - public int getAttributeCount() { - throw new UnsupportedOperationException(); - } - - @Override - public String getAttributeName(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public String getAttributeValue(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public String getPositionDescription() { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeNameResource(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeResourceValue(String namespace, String attribute, - int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeIntValue(String namespace, String attribute, - int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeUnsignedIntValue(String namespace, String attribute, - int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public float getAttributeFloatValue(String namespace, String attribute, - float defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeListValue(int index, - String[] options, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getAttributeBooleanValue(int index, boolean defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeResourceValue(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeIntValue(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getAttributeUnsignedIntValue(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public float getAttributeFloatValue(int index, float defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public String getIdAttribute() { - throw new UnsupportedOperationException(); - } - - @Override - public String getClassAttribute() { - throw new UnsupportedOperationException(); - } - - @Override - public int getIdAttributeResourceValue(int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getStyleAttribute() { - throw new UnsupportedOperationException(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java deleted file mode 100644 index 6fd5acc..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -package com.android.layoutlib.bridge.android; - -import android.os.IBinder; -import android.os.IPowerManager; -import android.os.RemoteException; -import android.os.WorkSource; - -/** - * Fake implementation of IPowerManager. - * - */ -public class BridgePowerManager implements IPowerManager { - - @Override - public boolean isScreenOn() throws RemoteException { - return true; - } - - @Override - public IBinder asBinder() { - // pass for now. - return null; - } - - @Override - public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3) - throws RemoteException { - // pass for now. - } - - @Override - public void crash(String arg0) throws RemoteException { - // pass for now. - } - - @Override - public void goToSleep(long arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void nap(long arg0) throws RemoteException { - // pass for now. - } - - @Override - public void reboot(boolean confirm, String reason, boolean wait) { - // pass for now. - } - - @Override - public void shutdown(boolean confirm, boolean wait) { - // pass for now. - } - - @Override - public void releaseWakeLock(IBinder arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void setAttentionLight(boolean arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setTemporaryScreenBrightnessSettingOverride(int arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setMaximumScreenOffTimeoutFromDeviceAdmin(int arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setStayOnSetting(int arg0) throws RemoteException { - // pass for now. - } - - @Override - public void updateWakeLockWorkSource(IBinder arg0, WorkSource arg1) throws RemoteException { - // pass for now. - } - - @Override - public boolean isWakeLockLevelSupported(int level) throws RemoteException { - // pass for now. - return true; - } - - @Override - public void userActivity(long time, int event, int flags) throws RemoteException { - // pass for now. - } - - @Override - public void wakeUp(long time) throws RemoteException { - // pass for now. - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java deleted file mode 100644 index df576d2..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.res.Configuration; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.view.DragEvent; -import android.view.IWindow; - -/** - * Implementation of {@link IWindow} to pass to the AttachInfo. - */ -public final class BridgeWindow implements IWindow { - - @Override - public void dispatchAppVisibility(boolean arg0) throws RemoteException { - // pass for now. - } - - @Override - public void dispatchGetNewSurface() throws RemoteException { - // pass for now. - } - - @Override - public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2) - throws RemoteException { - // pass for now. - } - - @Override - public void resized(Rect arg1, Rect arg1p5, Rect arg2, Rect arg3, - boolean arg4, Configuration arg5) throws RemoteException { - // pass for now. - } - - @Override - public void moved(int arg0, int arg1) throws RemoteException { - // pass for now. - } - - @Override - public void dispatchScreenState(boolean on) throws RemoteException { - // pass for now. - } - - @Override - public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException { - // pass for now. - } - - @Override - public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, - boolean sync) { - // pass for now. - } - - @Override - public void dispatchWallpaperCommand(String action, int x, int y, - int z, Bundle extras, boolean sync) { - // pass for now. - } - - @Override - public void closeSystemDialogs(String reason) { - // pass for now. - } - - @Override - public void dispatchDragEvent(DragEvent event) { - // pass for now. - } - - @Override - public void dispatchSystemUiVisibilityChanged(int seq, int globalUi, - int localValue, int localChanges) { - // pass for now. - } - - @Override - public void doneAnimating() { - } - - @Override - public IBinder asBinder() { - // pass for now. - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java deleted file mode 100644 index 09e6878..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.android; - -import android.content.ClipData; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.view.IWindow; -import android.view.IWindowId; -import android.view.IWindowSession; -import android.view.InputChannel; -import android.view.Surface; -import android.view.SurfaceView; -import android.view.WindowManager.LayoutParams; - -/** - * Implementation of {@link IWindowSession} so that mSession is not null in - * the {@link SurfaceView}. - */ -public final class BridgeWindowSession implements IWindowSession { - - @Override - public int add(IWindow arg0, int seq, LayoutParams arg1, int arg2, Rect arg3, - InputChannel outInputchannel) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public int addToDisplay(IWindow arg0, int seq, LayoutParams arg1, int arg2, int displayId, - Rect arg3, InputChannel outInputchannel) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public int addWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2, - Rect arg3) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public int addToDisplayWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2, - int displayId, Rect arg3) - throws RemoteException { - // pass for now. - return 0; - } - - @Override - public void finishDrawing(IWindow arg0) throws RemoteException { - // pass for now. - } - - @Override - public boolean getInTouchMode() throws RemoteException { - // pass for now. - return false; - } - - @Override - public boolean performHapticFeedback(IWindow window, int effectId, boolean always) { - // pass for now. - return false; - } - @Override - public int relayout(IWindow arg0, int seq, LayoutParams arg1, int arg2, int arg3, int arg4, - int arg4_5, Rect arg5Z, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, - Surface arg8) throws RemoteException { - // pass for now. - return 0; - } - - @Override - public void performDeferredDestroy(IWindow window) { - // pass for now. - } - - @Override - public boolean outOfMemory(IWindow window) throws RemoteException { - return false; - } - - @Override - public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { - // pass for now. - } - - @Override - public void remove(IWindow arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setInTouchMode(boolean arg0) throws RemoteException { - // pass for now. - } - - @Override - public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException { - // pass for now. - } - - @Override - public void setInsets(IWindow window, int touchable, Rect contentInsets, - Rect visibleInsets, Region touchableRegion) { - // pass for now. - } - - @Override - public IBinder prepareDrag(IWindow window, int flags, - int thumbnailWidth, int thumbnailHeight, Surface outSurface) - throws RemoteException { - // pass for now - return null; - } - - @Override - public boolean performDrag(IWindow window, IBinder dragToken, - float touchX, float touchY, float thumbCenterX, float thumbCenterY, - ClipData data) - throws RemoteException { - // pass for now - return false; - } - - @Override - public void reportDropResult(IWindow window, boolean consumed) throws RemoteException { - // pass for now - } - - @Override - public void dragRecipientEntered(IWindow window) throws RemoteException { - // pass for now - } - - @Override - public void dragRecipientExited(IWindow window) throws RemoteException { - // pass for now - } - - @Override - public void setWallpaperPosition(IBinder window, float x, float y, - float xStep, float yStep) { - // pass for now. - } - - @Override - public void wallpaperOffsetsComplete(IBinder window) { - // pass for now. - } - - @Override - public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, - int z, Bundle extras, boolean sync) { - // pass for now. - return null; - } - - @Override - public void wallpaperCommandComplete(IBinder window, Bundle result) { - // pass for now. - } - - @Override - public void setUniverseTransform(IBinder window, float alpha, float offx, float offy, - float dsdx, float dtdx, float dsdy, float dtdy) { - // pass for now. - } - - @Override - public IBinder asBinder() { - // pass for now. - return null; - } - - @Override - public void onRectangleOnScreenRequested(IBinder window, Rect rectangle, boolean immediate) { - // pass for now. - } - - @Override - public IWindowId getWindowId(IBinder window) throws RemoteException { - // pass for now. - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java deleted file mode 100644 index ac8712e..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge.android; - - -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.layoutlib.bridge.impl.ParserFactory; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.BridgeXmlPullAttributes; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; - -/** - * {@link BridgeXmlBlockParser} reimplements most of android.xml.XmlBlock.Parser. - * It delegates to both an instance of {@link XmlPullParser} and an instance of - * XmlPullAttributes (for the {@link AttributeSet} part). - */ -public class BridgeXmlBlockParser implements XmlResourceParser { - - private final XmlPullParser mParser; - private final BridgeXmlPullAttributes mAttrib; - private final BridgeContext mContext; - private final boolean mPlatformFile; - - private boolean mStarted = false; - private int mEventType = START_DOCUMENT; - - private boolean mPopped = true; // default to true in case it's not pushed. - - /** - * Builds a {@link BridgeXmlBlockParser}. - * @param parser The XmlPullParser to get the content from. - * @param context the Context. - * @param platformFile Indicates whether the the file is a platform file or not. - */ - public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) { - if (ParserFactory.LOG_PARSER) { - System.out.println("CRTE " + parser.toString()); - } - - mParser = parser; - mContext = context; - mPlatformFile = platformFile; - mAttrib = new BridgeXmlPullAttributes(parser, context, mPlatformFile); - - if (mContext != null) { - mContext.pushParser(this); - mPopped = false; - } - } - - public XmlPullParser getParser() { - return mParser; - } - - public boolean isPlatformFile() { - return mPlatformFile; - } - - public Object getViewCookie() { - if (mParser instanceof ILayoutPullParser) { - return ((ILayoutPullParser)mParser).getViewCookie(); - } - - return null; - } - - public void ensurePopped() { - if (mContext != null && mPopped == false) { - mContext.popParser(); - mPopped = true; - } - } - - // ------- XmlResourceParser implementation - - @Override - public void setFeature(String name, boolean state) - throws XmlPullParserException { - if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) { - return; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) { - return; - } - throw new XmlPullParserException("Unsupported feature: " + name); - } - - @Override - public boolean getFeature(String name) { - if (FEATURE_PROCESS_NAMESPACES.equals(name)) { - return true; - } - if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) { - return true; - } - return false; - } - - @Override - public void setProperty(String name, Object value) throws XmlPullParserException { - throw new XmlPullParserException("setProperty() not supported"); - } - - @Override - public Object getProperty(String name) { - return null; - } - - @Override - public void setInput(Reader in) throws XmlPullParserException { - mParser.setInput(in); - } - - @Override - public void setInput(InputStream inputStream, String inputEncoding) - throws XmlPullParserException { - mParser.setInput(inputStream, inputEncoding); - } - - @Override - public void defineEntityReplacementText(String entityName, - String replacementText) throws XmlPullParserException { - throw new XmlPullParserException( - "defineEntityReplacementText() not supported"); - } - - @Override - public String getNamespacePrefix(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespacePrefix() not supported"); - } - - @Override - public String getInputEncoding() { - return null; - } - - @Override - public String getNamespace(String prefix) { - throw new RuntimeException("getNamespace() not supported"); - } - - @Override - public int getNamespaceCount(int depth) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceCount() not supported"); - } - - @Override - public String getPositionDescription() { - return "Binary XML file line #" + getLineNumber(); - } - - @Override - public String getNamespaceUri(int pos) throws XmlPullParserException { - throw new XmlPullParserException("getNamespaceUri() not supported"); - } - - @Override - public int getColumnNumber() { - return -1; - } - - @Override - public int getDepth() { - return mParser.getDepth(); - } - - @Override - public String getText() { - return mParser.getText(); - } - - @Override - public int getLineNumber() { - return mParser.getLineNumber(); - } - - @Override - public int getEventType() { - return mEventType; - } - - @Override - public boolean isWhitespace() throws XmlPullParserException { - // Original comment: whitespace was stripped by aapt. - return mParser.isWhitespace(); - } - - @Override - public String getPrefix() { - throw new RuntimeException("getPrefix not supported"); - } - - @Override - public char[] getTextCharacters(int[] holderForStartAndLength) { - String txt = getText(); - char[] chars = null; - if (txt != null) { - holderForStartAndLength[0] = 0; - holderForStartAndLength[1] = txt.length(); - chars = new char[txt.length()]; - txt.getChars(0, txt.length(), chars, 0); - } - return chars; - } - - @Override - public String getNamespace() { - return mParser.getNamespace(); - } - - @Override - public String getName() { - return mParser.getName(); - } - - @Override - public String getAttributeNamespace(int index) { - return mParser.getAttributeNamespace(index); - } - - @Override - public String getAttributeName(int index) { - return mParser.getAttributeName(index); - } - - @Override - public String getAttributePrefix(int index) { - throw new RuntimeException("getAttributePrefix not supported"); - } - - @Override - public boolean isEmptyElementTag() { - // XXX Need to detect this. - return false; - } - - @Override - public int getAttributeCount() { - return mParser.getAttributeCount(); - } - - @Override - public String getAttributeValue(int index) { - return mParser.getAttributeValue(index); - } - - @Override - public String getAttributeType(int index) { - return "CDATA"; - } - - @Override - public boolean isAttributeDefault(int index) { - return false; - } - - @Override - public int nextToken() throws XmlPullParserException, IOException { - return next(); - } - - @Override - public String getAttributeValue(String namespace, String name) { - return mParser.getAttributeValue(namespace, name); - } - - @Override - public int next() throws XmlPullParserException, IOException { - if (!mStarted) { - mStarted = true; - - if (ParserFactory.LOG_PARSER) { - System.out.println("STRT " + mParser.toString()); - } - - return START_DOCUMENT; - } - - int ev = mParser.next(); - - if (ParserFactory.LOG_PARSER) { - System.out.println("NEXT " + mParser.toString() + " " + - eventTypeToString(mEventType) + " -> " + eventTypeToString(ev)); - } - - if (ev == END_TAG && mParser.getDepth() == 1) { - // done with parser remove it from the context stack. - ensurePopped(); - - if (ParserFactory.LOG_PARSER) { - System.out.println(""); - } - } - - mEventType = ev; - return ev; - } - - public static String eventTypeToString(int eventType) { - switch (eventType) { - case START_DOCUMENT: - return "START_DOC"; - case END_DOCUMENT: - return "END_DOC"; - case START_TAG: - return "START_TAG"; - case END_TAG: - return "END_TAG"; - case TEXT: - return "TEXT"; - case CDSECT: - return "CDSECT"; - case ENTITY_REF: - return "ENTITY_REF"; - case IGNORABLE_WHITESPACE: - return "IGNORABLE_WHITESPACE"; - case PROCESSING_INSTRUCTION: - return "PROCESSING_INSTRUCTION"; - case COMMENT: - return "COMMENT"; - case DOCDECL: - return "DOCDECL"; - } - - return "????"; - } - - @Override - public void require(int type, String namespace, String name) - throws XmlPullParserException { - if (type != getEventType() - || (namespace != null && !namespace.equals(getNamespace())) - || (name != null && !name.equals(getName()))) - throw new XmlPullParserException("expected " + TYPES[type] - + getPositionDescription()); - } - - @Override - public String nextText() throws XmlPullParserException, IOException { - if (getEventType() != START_TAG) { - throw new XmlPullParserException(getPositionDescription() - + ": parser must be on START_TAG to read next text", this, - null); - } - int eventType = next(); - if (eventType == TEXT) { - String result = getText(); - eventType = next(); - if (eventType != END_TAG) { - throw new XmlPullParserException( - getPositionDescription() - + ": event TEXT it must be immediately followed by END_TAG", - this, null); - } - return result; - } else if (eventType == END_TAG) { - return ""; - } else { - throw new XmlPullParserException(getPositionDescription() - + ": parser must be on START_TAG or TEXT to read text", - this, null); - } - } - - @Override - public int nextTag() throws XmlPullParserException, IOException { - int eventType = next(); - if (eventType == TEXT && isWhitespace()) { // skip whitespace - eventType = next(); - } - if (eventType != START_TAG && eventType != END_TAG) { - throw new XmlPullParserException(getPositionDescription() - + ": expected start or end tag", this, null); - } - return eventType; - } - - // AttributeSet implementation - - - @Override - public void close() { - // pass - } - - @Override - public boolean getAttributeBooleanValue(int index, boolean defaultValue) { - return mAttrib.getAttributeBooleanValue(index, defaultValue); - } - - @Override - public boolean getAttributeBooleanValue(String namespace, String attribute, - boolean defaultValue) { - return mAttrib.getAttributeBooleanValue(namespace, attribute, defaultValue); - } - - @Override - public float getAttributeFloatValue(int index, float defaultValue) { - return mAttrib.getAttributeFloatValue(index, defaultValue); - } - - @Override - public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) { - return mAttrib.getAttributeFloatValue(namespace, attribute, defaultValue); - } - - @Override - public int getAttributeIntValue(int index, int defaultValue) { - return mAttrib.getAttributeIntValue(index, defaultValue); - } - - @Override - public int getAttributeIntValue(String namespace, String attribute, int defaultValue) { - return mAttrib.getAttributeIntValue(namespace, attribute, defaultValue); - } - - @Override - public int getAttributeListValue(int index, String[] options, int defaultValue) { - return mAttrib.getAttributeListValue(index, options, defaultValue); - } - - @Override - public int getAttributeListValue(String namespace, String attribute, - String[] options, int defaultValue) { - return mAttrib.getAttributeListValue(namespace, attribute, options, defaultValue); - } - - @Override - public int getAttributeNameResource(int index) { - return mAttrib.getAttributeNameResource(index); - } - - @Override - public int getAttributeResourceValue(int index, int defaultValue) { - return mAttrib.getAttributeResourceValue(index, defaultValue); - } - - @Override - public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) { - return mAttrib.getAttributeResourceValue(namespace, attribute, defaultValue); - } - - @Override - public int getAttributeUnsignedIntValue(int index, int defaultValue) { - return mAttrib.getAttributeUnsignedIntValue(index, defaultValue); - } - - @Override - public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) { - return mAttrib.getAttributeUnsignedIntValue(namespace, attribute, defaultValue); - } - - @Override - public String getClassAttribute() { - return mAttrib.getClassAttribute(); - } - - @Override - public String getIdAttribute() { - return mAttrib.getIdAttribute(); - } - - @Override - public int getIdAttributeResourceValue(int defaultValue) { - return mAttrib.getIdAttributeResourceValue(defaultValue); - } - - @Override - public int getStyleAttribute() { - return mAttrib.getStyleAttribute(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java deleted file mode 100644 index 9a633bf..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ -package com.android.layoutlib.bridge.android.view; - -import android.util.DisplayMetrics; -import android.view.Display; -import android.view.DisplayInfo; -import android.view.View; -import android.view.WindowManager; - -public class WindowManagerImpl implements WindowManager { - - private final DisplayMetrics mMetrics; - private final Display mDisplay; - - public WindowManagerImpl(DisplayMetrics metrics) { - mMetrics = metrics; - - DisplayInfo info = new DisplayInfo(); - info.logicalHeight = mMetrics.heightPixels; - info.logicalWidth = mMetrics.widthPixels; - mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, null); - } - - @Override - public Display getDefaultDisplay() { - return mDisplay; - } - - - @Override - public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) { - // pass - } - - @Override - public void removeView(View arg0) { - // pass - } - - @Override - public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) { - // pass - } - - - @Override - public void removeViewImmediate(View arg0) { - // pass - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java deleted file mode 100644 index ea9d8d9..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.ResourceHelper; -import com.android.resources.Density; -import com.android.resources.ResourceType; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Base "bar" class for the window decor around the the edited layout. - * This is basically an horizontal layout that loads a given layout on creation (it is read - * through {@link Class#getResourceAsStream(String)}). - * - * The given layout should be a merge layout so that all the children belong to this class directly. - * - * It also provides a few utility methods to configure the content of the layout. - */ -abstract class CustomBar extends LinearLayout { - - protected abstract TextView getStyleableTextView(); - - protected CustomBar(Context context, Density density, int orientation, String layoutPath, - String name) throws XmlPullParserException { - super(context); - setOrientation(orientation); - if (orientation == LinearLayout.HORIZONTAL) { - setGravity(Gravity.CENTER_VERTICAL); - } else { - setGravity(Gravity.CENTER_HORIZONTAL); - } - - LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - - XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), - name); - - BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( - parser, (BridgeContext) context, false /*platformFile*/); - - try { - inflater.inflate(bridgeParser, this, true); - } finally { - bridgeParser.ensurePopped(); - } - } - - private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut, - boolean tryOtherDensities) { - // current density - Density density = densityInOut[0]; - - // bitmap url relative to this class - pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName; - - InputStream stream = getClass().getResourceAsStream(pathOut[0]); - if (stream == null && tryOtherDensities) { - for (Density d : Density.values()) { - if (d != density) { - densityInOut[0] = d; - stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/); - if (stream != null) { - return stream; - } - } - } - } - - return stream; - } - - protected void loadIcon(int index, String iconName, Density density) { - View child = getChildAt(index); - if (child instanceof ImageView) { - ImageView imageView = (ImageView) child; - - String[] pathOut = new String[1]; - Density[] densityInOut = new Density[] { density }; - InputStream stream = getIcon(iconName, densityInOut, pathOut, - true /*tryOtherDensities*/); - density = densityInOut[0]; - - if (stream != null) { - // look for a cached bitmap - Bitmap bitmap = Bridge.getCachedBitmap(pathOut[0], true /*isFramework*/); - if (bitmap == null) { - try { - bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density); - Bridge.setCachedBitmap(pathOut[0], bitmap, true /*isFramework*/); - } catch (IOException e) { - return; - } - } - - if (bitmap != null) { - BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), - bitmap); - imageView.setImageDrawable(drawable); - } - } - } - } - - protected void loadIcon(int index, String iconReference) { - ResourceValue value = getResourceValue(iconReference); - if (value != null) { - loadIcon(index, value); - } - } - - protected void loadIconById(int id, String iconReference) { - ResourceValue value = getResourceValue(iconReference); - if (value != null) { - loadIconById(id, value); - } - } - - - protected Drawable loadIcon(int index, ResourceType type, String name) { - BridgeContext bridgeContext = (BridgeContext) mContext; - RenderResources res = bridgeContext.getRenderResources(); - - // find the resource - ResourceValue value = res.getFrameworkResource(type, name); - - // resolve it if needed - value = res.resolveResValue(value); - return loadIcon(index, value); - } - - private Drawable loadIcon(int index, ResourceValue value) { - View child = getChildAt(index); - if (child instanceof ImageView) { - ImageView imageView = (ImageView) child; - - return loadIcon(imageView, value); - } - - return null; - } - - private Drawable loadIconById(int id, ResourceValue value) { - View child = findViewById(id); - if (child instanceof ImageView) { - ImageView imageView = (ImageView) child; - - return loadIcon(imageView, value); - } - - return null; - } - - - private Drawable loadIcon(ImageView imageView, ResourceValue value) { - Drawable drawable = ResourceHelper.getDrawable(value, (BridgeContext) mContext); - if (drawable != null) { - imageView.setImageDrawable(drawable); - } - - return drawable; - } - - protected TextView setText(int index, String stringReference) { - View child = getChildAt(index); - if (child instanceof TextView) { - TextView textView = (TextView) child; - setText(textView, stringReference); - return textView; - } - - return null; - } - - protected TextView setTextById(int id, String stringReference) { - View child = findViewById(id); - if (child instanceof TextView) { - TextView textView = (TextView) child; - setText(textView, stringReference); - return textView; - } - - return null; - } - - private void setText(TextView textView, String stringReference) { - ResourceValue value = getResourceValue(stringReference); - if (value != null) { - textView.setText(value.getValue()); - } else { - textView.setText(stringReference); - } - } - - protected void setStyle(String themeEntryName) { - - BridgeContext bridgeContext = (BridgeContext) mContext; - RenderResources res = bridgeContext.getRenderResources(); - - ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/); - value = res.resolveResValue(value); - - if (value instanceof StyleResourceValue == false) { - return; - } - - StyleResourceValue style = (StyleResourceValue) value; - - // get the background - ResourceValue backgroundValue = res.findItemInStyle(style, "background", - true /*isFrameworkAttr*/); - backgroundValue = res.resolveResValue(backgroundValue); - if (backgroundValue != null) { - Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext); - if (d != null) { - setBackground(d); - } - } - - TextView textView = getStyleableTextView(); - if (textView != null) { - // get the text style - ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle", - true /*isFrameworkAttr*/); - textStyleValue = res.resolveResValue(textStyleValue); - if (textStyleValue instanceof StyleResourceValue) { - StyleResourceValue textStyle = (StyleResourceValue) textStyleValue; - - ResourceValue textSize = res.findItemInStyle(textStyle, "textSize", - true /*isFrameworkAttr*/); - textSize = res.resolveResValue(textSize); - - if (textSize != null) { - TypedValue out = new TypedValue(); - if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out, - true /*requireUnit*/)) { - textView.setTextSize( - out.getDimension(bridgeContext.getResources().getDisplayMetrics())); - } - } - - - ResourceValue textColor = res.findItemInStyle(textStyle, "textColor", - true /*isFrameworkAttr*/); - textColor = res.resolveResValue(textColor); - if (textColor != null) { - ColorStateList stateList = ResourceHelper.getColorStateList( - textColor, bridgeContext); - if (stateList != null) { - textView.setTextColor(stateList); - } - } - } - } - } - - private ResourceValue getResourceValue(String reference) { - BridgeContext bridgeContext = (BridgeContext) mContext; - RenderResources res = bridgeContext.getRenderResources(); - - // find the resource - ResourceValue value = res.findResValue(reference, false /*isFramework*/); - - // resolve it if needed - return res.resolveResValue(value); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java deleted file mode 100644 index 226649d..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.resources.Density; - -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class FakeActionBar extends CustomBar { - - private TextView mTextView; - - public FakeActionBar(Context context, Density density, String label, String icon) - throws XmlPullParserException { - super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml"); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - loadIconById(android.R.id.home, icon); - mTextView = setText(1, label); - - setStyle("actionBarStyle"); - } - - @Override - protected TextView getStyleableTextView() { - return mTextView; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java deleted file mode 100644 index cc90d6b..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.resources.Density; - -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class NavigationBar extends CustomBar { - - public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException { - super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml"); - - setBackgroundColor(0xFF000000); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - // 0 is a spacer. - int back = 1; - int recent = 3; - if (orientation == LinearLayout.VERTICAL) { - back = 3; - recent = 1; - } - - loadIcon(back, "ic_sysbar_back.png", density); - loadIcon(2, "ic_sysbar_home.png", density); - loadIcon(recent, "ic_sysbar_recent.png", density); - } - - @Override - protected TextView getStyleableTextView() { - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java deleted file mode 100644 index 5c08412..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.resources.Density; -import com.android.resources.ResourceType; - -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LevelListDrawable; -import android.view.Gravity; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class StatusBar extends CustomBar { - - public StatusBar(Context context, Density density) throws XmlPullParserException { - super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml"); - - // FIXME: use FILL_H? - setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT); - setBackgroundColor(0xFF000000); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - // 0 is the spacer - loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density); - Drawable drawable = loadIcon(2, ResourceType.DRAWABLE, "stat_sys_battery_charge"); - if (drawable instanceof LevelListDrawable) { - ((LevelListDrawable) drawable).setLevel(100); - } - } - - @Override - protected TextView getStyleableTextView() { - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java deleted file mode 100644 index c27859f..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.bars; - -import com.android.resources.Density; - -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Context; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class TitleBar extends CustomBar { - - private TextView mTextView; - - public TitleBar(Context context, Density density, String label) - throws XmlPullParserException { - super(context, density, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml"); - - // Cannot access the inside items through id because no R.id values have been - // created for them. - // We do know the order though. - mTextView = setText(0, label); - - setStyle("windowTitleBackgroundStyle"); - } - - @Override - protected TextView getStyleableTextView() { - return mTextView; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java deleted file mode 100644 index ae1217d..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.layoutlib.bridge.util.Debug; -import com.android.layoutlib.bridge.util.SparseWeakArray; - -import android.util.SparseArray; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; - -/** - * Manages native delegates. - * - * This is used in conjunction with layoublib_create: certain Android java classes are mere - * wrappers around a heavily native based implementation, and we need a way to run these classes - * in our Eclipse rendering framework without bringing all the native code from the Android - * platform. - * - * Thus we instruct layoutlib_create to modify the bytecode of these classes to replace their - * native methods by "delegate calls". - * - * For example, a native method android.graphics.Matrix.init(...) will actually become - * a call to android.graphics.Matrix_Delegate.init(...). - * - * The Android java classes that use native code uses an int (Java side) to reference native - * objects. This int is generally directly the pointer to the C structure counterpart. - * Typically a creation method will return such an int, and then this int will be passed later - * to a Java method to identify the C object to manipulate. - * - * Since we cannot use the Java object reference as the int directly, DelegateManager manages the - * int -> Delegate class link. - * - * Native methods usually always have the int as parameters. The first thing the delegate method - * will do is call {@link #getDelegate(int)} to get the Java object matching the int. - * - * Typical native init methods are returning a new int back to the Java class, so - * {@link #addNewDelegate(Object)} does the same. - * - * The JNI references are counted, so we do the same through a {@link WeakReference}. Because - * the Java object needs to count as a reference (even though it only holds an int), we use the - * following mechanism: - * - * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(int)} adds and removes - * the delegate to/from a list. This list hold the reference and prevents the GC from reclaiming - * the delegate. - * - * - {@link #addNewDelegate(Object)} also adds the delegate to a {@link SparseArray} that holds a - * {@link WeakReference} to the delegate. This allows the delegate to be deleted automatically - * when nothing references it. This means that any class that holds a delegate (except for the - * Java main class) must not use the int but the Delegate class instead. The integers must - * only be used in the API between the main Java class and the Delegate. - * - * @param <T> the delegate class to manage - */ -public final class DelegateManager<T> { - private final Class<T> mClass; - private final SparseWeakArray<T> mDelegates = new SparseWeakArray<T>(); - /** list used to store delegates when their main object holds a reference to them. - * This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed - * @see #addNewDelegate(Object) - * @see #removeJavaReferenceFor(int) - */ - private final List<T> mJavaReferences = new ArrayList<T>(); - private int mDelegateCounter = 0; - - public DelegateManager(Class<T> theClass) { - mClass = theClass; - } - - /** - * Returns the delegate from the given native int. - * <p> - * If the int is zero, then this will always return null. - * <p> - * If the int is non zero and the delegate is not found, this will throw an assert. - * - * @param native_object the native int. - * @return the delegate or null if not found. - */ - public T getDelegate(int native_object) { - if (native_object > 0) { - T delegate = mDelegates.get(native_object); - - if (Debug.DEBUG) { - if (delegate == null) { - System.out.println("Unknown " + mClass.getSimpleName() + " with int " + - native_object); - } - } - - assert delegate != null; - return delegate; - } - return null; - } - - /** - * Adds a delegate to the manager and returns the native int used to identify it. - * @param newDelegate the delegate to add - * @return a unique native int to identify the delegate - */ - public int addNewDelegate(T newDelegate) { - int native_object = ++mDelegateCounter; - mDelegates.put(native_object, newDelegate); - assert !mJavaReferences.contains(newDelegate); - mJavaReferences.add(newDelegate); - - if (Debug.DEBUG) { - System.out.println("New " + mClass.getSimpleName() + " with int " + native_object); - } - - return native_object; - } - - /** - * Removes the main reference on the given delegate. - * @param native_object the native integer representing the delegate. - */ - public void removeJavaReferenceFor(int native_object) { - T delegate = getDelegate(native_object); - - if (Debug.DEBUG) { - System.out.println("Removing main Java ref on " + mClass.getSimpleName() + - " with int " + native_object); - } - - mJavaReferences.remove(delegate); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java deleted file mode 100644 index 081ce67..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge.impl; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import android.graphics.Typeface; - -import java.awt.Font; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Provides {@link Font} object to the layout lib. - * <p/> - * The fonts are loaded from the SDK directory. Family/style mapping is done by parsing the - * fonts.xml file located alongside the ttf files. - */ -public final class FontLoader { - private static final String FONTS_SYSTEM = "system_fonts.xml"; - private static final String FONTS_VENDOR = "vendor_fonts.xml"; - private static final String FONTS_FALLBACK = "fallback_fonts.xml"; - - private static final String NODE_FAMILYSET = "familyset"; - private static final String NODE_FAMILY = "family"; - private static final String NODE_NAME = "name"; - private static final String NODE_FILE = "file"; - - private static final String FONT_SUFFIX_NONE = ".ttf"; - private static final String FONT_SUFFIX_REGULAR = "-Regular.ttf"; - private static final String FONT_SUFFIX_BOLD = "-Bold.ttf"; - private static final String FONT_SUFFIX_ITALIC = "-Italic.ttf"; - private static final String FONT_SUFFIX_BOLDITALIC = "-BoldItalic.ttf"; - - // This must match the values of Typeface styles so that we can use them for indices in this - // array. - private static final int[] AWT_STYLES = new int[] { - Font.PLAIN, - Font.BOLD, - Font.ITALIC, - Font.BOLD | Font.ITALIC - }; - private static int[] DERIVE_BOLD_ITALIC = new int[] { - Typeface.ITALIC, Typeface.BOLD, Typeface.NORMAL - }; - private static int[] DERIVE_ITALIC = new int[] { Typeface.NORMAL }; - private static int[] DERIVE_BOLD = new int[] { Typeface.NORMAL }; - - private static final List<FontInfo> mMainFonts = new ArrayList<FontInfo>(); - private static final List<FontInfo> mFallbackFonts = new ArrayList<FontInfo>(); - - private final String mOsFontsLocation; - - public static FontLoader create(String fontOsLocation) { - try { - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - parserFactory.setNamespaceAware(true); - - // parse the system fonts - FontHandler handler = parseFontFile(parserFactory, fontOsLocation, FONTS_SYSTEM); - List<FontInfo> systemFonts = handler.getFontList(); - - - // parse the fallback fonts - handler = parseFontFile(parserFactory, fontOsLocation, FONTS_FALLBACK); - List<FontInfo> fallbackFonts = handler.getFontList(); - - return new FontLoader(fontOsLocation, systemFonts, fallbackFonts); - } catch (ParserConfigurationException e) { - // return null below - } catch (SAXException e) { - // return null below - } catch (FileNotFoundException e) { - // return null below - } catch (IOException e) { - // return null below - } - - return null; - } - - private static FontHandler parseFontFile(SAXParserFactory parserFactory, - String fontOsLocation, String fontFileName) - throws ParserConfigurationException, SAXException, IOException, FileNotFoundException { - - SAXParser parser = parserFactory.newSAXParser(); - File f = new File(fontOsLocation, fontFileName); - - FontHandler definitionParser = new FontHandler( - fontOsLocation + File.separator); - parser.parse(new FileInputStream(f), definitionParser); - return definitionParser; - } - - private FontLoader(String fontOsLocation, - List<FontInfo> fontList, List<FontInfo> fallBackList) { - mOsFontsLocation = fontOsLocation; - mMainFonts.addAll(fontList); - mFallbackFonts.addAll(fallBackList); - } - - - public String getOsFontsLocation() { - return mOsFontsLocation; - } - - /** - * Returns a {@link Font} object given a family name and a style value (constant in - * {@link Typeface}). - * @param family the family name - * @param style a 1-item array containing the requested style. Based on the font being read - * the actual style may be different. The array contains the actual style after - * the method returns. - * @return the font object or null if no match could be found. - */ - public synchronized List<Font> getFont(String family, int style) { - List<Font> result = new ArrayList<Font>(); - - if (family == null) { - return result; - } - - - // get the font objects from the main list based on family. - for (FontInfo info : mMainFonts) { - if (info.families.contains(family)) { - result.add(info.font[style]); - break; - } - } - - // add all the fallback fonts for the given style - for (FontInfo info : mFallbackFonts) { - result.add(info.font[style]); - } - - return result; - } - - - public synchronized List<Font> getFallbackFonts(int style) { - List<Font> result = new ArrayList<Font>(); - // add all the fallback fonts - for (FontInfo info : mFallbackFonts) { - result.add(info.font[style]); - } - return result; - } - - - private final static class FontInfo { - final Font[] font = new Font[4]; // Matches the 4 type-face styles. - final Set<String> families; - - FontInfo() { - families = new HashSet<String>(); - } - } - - private final static class FontHandler extends DefaultHandler { - private final String mOsFontsLocation; - - private FontInfo mFontInfo = null; - private final StringBuilder mBuilder = new StringBuilder(); - private List<FontInfo> mFontList = new ArrayList<FontInfo>(); - - private FontHandler(String osFontsLocation) { - super(); - mOsFontsLocation = osFontsLocation; - } - - public List<FontInfo> getFontList() { - return mFontList; - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) - */ - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) - throws SAXException { - if (NODE_FAMILYSET.equals(localName)) { - mFontList = new ArrayList<FontInfo>(); - } else if (NODE_FAMILY.equals(localName)) { - if (mFontList != null) { - mFontInfo = new FontInfo(); - } - } - - mBuilder.setLength(0); - - super.startElement(uri, localName, name, attributes); - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) - */ - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - mBuilder.append(ch, start, length); - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String) - */ - @Override - public void endElement(String uri, String localName, String name) throws SAXException { - if (NODE_FAMILY.equals(localName)) { - if (mFontInfo != null) { - // if has a normal font file, add to the list - if (mFontInfo.font[Typeface.NORMAL] != null) { - mFontList.add(mFontInfo); - - // create missing font styles, order is important. - if (mFontInfo.font[Typeface.BOLD_ITALIC] == null) { - computeDerivedFont(Typeface.BOLD_ITALIC, DERIVE_BOLD_ITALIC); - } - if (mFontInfo.font[Typeface.ITALIC] == null) { - computeDerivedFont(Typeface.ITALIC, DERIVE_ITALIC); - } - if (mFontInfo.font[Typeface.BOLD] == null) { - computeDerivedFont(Typeface.BOLD, DERIVE_BOLD); - } - } - - mFontInfo = null; - } - } else if (NODE_NAME.equals(localName)) { - // handle a new name for an existing Font Info - if (mFontInfo != null) { - String family = trimXmlWhitespaces(mBuilder.toString()); - mFontInfo.families.add(family); - } - } else if (NODE_FILE.equals(localName)) { - // handle a new file for an existing Font Info - if (mFontInfo != null) { - String fileName = trimXmlWhitespaces(mBuilder.toString()); - Font font = getFont(fileName); - if (font != null) { - if (fileName.endsWith(FONT_SUFFIX_REGULAR)) { - mFontInfo.font[Typeface.NORMAL] = font; - } else if (fileName.endsWith(FONT_SUFFIX_BOLD)) { - mFontInfo.font[Typeface.BOLD] = font; - } else if (fileName.endsWith(FONT_SUFFIX_ITALIC)) { - mFontInfo.font[Typeface.ITALIC] = font; - } else if (fileName.endsWith(FONT_SUFFIX_BOLDITALIC)) { - mFontInfo.font[Typeface.BOLD_ITALIC] = font; - } else if (fileName.endsWith(FONT_SUFFIX_NONE)) { - mFontInfo.font[Typeface.NORMAL] = font; - } - } - } - } - } - - private Font getFont(String fileName) { - try { - File file = new File(mOsFontsLocation, fileName); - if (file.exists()) { - return Font.createFont(Font.TRUETYPE_FONT, file); - } - } catch (Exception e) { - - } - - return null; - } - - private void computeDerivedFont( int toCompute, int[] basedOnList) { - for (int basedOn : basedOnList) { - if (mFontInfo.font[basedOn] != null) { - mFontInfo.font[toCompute] = - mFontInfo.font[basedOn].deriveFont(AWT_STYLES[toCompute]); - return; - } - } - - // we really shouldn't stop there. This means we don't have a NORMAL font... - assert false; - } - - private String trimXmlWhitespaces(String value) { - if (value == null) { - return null; - } - - // look for carriage return and replace all whitespace around it by just 1 space. - int index; - - while ((index = value.indexOf('\n')) != -1) { - // look for whitespace on each side - int left = index - 1; - while (left >= 0) { - if (Character.isWhitespace(value.charAt(left))) { - left--; - } else { - break; - } - } - - int right = index + 1; - int count = value.length(); - while (right < count) { - if (Character.isWhitespace(value.charAt(right))) { - right++; - } else { - break; - } - } - - // remove all between left and right (non inclusive) and replace by a single space. - String leftString = null; - if (left >= 0) { - leftString = value.substring(0, left + 1); - } - String rightString = null; - if (right < count) { - rightString = value.substring(right); - } - - if (leftString != null) { - value = leftString; - if (rightString != null) { - value += " " + rightString; - } - } else { - value = rightString != null ? rightString : ""; - } - } - - // now we un-escape the string - int length = value.length(); - char[] buffer = value.toCharArray(); - - for (int i = 0 ; i < length ; i++) { - if (buffer[i] == '\\') { - if (buffer[i+1] == 'n') { - // replace the char with \n - buffer[i+1] = '\n'; - } - - // offset the rest of the buffer since we go from 2 to 1 char - System.arraycopy(buffer, i+1, buffer, i, length - i - 1); - length--; - } - } - - return new String(buffer, 0, length); - } - - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java deleted file mode 100644 index 21d6b1a..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +++ /dev/null @@ -1,803 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.layoutlib.bridge.Bridge; - -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Paint_Delegate; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Region; -import android.graphics.Region_Delegate; -import android.graphics.Shader_Delegate; -import android.graphics.Xfermode_Delegate; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; - -/** - * Class representing a graphics context snapshot, as well as a context stack as a linked list. - * <p> - * This is based on top of {@link Graphics2D} but can operate independently if none are available - * yet when setting transforms and clip information. - * <p> - * This allows for drawing through {@link #draw(Drawable, Paint_Delegate)} and - * {@link #draw(Drawable, Paint_Delegate)} - * - * Handling of layers (created with {@link Canvas#saveLayer(RectF, Paint, int)}) is handled through - * a list of Graphics2D for each layers. The class actually maintains a list of {@link Layer} - * for each layer. Doing a save() will duplicate this list so that each graphics2D object - * ({@link Layer#getGraphics()}) is configured only for the new snapshot. - */ -public class GcSnapshot { - - private final GcSnapshot mPrevious; - private final int mFlags; - - /** list of layers. The first item in the list is always the */ - private final ArrayList<Layer> mLayers = new ArrayList<Layer>(); - - /** temp transform in case transformation are set before a Graphics2D exists */ - private AffineTransform mTransform = null; - /** temp clip in case clipping is set before a Graphics2D exists */ - private Area mClip = null; - - // local layer data - /** a local layer created with {@link Canvas#saveLayer(RectF, Paint, int)}. - * If this is null, this does not mean there's no layer, just that the snapshot is not the - * one that created the layer. - * @see #getLayerSnapshot() - */ - private final Layer mLocalLayer; - private final Paint_Delegate mLocalLayerPaint; - private final Rect mLayerBounds; - - public interface Drawable { - void draw(Graphics2D graphics, Paint_Delegate paint); - } - - /** - * Class containing information about a layer. - * - * This contains graphics, bitmap and layer information. - */ - private static class Layer { - private final Graphics2D mGraphics; - private final Bitmap_Delegate mBitmap; - private final BufferedImage mImage; - /** the flags that were used to configure the layer. This is never changed, and passed - * as is when {@link #makeCopy()} is called */ - private final int mFlags; - /** the original content of the layer when the next object was created. This is not - * passed in {@link #makeCopy()} and instead is recreated when a new layer is added - * (depending on its flags) */ - private BufferedImage mOriginalCopy; - - /** - * Creates a layer with a graphics and a bitmap. This is only used to create - * the base layer. - * - * @param graphics the graphics - * @param bitmap the bitmap - */ - Layer(Graphics2D graphics, Bitmap_Delegate bitmap) { - mGraphics = graphics; - mBitmap = bitmap; - mImage = mBitmap.getImage(); - mFlags = 0; - } - - /** - * Creates a layer with a graphics and an image. If the image belongs to a - * {@link Bitmap_Delegate} (case of the base layer), then - * {@link Layer#Layer(Graphics2D, Bitmap_Delegate)} should be used. - * - * @param graphics the graphics the new graphics for this layer - * @param image the image the image from which the graphics came - * @param flags the flags that were used to save this layer - */ - Layer(Graphics2D graphics, BufferedImage image, int flags) { - mGraphics = graphics; - mBitmap = null; - mImage = image; - mFlags = flags; - } - - /** The Graphics2D, guaranteed to be non null */ - Graphics2D getGraphics() { - return mGraphics; - } - - /** The BufferedImage, guaranteed to be non null */ - BufferedImage getImage() { - return mImage; - } - - /** Returns the layer save flags. This is only valid for additional layers. - * For the base layer this will always return 0; - * For a given layer, all further copies of this {@link Layer} object in new snapshots - * will always return the same value. - */ - int getFlags() { - return mFlags; - } - - Layer makeCopy() { - if (mBitmap != null) { - return new Layer((Graphics2D) mGraphics.create(), mBitmap); - } - - return new Layer((Graphics2D) mGraphics.create(), mImage, mFlags); - } - - /** sets an optional copy of the original content to be used during restore */ - void setOriginalCopy(BufferedImage image) { - mOriginalCopy = image; - } - - BufferedImage getOriginalCopy() { - return mOriginalCopy; - } - - void change() { - if (mBitmap != null) { - mBitmap.change(); - } - } - - /** - * Sets the clip for the graphics2D object associated with the layer. - * This should be used over the normal Graphics2D setClip method. - * - * @param clipShape the shape to use a the clip shape. - */ - void setClip(Shape clipShape) { - // because setClip is only guaranteed to work with rectangle shape, - // first reset the clip to max and then intersect the current (empty) - // clip with the shap. - mGraphics.setClip(null); - mGraphics.clip(clipShape); - } - - /** - * Clips the layer with the given shape. This performs an intersect between the current - * clip shape and the given shape. - * @param shape the new clip shape. - */ - public void clip(Shape shape) { - mGraphics.clip(shape); - } - } - - /** - * Creates the root snapshot associating it with a given bitmap. - * <p> - * If <var>bitmap</var> is null, then {@link GcSnapshot#setBitmap(Bitmap_Delegate)} must be - * called before the snapshot can be used to draw. Transform and clip operations are permitted - * before. - * - * @param image the image to associate to the snapshot or null. - * @return the root snapshot - */ - public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) { - GcSnapshot snapshot = new GcSnapshot(); - if (bitmap != null) { - snapshot.setBitmap(bitmap); - } - - return snapshot; - } - - /** - * Saves the current state according to the given flags and returns the new current snapshot. - * <p/> - * This is the equivalent of {@link Canvas#save(int)} - * - * @param flags the save flags. - * @return the new snapshot - * - * @see Canvas#save(int) - */ - public GcSnapshot save(int flags) { - return new GcSnapshot(this, null /*layerbounds*/, null /*paint*/, flags); - } - - /** - * Saves the current state and creates a new layer, and returns the new current snapshot. - * <p/> - * This is the equivalent of {@link Canvas#saveLayer(RectF, Paint, int)} - * - * @param layerBounds the layer bounds - * @param paint the Paint information used to blit the layer back into the layers underneath - * upon restore - * @param flags the save flags. - * @return the new snapshot - * - * @see Canvas#saveLayer(RectF, Paint, int) - */ - public GcSnapshot saveLayer(RectF layerBounds, Paint_Delegate paint, int flags) { - return new GcSnapshot(this, layerBounds, paint, flags); - } - - /** - * Creates the root snapshot. - * {@link #setGraphics2D(Graphics2D)} will have to be called on it when possible. - */ - private GcSnapshot() { - mPrevious = null; - mFlags = 0; - mLocalLayer = null; - mLocalLayerPaint = null; - mLayerBounds = null; - } - - /** - * Creates a new {@link GcSnapshot} on top of another one, with a layer data to be restored - * into the main graphics when {@link #restore()} is called. - * - * @param previous the previous snapshot head. - * @param layerBounds the region of the layer. Optional, if null, this is a normal save() - * @param paint the Paint information used to blit the layer back into the layers underneath - * upon restore - * @param flags the flags regarding what should be saved. - */ - private GcSnapshot(GcSnapshot previous, RectF layerBounds, Paint_Delegate paint, int flags) { - assert previous != null; - mPrevious = previous; - mFlags = flags; - - // make a copy of the current layers before adding the new one. - // This keeps the same BufferedImage reference but creates new Graphics2D for this - // snapshot. - // It does not copy whatever original copy the layers have, as they will be done - // only if the new layer doesn't clip drawing to itself. - for (Layer layer : mPrevious.mLayers) { - mLayers.add(layer.makeCopy()); - } - - if (layerBounds != null) { - // get the current transform - AffineTransform matrix = mLayers.get(0).getGraphics().getTransform(); - - // transform the layerBounds with the current transform and stores it into a int rect - RectF rect2 = new RectF(); - mapRect(matrix, rect2, layerBounds); - mLayerBounds = new Rect(); - rect2.round(mLayerBounds); - - // get the base layer (always at index 0) - Layer baseLayer = mLayers.get(0); - - // create the image for the layer - BufferedImage layerImage = new BufferedImage( - baseLayer.getImage().getWidth(), - baseLayer.getImage().getHeight(), - (mFlags & Canvas.HAS_ALPHA_LAYER_SAVE_FLAG) != 0 ? - BufferedImage.TYPE_INT_ARGB : - BufferedImage.TYPE_INT_RGB); - - // create a graphics for it so that drawing can be done. - Graphics2D layerGraphics = layerImage.createGraphics(); - - // because this layer inherits the current context for transform and clip, - // set them to one from the base layer. - AffineTransform currentMtx = baseLayer.getGraphics().getTransform(); - layerGraphics.setTransform(currentMtx); - - // create a new layer for this new layer and add it to the list at the end. - mLayers.add(mLocalLayer = new Layer(layerGraphics, layerImage, flags)); - - // set the clip on it. - Shape currentClip = baseLayer.getGraphics().getClip(); - mLocalLayer.setClip(currentClip); - - // if the drawing is not clipped to the local layer only, we save the current content - // of all other layers. We are only interested in the part that will actually - // be drawn, so we create as small bitmaps as we can. - // This is so that we can erase the drawing that goes in the layers below that will - // be coming from the layer itself. - if ((mFlags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0) { - int w = mLayerBounds.width(); - int h = mLayerBounds.height(); - for (int i = 0 ; i < mLayers.size() - 1 ; i++) { - Layer layer = mLayers.get(i); - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = image.createGraphics(); - graphics.drawImage(layer.getImage(), - 0, 0, w, h, - mLayerBounds.left, mLayerBounds.top, - mLayerBounds.right, mLayerBounds.bottom, - null); - graphics.dispose(); - layer.setOriginalCopy(image); - } - } - } else { - mLocalLayer = null; - mLayerBounds = null; - } - - mLocalLayerPaint = paint; - } - - public void dispose() { - for (Layer layer : mLayers) { - layer.getGraphics().dispose(); - } - - if (mPrevious != null) { - mPrevious.dispose(); - } - } - - /** - * Restores the top {@link GcSnapshot}, and returns the next one. - */ - public GcSnapshot restore() { - return doRestore(); - } - - /** - * Restores the {@link GcSnapshot} to <var>saveCount</var>. - * @param saveCount the saveCount or -1 to only restore 1. - * - * @return the new head of the Gc snapshot stack. - */ - public GcSnapshot restoreTo(int saveCount) { - return doRestoreTo(size(), saveCount); - } - - public int size() { - if (mPrevious != null) { - return mPrevious.size() + 1; - } - - return 1; - } - - /** - * Link the snapshot to a Bitmap_Delegate. - * <p/> - * This is only for the case where the snapshot was created with a null image when calling - * {@link #createDefaultSnapshot(Bitmap_Delegate)}, and is therefore not yet linked to - * a previous snapshot. - * <p/> - * If any transform or clip information was set before, they are put into the Graphics object. - * @param bitmap the bitmap to link to. - */ - public void setBitmap(Bitmap_Delegate bitmap) { - // create a new Layer for the bitmap. This will be the base layer. - Graphics2D graphics2D = bitmap.getImage().createGraphics(); - Layer baseLayer = new Layer(graphics2D, bitmap); - - // Set the current transform and clip which can either come from mTransform/mClip if they - // were set when there was no bitmap/layers or from the current base layers if there is - // one already. - - graphics2D.setTransform(getTransform()); - // reset mTransform in case there was one. - mTransform = null; - - baseLayer.setClip(getClip()); - // reset mClip in case there was one. - mClip = null; - - // replace whatever current layers we have with this. - mLayers.clear(); - mLayers.add(baseLayer); - - } - - public void translate(float dx, float dy) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().translate(dx, dy); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.translate(dx, dy); - } - } - - public void rotate(double radians) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().rotate(radians); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.rotate(radians); - } - } - - public void scale(float sx, float sy) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().scale(sx, sy); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.scale(sx, sy); - } - } - - public AffineTransform getTransform() { - if (mLayers.size() > 0) { - // all graphics2D in the list have the same transform - return mLayers.get(0).getGraphics().getTransform(); - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - return mTransform; - } - } - - public void setTransform(AffineTransform transform) { - if (mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.getGraphics().setTransform(transform); - } - } else { - if (mTransform == null) { - mTransform = new AffineTransform(); - } - mTransform.setTransform(transform); - } - } - - public boolean clip(Shape shape, int regionOp) { - // Simple case of intersect with existing layers. - // Because Graphics2D#setClip works a bit peculiarly, we optimize - // the case of clipping by intersection, as it's supported natively. - if (regionOp == Region.Op.INTERSECT.nativeInt && mLayers.size() > 0) { - for (Layer layer : mLayers) { - layer.clip(shape); - } - - Shape currentClip = getClip(); - return currentClip != null && currentClip.getBounds().isEmpty() == false; - } - - Area area = null; - - if (regionOp == Region.Op.REPLACE.nativeInt) { - area = new Area(shape); - } else { - area = Region_Delegate.combineShapes(getClip(), shape, regionOp); - } - - assert area != null; - - if (mLayers.size() > 0) { - if (area != null) { - for (Layer layer : mLayers) { - layer.setClip(area); - } - } - - Shape currentClip = getClip(); - return currentClip != null && currentClip.getBounds().isEmpty() == false; - } else { - if (area != null) { - mClip = area; - } else { - mClip = new Area(); - } - - return mClip.getBounds().isEmpty() == false; - } - } - - public boolean clipRect(float left, float top, float right, float bottom, int regionOp) { - return clip(new Rectangle2D.Float(left, top, right - left, bottom - top), regionOp); - } - - /** - * Returns the current clip, or null if none have been setup. - */ - public Shape getClip() { - if (mLayers.size() > 0) { - // they all have the same clip - return mLayers.get(0).getGraphics().getClip(); - } else { - return mClip; - } - } - - private GcSnapshot doRestoreTo(int size, int saveCount) { - if (size <= saveCount) { - return this; - } - - // restore the current one first. - GcSnapshot previous = doRestore(); - - if (size == saveCount + 1) { // this was the only one that needed restore. - return previous; - } else { - return previous.doRestoreTo(size - 1, saveCount); - } - } - - /** - * Executes the Drawable's draw method, with a null paint delegate. - * <p/> - * Note that the method can be called several times if there are more than one active layer. - * @param drawable - */ - public void draw(Drawable drawable) { - draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/); - } - - /** - * Executes the Drawable's draw method. - * <p/> - * Note that the method can be called several times if there are more than one active layer. - * @param drawable - * @param paint - * @param compositeOnly whether the paint is used for composite only. This is typically - * the case for bitmaps. - * @param forceSrcMode if true, this overrides the composite to be SRC - */ - public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly, - boolean forceSrcMode) { - // the current snapshot may not have a mLocalLayer (ie it was created on save() instead - // of saveLayer(), but that doesn't mean there's no layer. - // mLayers however saves all the information we need (flags). - if (mLayers.size() == 1) { - // no layer, only base layer. easy case. - drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceSrcMode); - } else { - // draw in all the layers until the layer save flags tells us to stop (ie drawing - // in that layer is limited to the layer itself. - int flags; - int i = mLayers.size() - 1; - - do { - Layer layer = mLayers.get(i); - - drawInLayer(layer, drawable, paint, compositeOnly, forceSrcMode); - - // then go to previous layer, only if there are any left, and its flags - // doesn't restrict drawing to the layer itself. - i--; - flags = layer.getFlags(); - } while (i >= 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0); - } - } - - private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint, - boolean compositeOnly, boolean forceSrcMode) { - Graphics2D originalGraphics = layer.getGraphics(); - // get a Graphics2D object configured with the drawing parameters. - Graphics2D configuredGraphics2D = - paint != null ? - createCustomGraphics(originalGraphics, paint, compositeOnly, forceSrcMode) : - (Graphics2D) originalGraphics.create(); - - try { - drawable.draw(configuredGraphics2D, paint); - layer.change(); - } finally { - // dispose Graphics2D object - configuredGraphics2D.dispose(); - } - } - - private GcSnapshot doRestore() { - if (mPrevious != null) { - if (mLocalLayer != null) { - // prepare to blit the layers in which we have draw, in the layer beneath - // them, starting with the top one (which is the current local layer). - int i = mLayers.size() - 1; - int flags; - do { - Layer dstLayer = mLayers.get(i - 1); - - restoreLayer(dstLayer); - - flags = dstLayer.getFlags(); - i--; - } while (i > 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0); - } - - // if this snapshot does not save everything, then set the previous snapshot - // to this snapshot content - - // didn't save the matrix? set the current matrix on the previous snapshot - if ((mFlags & Canvas.MATRIX_SAVE_FLAG) == 0) { - AffineTransform mtx = getTransform(); - for (Layer layer : mPrevious.mLayers) { - layer.getGraphics().setTransform(mtx); - } - } - - // didn't save the clip? set the current clip on the previous snapshot - if ((mFlags & Canvas.CLIP_SAVE_FLAG) == 0) { - Shape clip = getClip(); - for (Layer layer : mPrevious.mLayers) { - layer.setClip(clip); - } - } - } - - for (Layer layer : mLayers) { - layer.getGraphics().dispose(); - } - - return mPrevious; - } - - private void restoreLayer(Layer dstLayer) { - - Graphics2D baseGfx = dstLayer.getImage().createGraphics(); - - // if the layer contains an original copy this means the flags - // didn't restrict drawing to the local layer and we need to make sure the - // layer bounds in the layer beneath didn't receive any drawing. - // so we use the originalCopy to erase the new drawings in there. - BufferedImage originalCopy = dstLayer.getOriginalCopy(); - if (originalCopy != null) { - Graphics2D g = (Graphics2D) baseGfx.create(); - g.setComposite(AlphaComposite.Src); - - g.drawImage(originalCopy, - mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, - 0, 0, mLayerBounds.width(), mLayerBounds.height(), - null); - g.dispose(); - } - - // now draw put the content of the local layer onto the layer, - // using the paint information - Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint, - true /*alphaOnly*/, false /*forceSrcMode*/); - - g.drawImage(mLocalLayer.getImage(), - mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, - mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, - null); - g.dispose(); - - baseGfx.dispose(); - } - - /** - * Creates a new {@link Graphics2D} based on the {@link Paint} parameters. - * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. - */ - private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint, - boolean compositeOnly, boolean forceSrcMode) { - // make new one graphics - Graphics2D g = (Graphics2D) original.create(); - - // configure it - - if (paint.isAntiAliased()) { - g.setRenderingHint( - RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setRenderingHint( - RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - - boolean customShader = false; - - // get the shader first, as it'll replace the color if it can be used it. - if (compositeOnly == false) { - Shader_Delegate shaderDelegate = paint.getShader(); - if (shaderDelegate != null) { - if (shaderDelegate.isSupported()) { - java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint(); - assert shaderPaint != null; - if (shaderPaint != null) { - g.setPaint(shaderPaint); - customShader = true; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER, - shaderDelegate.getSupportMessage(), - null /*throwable*/, null /*data*/); - } - } - - // if no shader, use the paint color - if (customShader == false) { - g.setColor(new Color(paint.getColor(), true /*hasAlpha*/)); - } - - // set the stroke - g.setStroke(paint.getJavaStroke()); - } - - // the alpha for the composite. Always opaque if the normal paint color is used since - // it contains the alpha - int alpha = (compositeOnly || customShader) ? paint.getAlpha() : 0xFF; - - if (forceSrcMode) { - g.setComposite(AlphaComposite.getInstance( - AlphaComposite.SRC, (float) alpha / 255.f)); - } else { - boolean customXfermode = false; - Xfermode_Delegate xfermodeDelegate = paint.getXfermode(); - if (xfermodeDelegate != null) { - if (xfermodeDelegate.isSupported()) { - Composite composite = xfermodeDelegate.getComposite(alpha); - assert composite != null; - if (composite != null) { - g.setComposite(composite); - customXfermode = true; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE, - xfermodeDelegate.getSupportMessage(), - null /*throwable*/, null /*data*/); - } - } - - // if there was no custom xfermode, but we have alpha (due to a shader and a non - // opaque alpha channel in the paint color), then we create an AlphaComposite anyway - // that will handle the alpha. - if (customXfermode == false && alpha != 0xFF) { - g.setComposite(AlphaComposite.getInstance( - AlphaComposite.SRC_OVER, (float) alpha / 255.f)); - } - } - - return g; - } - - private void mapRect(AffineTransform matrix, RectF dst, RectF src) { - // array with 4 corners - float[] corners = new float[] { - src.left, src.top, - src.right, src.top, - src.right, src.bottom, - src.left, src.bottom, - }; - - // apply the transform to them. - matrix.transform(corners, 0, corners, 0, 4); - - // now put the result in the rect. We take the min/max of Xs and min/max of Ys - dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6])); - dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6])); - - dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7])); - dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java deleted file mode 100644 index 803849f..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.impl; - - -import org.kxml2.io.KXmlParser; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -/** - * A factory for {@link XmlPullParser}. - * - */ -public class ParserFactory { - - private final static String ENCODING = "UTF-8"; //$NON-NLS-1$ - - public final static boolean LOG_PARSER = false; - - public static XmlPullParser create(File f) - throws XmlPullParserException, FileNotFoundException { - InputStream stream = new FileInputStream(f); - return create(stream, f.getName(), f.length()); - } - - public static XmlPullParser create(InputStream stream, String name) - throws XmlPullParserException { - return create(stream, name, -1); - } - - private static XmlPullParser create(InputStream stream, String name, long size) - throws XmlPullParserException { - KXmlParser parser = instantiateParser(name); - - stream = readAndClose(stream, name, size); - - parser.setInput(stream, ENCODING); - return parser; - } - - private static KXmlParser instantiateParser(String name) throws XmlPullParserException { - KXmlParser parser; - if (name != null) { - parser = new CustomParser(name); - } else { - parser = new KXmlParser(); - } - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - return parser; - } - - private static InputStream readAndClose(InputStream stream, String name, long size) - throws XmlPullParserException { - // just a sanity check. It's doubtful we'll have such big files! - if (size > Integer.MAX_VALUE) { - throw new XmlPullParserException("File " + name + " is too big to be parsed"); - } - int intSize = (int) size; - - // create a buffered reader to facilitate reading. - BufferedInputStream bufferedStream = new BufferedInputStream(stream); - try { - int avail; - if (intSize != -1) { - avail = intSize; - } else { - // get the size to read. - avail = bufferedStream.available(); - } - - // create the initial buffer and read it. - byte[] buffer = new byte[avail]; - int read = stream.read(buffer); - - // this is the easy case. - if (read == intSize) { - return new ByteArrayInputStream(buffer); - } - - // check if there is more to read (read() does not necessarily read all that - // available() returned!) - while ((avail = bufferedStream.available()) > 0) { - if (read + avail > buffer.length) { - // just allocate what is needed. We're mostly reading small files - // so it shouldn't be too problematic. - byte[] moreBuffer = new byte[read + avail]; - System.arraycopy(buffer, 0, moreBuffer, 0, read); - buffer = moreBuffer; - } - - read += stream.read(buffer, read, avail); - } - - // return a new stream encapsulating this buffer. - return new ByteArrayInputStream(buffer); - - } catch (IOException e) { - throw new XmlPullParserException("Failed to read " + name, null, e); - } finally { - try { - bufferedStream.close(); - } catch (IOException e) { - } - } - } - - private static class CustomParser extends KXmlParser { - private final String mName; - - CustomParser(String name) { - super(); - mName = name; - } - - @Override - public String toString() { - return mName; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java deleted file mode 100644 index 7b70180..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; - -import android.animation.AnimationThread; -import android.animation.Animator; - -public class PlayAnimationThread extends AnimationThread { - - private final Animator mAnimator; - - public PlayAnimationThread(Animator animator, RenderSessionImpl scene, String animName, - IAnimationListener listener) { - super(scene, animName, listener); - mAnimator = animator; - } - - @Override - public Result preAnimation() { - // start the animation. This will send a message to the handler right away, so - // the queue is filled when this method returns. - mAnimator.start(); - - return Status.SUCCESS.createResult(); - } - - @Override - public void postAnimation() { - // nothing to be done. - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java deleted file mode 100644 index b909bec..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.impl; - -import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT; -import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; - -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderParams; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider; -import com.android.ide.common.rendering.api.Result; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.resources.Density; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; -import com.android.resources.ScreenSize; - -import android.content.res.Configuration; -import android.os.HandlerThread_Delegate; -import android.os.Looper; -import android.util.DisplayMetrics; -import android.view.ViewConfiguration_Accessor; -import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodManager_Accessor; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Base class for rendering action. - * - * It provides life-cycle methods to init and stop the rendering. - * The most important methods are: - * {@link #init(long)} and {@link #acquire(long)} to start a rendering and {@link #release()} - * after the rendering. - * - * - * @param <T> the {@link RenderParams} implementation - * - */ -public abstract class RenderAction<T extends RenderParams> extends FrameworkResourceIdProvider { - - /** - * The current context being rendered. This is set through {@link #acquire(long)} and - * {@link #init(long)}, and unset in {@link #release()}. - */ - private static BridgeContext sCurrentContext = null; - - private final T mParams; - - private BridgeContext mContext; - - /** - * Creates a renderAction. - * <p> - * This <b>must</b> be followed by a call to {@link RenderAction#init()}, which act as a - * call to {@link RenderAction#acquire(long)} - * - * @param params the RenderParams. This must be a copy that the action can keep - * - */ - protected RenderAction(T params) { - mParams = params; - } - - /** - * Initializes and acquires the scene, creating various Android objects such as context, - * inflater, and parser. - * - * @param timeout the time to wait if another rendering is happening. - * - * @return whether the scene was prepared - * - * @see #acquire(long) - * @see #release() - */ - public Result init(long timeout) { - // acquire the lock. if the result is null, lock was just acquired, otherwise, return - // the result. - Result result = acquireLock(timeout); - if (result != null) { - return result; - } - - HardwareConfig hardwareConfig = mParams.getHardwareConfig(); - - // setup the display Metrics. - DisplayMetrics metrics = new DisplayMetrics(); - metrics.densityDpi = metrics.noncompatDensityDpi = - hardwareConfig.getDensity().getDpiValue(); - - metrics.density = metrics.noncompatDensity = - metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT; - - metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density; - - metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth(); - metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight(); - metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi(); - metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi(); - - RenderResources resources = mParams.getResources(); - - // build the context - mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources, - mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion()); - - setUp(); - - return SUCCESS.createResult(); - } - - - /** - * Prepares the scene for action. - * <p> - * This call is blocking if another rendering/inflating is currently happening, and will return - * whether the preparation worked. - * - * The preparation can fail if another rendering took too long and the timeout was elapsed. - * - * More than one call to this from the same thread will have no effect and will return - * {@link Result#SUCCESS}. - * - * After scene actions have taken place, only one call to {@link #release()} must be - * done. - * - * @param timeout the time to wait if another rendering is happening. - * - * @return whether the scene was prepared - * - * @see #release() - * - * @throws IllegalStateException if {@link #init(long)} was never called. - */ - public Result acquire(long timeout) { - if (mContext == null) { - throw new IllegalStateException("After scene creation, #init() must be called"); - } - - // acquire the lock. if the result is null, lock was just acquired, otherwise, return - // the result. - Result result = acquireLock(timeout); - if (result != null) { - return result; - } - - setUp(); - - return SUCCESS.createResult(); - } - - /** - * Acquire the lock so that the scene can be acted upon. - * <p> - * This returns null if the lock was just acquired, otherwise it returns - * {@link Result#SUCCESS} if the lock already belonged to that thread, or another - * instance (see {@link Result#getStatus()}) if an error occurred. - * - * @param timeout the time to wait if another rendering is happening. - * @return null if the lock was just acquire or another result depending on the state. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene. - */ - private Result acquireLock(long timeout) { - ReentrantLock lock = Bridge.getLock(); - if (lock.isHeldByCurrentThread() == false) { - try { - boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); - - if (acquired == false) { - return ERROR_TIMEOUT.createResult(); - } - } catch (InterruptedException e) { - return ERROR_LOCK_INTERRUPTED.createResult(); - } - } else { - // This thread holds the lock already. Checks that this wasn't for a different context. - // If this is called by init, mContext will be null and so should sCurrentContext - // anyway - if (mContext != sCurrentContext) { - throw new IllegalStateException("Acquiring different scenes from same thread without releases"); - } - return SUCCESS.createResult(); - } - - return null; - } - - /** - * Cleans up the scene after an action. - */ - public void release() { - ReentrantLock lock = Bridge.getLock(); - - // with the use of finally blocks, it is possible to find ourself calling this - // without a successful call to prepareScene. This test makes sure that unlock() will - // not throw IllegalMonitorStateException. - if (lock.isHeldByCurrentThread()) { - tearDown(); - lock.unlock(); - } - } - - /** - * Sets up the session for rendering. - * <p/> - * The counterpart is {@link #tearDown()}. - */ - private void setUp() { - // make sure the Resources object references the context (and other objects) for this - // scene - mContext.initResources(); - sCurrentContext = mContext; - - // create an InputMethodManager - InputMethodManager.getInstance(); - - LayoutLog currentLog = mParams.getLog(); - Bridge.setLog(currentLog); - mContext.getRenderResources().setFrameworkResourceIdProvider(this); - mContext.getRenderResources().setLogger(currentLog); - } - - /** - * Tear down the session after rendering. - * <p/> - * The counterpart is {@link #setUp()}. - */ - private void tearDown() { - // Make sure to remove static references, otherwise we could not unload the lib - mContext.disposeResources(); - - // quit HandlerThread created during this session. - HandlerThread_Delegate.cleanUp(sCurrentContext); - - // clear the stored ViewConfiguration since the map is per density and not per context. - ViewConfiguration_Accessor.clearConfigurations(); - - // remove the InputMethodManager - InputMethodManager_Accessor.resetInstance(); - - sCurrentContext = null; - - Bridge.setLog(null); - mContext.getRenderResources().setFrameworkResourceIdProvider(null); - mContext.getRenderResources().setLogger(null); - } - - public static BridgeContext getCurrentContext() { - return sCurrentContext; - } - - protected T getParams() { - return mParams; - } - - protected BridgeContext getContext() { - return mContext; - } - - /** - * Returns the log associated with the session. - * @return the log or null if there are none. - */ - public LayoutLog getLog() { - if (mParams != null) { - return mParams.getLog(); - } - - return null; - } - - /** - * Checks that the lock is owned by the current thread and that the current context is the one - * from this scene. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - */ - protected void checkLock() { - ReentrantLock lock = Bridge.getLock(); - if (lock.isHeldByCurrentThread() == false) { - throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); - } - if (sCurrentContext != mContext) { - throw new IllegalStateException("Thread acquired a scene but is rendering a different one"); - } - } - - private Configuration getConfiguration() { - Configuration config = new Configuration(); - - HardwareConfig hardwareConfig = mParams.getHardwareConfig(); - - ScreenSize screenSize = hardwareConfig.getScreenSize(); - if (screenSize != null) { - switch (screenSize) { - case SMALL: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL; - break; - case NORMAL: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL; - break; - case LARGE: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE; - break; - case XLARGE: - config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE; - break; - } - } - - Density density = hardwareConfig.getDensity(); - if (density == null) { - density = Density.MEDIUM; - } - - config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue(); - config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue(); - if (config.screenHeightDp < config.screenWidthDp) { - config.smallestScreenWidthDp = config.screenHeightDp; - } else { - config.smallestScreenWidthDp = config.screenWidthDp; - } - config.densityDpi = density.getDpiValue(); - - // never run in compat mode: - config.compatScreenWidthDp = config.screenWidthDp; - config.compatScreenHeightDp = config.screenHeightDp; - - ScreenOrientation orientation = hardwareConfig.getOrientation(); - if (orientation != null) { - switch (orientation) { - case PORTRAIT: - config.orientation = Configuration.ORIENTATION_PORTRAIT; - break; - case LANDSCAPE: - config.orientation = Configuration.ORIENTATION_LANDSCAPE; - break; - case SQUARE: - config.orientation = Configuration.ORIENTATION_SQUARE; - break; - } - } else { - config.orientation = Configuration.ORIENTATION_UNDEFINED; - } - - // TODO: fill in more config info. - - return config; - } - - - // --- FrameworkResourceIdProvider methods - - @Override - public Integer getId(ResourceType resType, String resName) { - return Bridge.getResourceId(resType, resName); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java deleted file mode 100644 index b677131..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.impl; - -import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; - -import com.android.ide.common.rendering.api.DrawableParams; -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.resources.ResourceType; - -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.view.AttachInfo_Accessor; -import android.view.View.MeasureSpec; -import android.widget.FrameLayout; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.IOException; - -/** - * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}. - * - * The class only provides a simple {@link #render()} method, but the full life-cycle of the - * action must be respected. - * - * @see RenderAction - * - */ -public class RenderDrawable extends RenderAction<DrawableParams> { - - public RenderDrawable(DrawableParams params) { - super(new DrawableParams(params)); - } - - public Result render() { - checkLock(); - try { - // get the drawable resource value - DrawableParams params = getParams(); - HardwareConfig hardwareConfig = params.getHardwareConfig(); - ResourceValue drawableResource = params.getDrawable(); - - // resolve it - BridgeContext context = getContext(); - drawableResource = context.getRenderResources().resolveResValue(drawableResource); - - if (drawableResource == null || - drawableResource.getResourceType() != ResourceType.DRAWABLE) { - return Status.ERROR_NOT_A_DRAWABLE.createResult(); - } - - // create a simple FrameLayout - FrameLayout content = new FrameLayout(context); - - // get the actual Drawable object to draw - Drawable d = ResourceHelper.getDrawable(drawableResource, context); - content.setBackground(d); - - // set the AttachInfo on the root view. - AttachInfo_Accessor.setAttachInfo(content); - - - // measure - int w = hardwareConfig.getScreenWidth(); - int h = hardwareConfig.getScreenHeight(); - int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); - int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); - content.measure(w_spec, h_spec); - - // now do the layout. - content.layout(0, 0, w, h); - - // preDraw setup - AttachInfo_Accessor.dispatchOnPreDraw(content); - - // draw into a new image - BufferedImage image = getImage(w, h); - - // create an Android bitmap around the BufferedImage - Bitmap bitmap = Bitmap_Delegate.createBitmap(image, - true /*isMutable*/, hardwareConfig.getDensity()); - - // create a Canvas around the Android bitmap - Canvas canvas = new Canvas(bitmap); - canvas.setDensity(hardwareConfig.getDensity().getDpiValue()); - - // and draw - content.draw(canvas); - - return Status.SUCCESS.createResult(image); - } catch (IOException e) { - return ERROR_UNKNOWN.createResult(e.getMessage(), e); - } - } - - protected BufferedImage getImage(int w, int h) { - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D gc = image.createGraphics(); - gc.setComposite(AlphaComposite.Src); - - gc.setColor(new Color(0x00000000, true)); - gc.fillRect(0, 0, w, h); - - // done - gc.dispose(); - - return image; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java deleted file mode 100644 index 6011fdb..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ /dev/null @@ -1,1471 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.impl; - -import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; -import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.HardwareConfig; -import com.android.ide.common.rendering.api.IAnimationListener; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.RenderParams; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.ide.common.rendering.api.SessionParams.RenderingMode; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.internal.util.XmlUtils; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.bars.FakeActionBar; -import com.android.layoutlib.bridge.bars.NavigationBar; -import com.android.layoutlib.bridge.bars.StatusBar; -import com.android.layoutlib.bridge.bars.TitleBar; -import com.android.layoutlib.bridge.impl.binding.FakeAdapter; -import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; -import com.android.util.Pair; - -import org.xmlpull.v1.XmlPullParserException; - -import android.animation.AnimationThread; -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.animation.LayoutTransition; -import android.animation.LayoutTransition.TransitionListener; -import android.app.Fragment_Delegate; -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.AttachInfo_Accessor; -import android.view.BridgeInflater; -import android.view.IWindowManager; -import android.view.IWindowManagerImpl; -import android.view.Surface; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.view.ViewGroup.MarginLayoutParams; -import android.view.WindowManagerGlobal_Delegate; -import android.widget.AbsListView; -import android.widget.AbsSpinner; -import android.widget.AdapterView; -import android.widget.ExpandableListView; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.QuickContactBadge; -import android.widget.TabHost; -import android.widget.TabHost.TabSpec; -import android.widget.TabWidget; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Class implementing the render session. - * - * A session is a stateful representation of a layout file. It is initialized with data coming - * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then - * be done on the layout. - * - */ -public class RenderSessionImpl extends RenderAction<SessionParams> { - - private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; - private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; - - // scene state - private RenderSession mScene; - private BridgeXmlBlockParser mBlockParser; - private BridgeInflater mInflater; - private ResourceValue mWindowBackground; - private ViewGroup mViewRoot; - private FrameLayout mContentRoot; - private Canvas mCanvas; - private int mMeasuredScreenWidth = -1; - private int mMeasuredScreenHeight = -1; - private boolean mIsAlphaChannelImage; - private boolean mWindowIsFloating; - - private int mStatusBarSize; - private int mNavigationBarSize; - private int mNavigationBarOrientation = LinearLayout.HORIZONTAL; - private int mTitleBarSize; - private int mActionBarSize; - - - // information being returned through the API - private BufferedImage mImage; - private List<ViewInfo> mViewInfoList; - - private static final class PostInflateException extends Exception { - private static final long serialVersionUID = 1L; - - public PostInflateException(String message) { - super(message); - } - } - - /** - * Creates a layout scene with all the information coming from the layout bridge API. - * <p> - * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a - * call to {@link RenderSessionImpl#acquire(long)} - * - * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams) - */ - public RenderSessionImpl(SessionParams params) { - super(new SessionParams(params)); - } - - /** - * Initializes and acquires the scene, creating various Android objects such as context, - * inflater, and parser. - * - * @param timeout the time to wait if another rendering is happening. - * - * @return whether the scene was prepared - * - * @see #acquire(long) - * @see #release() - */ - @Override - public Result init(long timeout) { - Result result = super.init(timeout); - if (result.isSuccess() == false) { - return result; - } - - SessionParams params = getParams(); - BridgeContext context = getContext(); - - RenderResources resources = getParams().getResources(); - DisplayMetrics metrics = getContext().getMetrics(); - - // use default of true in case it's not found to use alpha by default - mIsAlphaChannelImage = getBooleanThemeValue(resources, - "windowIsFloating", true /*defaultValue*/); - - mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating", - true /*defaultValue*/); - - findBackground(resources); - findStatusBar(resources, metrics); - findActionBar(resources, metrics); - findNavigationBar(resources, metrics); - - // FIXME: find those out, and possibly add them to the render params - boolean hasNavigationBar = true; - IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), - metrics, Surface.ROTATION_0, - hasNavigationBar); - WindowManagerGlobal_Delegate.setWindowManagerService(iwm); - - // build the inflater and parser. - mInflater = new BridgeInflater(context, params.getProjectCallback()); - context.setBridgeInflater(mInflater); - - mBlockParser = new BridgeXmlBlockParser( - params.getLayoutDescription(), context, false /* platformResourceFlag */); - - return SUCCESS.createResult(); - } - - /** - * Inflates the layout. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #init(long)} was not called. - */ - public Result inflate() { - checkLock(); - - try { - - SessionParams params = getParams(); - HardwareConfig hardwareConfig = params.getHardwareConfig(); - BridgeContext context = getContext(); - - - // the view group that receives the window background. - ViewGroup backgroundView = null; - - if (mWindowIsFloating || params.isForceNoDecor()) { - backgroundView = mViewRoot = mContentRoot = new FrameLayout(context); - } else { - if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) { - /* - * This is a special case where the navigation bar is on the right. - +-------------------------------------------------+---+ - | Status bar (always) | | - +-------------------------------------------------+ | - | (Layout with background drawable) | | - | +---------------------------------------------+ | | - | | Title/Action bar (optional) | | | - | +---------------------------------------------+ | | - | | Content, vertical extending | | | - | | | | | - | +---------------------------------------------+ | | - +-------------------------------------------------+---+ - - So we create a horizontal layout, with the nav bar on the right, - and the left part is the normal layout below without the nav bar at - the bottom - */ - LinearLayout topLayout = new LinearLayout(context); - mViewRoot = topLayout; - topLayout.setOrientation(LinearLayout.HORIZONTAL); - - try { - NavigationBar navigationBar = new NavigationBar(context, - hardwareConfig.getDensity(), LinearLayout.VERTICAL); - navigationBar.setLayoutParams( - new LinearLayout.LayoutParams( - mNavigationBarSize, - LayoutParams.MATCH_PARENT)); - topLayout.addView(navigationBar); - } catch (XmlPullParserException e) { - - } - } - - /* - * we're creating the following layout - * - +-------------------------------------------------+ - | Status bar (always) | - +-------------------------------------------------+ - | (Layout with background drawable) | - | +---------------------------------------------+ | - | | Title/Action bar (optional) | | - | +---------------------------------------------+ | - | | Content, vertical extending | | - | | | | - | +---------------------------------------------+ | - +-------------------------------------------------+ - | Navigation bar for soft buttons, maybe see above| - +-------------------------------------------------+ - - */ - - LinearLayout topLayout = new LinearLayout(context); - topLayout.setOrientation(LinearLayout.VERTICAL); - // if we don't already have a view root this is it - if (mViewRoot == null) { - mViewRoot = topLayout; - } else { - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); - layoutParams.weight = 1; - topLayout.setLayoutParams(layoutParams); - - // this is the case of soft buttons + vertical bar. - // this top layout is the first layout in the horizontal layout. see above) - mViewRoot.addView(topLayout, 0); - } - - if (mStatusBarSize > 0) { - // system bar - try { - StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity()); - systemBar.setLayoutParams( - new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, mStatusBarSize)); - topLayout.addView(systemBar); - } catch (XmlPullParserException e) { - - } - } - - LinearLayout backgroundLayout = new LinearLayout(context); - backgroundView = backgroundLayout; - backgroundLayout.setOrientation(LinearLayout.VERTICAL); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - layoutParams.weight = 1; - backgroundLayout.setLayoutParams(layoutParams); - topLayout.addView(backgroundLayout); - - - // if the theme says no title/action bar, then the size will be 0 - if (mActionBarSize > 0) { - try { - FakeActionBar actionBar = new FakeActionBar(context, - hardwareConfig.getDensity(), - params.getAppLabel(), params.getAppIcon()); - actionBar.setLayoutParams( - new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, mActionBarSize)); - backgroundLayout.addView(actionBar); - } catch (XmlPullParserException e) { - - } - } else if (mTitleBarSize > 0) { - try { - TitleBar titleBar = new TitleBar(context, - hardwareConfig.getDensity(), params.getAppLabel()); - titleBar.setLayoutParams( - new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, mTitleBarSize)); - backgroundLayout.addView(titleBar); - } catch (XmlPullParserException e) { - - } - } - - // content frame - mContentRoot = new FrameLayout(context); - layoutParams = new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - layoutParams.weight = 1; - mContentRoot.setLayoutParams(layoutParams); - backgroundLayout.addView(mContentRoot); - - if (mNavigationBarOrientation == LinearLayout.HORIZONTAL && - mNavigationBarSize > 0) { - // system bar - try { - NavigationBar navigationBar = new NavigationBar(context, - hardwareConfig.getDensity(), LinearLayout.HORIZONTAL); - navigationBar.setLayoutParams( - new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, mNavigationBarSize)); - topLayout.addView(navigationBar); - } catch (XmlPullParserException e) { - - } - } - } - - - // Sets the project callback (custom view loader) to the fragment delegate so that - // it can instantiate the custom Fragment. - Fragment_Delegate.setProjectCallback(params.getProjectCallback()); - - View view = mInflater.inflate(mBlockParser, mContentRoot); - - // done with the parser, pop it. - context.popParser(); - - Fragment_Delegate.setProjectCallback(null); - - // set the AttachInfo on the root view. - AttachInfo_Accessor.setAttachInfo(mViewRoot); - - // post-inflate process. For now this supports TabHost/TabWidget - postInflateProcess(view, params.getProjectCallback()); - - // get the background drawable - if (mWindowBackground != null && backgroundView != null) { - Drawable d = ResourceHelper.getDrawable(mWindowBackground, context); - backgroundView.setBackground(d); - } - - return SUCCESS.createResult(); - } catch (PostInflateException e) { - return ERROR_INFLATION.createResult(e.getMessage(), e); - } catch (Throwable e) { - // get the real cause of the exception. - Throwable t = e; - while (t.getCause() != null) { - t = t.getCause(); - } - - return ERROR_INFLATION.createResult(t.getMessage(), t); - } - } - - /** - * Renders the scene. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @param freshRender whether the render is a new one and should erase the existing bitmap (in - * the case where bitmaps are reused). This is typically needed when not playing - * animations.) - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderParams#getRenderingMode() - * @see RenderSession#render(long) - */ - public Result render(boolean freshRender) { - checkLock(); - - SessionParams params = getParams(); - - try { - if (mViewRoot == null) { - return ERROR_NOT_INFLATED.createResult(); - } - - RenderingMode renderingMode = params.getRenderingMode(); - HardwareConfig hardwareConfig = params.getHardwareConfig(); - - // only do the screen measure when needed. - boolean newRenderSize = false; - if (mMeasuredScreenWidth == -1) { - newRenderSize = true; - mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); - mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); - - if (renderingMode != RenderingMode.NORMAL) { - int widthMeasureSpecMode = renderingMode.isHorizExpand() ? - MeasureSpec.UNSPECIFIED // this lets us know the actual needed size - : MeasureSpec.EXACTLY; - int heightMeasureSpecMode = renderingMode.isVertExpand() ? - MeasureSpec.UNSPECIFIED // this lets us know the actual needed size - : MeasureSpec.EXACTLY; - - // We used to compare the measured size of the content to the screen size but - // this does not work anymore due to the 2 following issues: - // - If the content is in a decor (system bar, title/action bar), the root view - // will not resize even with the UNSPECIFIED because of the embedded layout. - // - If there is no decor, but a dialog frame, then the dialog padding prevents - // comparing the size of the content to the screen frame (as it would not - // take into account the dialog padding). - - // The solution is to first get the content size in a normal rendering, inside - // the decor or the dialog padding. - // Then measure only the content with UNSPECIFIED to see the size difference - // and apply this to the screen size. - - // first measure the full layout, with EXACTLY to get the size of the - // content as it is inside the decor/dialog - Pair<Integer, Integer> exactMeasure = measureView( - mViewRoot, mContentRoot.getChildAt(0), - mMeasuredScreenWidth, MeasureSpec.EXACTLY, - mMeasuredScreenHeight, MeasureSpec.EXACTLY); - - // now measure the content only using UNSPECIFIED (where applicable, based on - // the rendering mode). This will give us the size the content needs. - Pair<Integer, Integer> result = measureView( - mContentRoot, mContentRoot.getChildAt(0), - mMeasuredScreenWidth, widthMeasureSpecMode, - mMeasuredScreenHeight, heightMeasureSpecMode); - - // now look at the difference and add what is needed. - if (renderingMode.isHorizExpand()) { - int measuredWidth = exactMeasure.getFirst(); - int neededWidth = result.getFirst(); - if (neededWidth > measuredWidth) { - mMeasuredScreenWidth += neededWidth - measuredWidth; - } - } - - if (renderingMode.isVertExpand()) { - int measuredHeight = exactMeasure.getSecond(); - int neededHeight = result.getSecond(); - if (neededHeight > measuredHeight) { - mMeasuredScreenHeight += neededHeight - measuredHeight; - } - } - } - } - - // measure again with the size we need - // This must always be done before the call to layout - measureView(mViewRoot, null /*measuredView*/, - mMeasuredScreenWidth, MeasureSpec.EXACTLY, - mMeasuredScreenHeight, MeasureSpec.EXACTLY); - - // now do the layout. - mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); - - if (params.isLayoutOnly()) { - // delete the canvas and image to reset them on the next full rendering - mImage = null; - mCanvas = null; - } else { - AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot); - - // draw the views - // create the BufferedImage into which the layout will be rendered. - boolean newImage = false; - if (newRenderSize || mCanvas == null) { - if (params.getImageFactory() != null) { - mImage = params.getImageFactory().getImage( - mMeasuredScreenWidth, - mMeasuredScreenHeight); - } else { - mImage = new BufferedImage( - mMeasuredScreenWidth, - mMeasuredScreenHeight, - BufferedImage.TYPE_INT_ARGB); - newImage = true; - } - - if (params.isBgColorOverridden()) { - // since we override the content, it's the same as if it was a new image. - newImage = true; - Graphics2D gc = mImage.createGraphics(); - gc.setColor(new Color(params.getOverrideBgColor(), true)); - gc.setComposite(AlphaComposite.Src); - gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); - gc.dispose(); - } - - // create an Android bitmap around the BufferedImage - Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, - true /*isMutable*/, hardwareConfig.getDensity()); - - // create a Canvas around the Android bitmap - mCanvas = new Canvas(bitmap); - mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); - } - - if (freshRender && newImage == false) { - Graphics2D gc = mImage.createGraphics(); - gc.setComposite(AlphaComposite.Src); - - gc.setColor(new Color(0x00000000, true)); - gc.fillRect(0, 0, - mMeasuredScreenWidth, mMeasuredScreenHeight); - - // done - gc.dispose(); - } - - mViewRoot.draw(mCanvas); - } - - mViewInfoList = startVisitingViews(mViewRoot, 0, params.getExtendedViewInfoMode()); - - // success! - return SUCCESS.createResult(); - } catch (Throwable e) { - // get the real cause of the exception. - Throwable t = e; - while (t.getCause() != null) { - t = t.getCause(); - } - - return ERROR_UNKNOWN.createResult(t.getMessage(), t); - } - } - - /** - * Executes {@link View#measure(int, int)} on a given view with the given parameters (used - * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}. - * - * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height) - * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}). - * - * @param viewToMeasure the view on which to execute measure(). - * @param measuredView if non null, the view to query for its measured width/height. - * @param width the width to use in the MeasureSpec. - * @param widthMode the MeasureSpec mode to use for the width. - * @param height the height to use in the MeasureSpec. - * @param heightMode the MeasureSpec mode to use for the height. - * @return the measured width/height if measuredView is non-null, null otherwise. - */ - private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView, - int width, int widthMode, int height, int heightMode) { - int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode); - int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode); - viewToMeasure.measure(w_spec, h_spec); - - if (measuredView != null) { - return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight()); - } - - return null; - } - - /** - * Animate an object - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#animate(Object, String, boolean, IAnimationListener) - */ - public Result animate(Object targetObject, String animationName, - boolean isFrameworkAnimation, IAnimationListener listener) { - checkLock(); - - BridgeContext context = getContext(); - - // find the animation file. - ResourceValue animationResource = null; - int animationId = 0; - if (isFrameworkAnimation) { - animationResource = context.getRenderResources().getFrameworkResource( - ResourceType.ANIMATOR, animationName); - if (animationResource != null) { - animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); - } - } else { - animationResource = context.getRenderResources().getProjectResource( - ResourceType.ANIMATOR, animationName); - if (animationResource != null) { - animationId = context.getProjectCallback().getResourceId( - ResourceType.ANIMATOR, animationName); - } - } - - if (animationResource != null) { - try { - Animator anim = AnimatorInflater.loadAnimator(context, animationId); - if (anim != null) { - anim.setTarget(targetObject); - - new PlayAnimationThread(anim, this, animationName, listener).start(); - - return SUCCESS.createResult(); - } - } catch (Exception e) { - // get the real cause of the exception. - Throwable t = e; - while (t.getCause() != null) { - t = t.getCause(); - } - - return ERROR_UNKNOWN.createResult(t.getMessage(), t); - } - } - - return ERROR_ANIM_NOT_FOUND.createResult(); - } - - /** - * Insert a new child into an existing parent. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) - */ - public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, - final int index, IAnimationListener listener) { - checkLock(); - - BridgeContext context = getContext(); - - // create a block parser for the XML - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - childXml, context, false /* platformResourceFlag */); - - // inflate the child without adding it to the root since we want to control where it'll - // get added. We do pass the parentView however to ensure that the layoutParams will - // be created correctly. - final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); - blockParser.ensurePopped(); - - invalidateRenderingSize(); - - if (listener != null) { - new AnimationThread(this, "insertChild", listener) { - - @Override - public Result preAnimation() { - parentView.setLayoutTransition(new LayoutTransition()); - return addView(parentView, child, index); - } - - @Override - public void postAnimation() { - parentView.setLayoutTransition(null); - } - }.start(); - - // always return success since the real status will come through the listener. - return SUCCESS.createResult(child); - } - - // add it to the parentView in the correct location - Result result = addView(parentView, child, index); - if (result.isSuccess() == false) { - return result; - } - - result = render(false /*freshRender*/); - if (result.isSuccess()) { - result = result.getCopyWithData(child); - } - - return result; - } - - /** - * Adds a given view to a given parent at a given index. - * - * @param parent the parent to receive the view - * @param view the view to add to the parent - * @param index the index where to do the add. - * - * @return a Result with {@link Status#SUCCESS} or - * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support - * adding views. - */ - private Result addView(ViewGroup parent, View view, int index) { - try { - parent.addView(view, index); - return SUCCESS.createResult(); - } catch (UnsupportedOperationException e) { - // looks like this is a view class that doesn't support children manipulation! - return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); - } - } - - /** - * Moves a view to a new parent at a given location - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) - */ - public Result moveChild(final ViewGroup newParentView, final View childView, final int index, - Map<String, String> layoutParamsMap, final IAnimationListener listener) { - checkLock(); - - invalidateRenderingSize(); - - LayoutParams layoutParams = null; - if (layoutParamsMap != null) { - // need to create a new LayoutParams object for the new parent. - layoutParams = newParentView.generateLayoutParams( - new BridgeLayoutParamsMapAttributes(layoutParamsMap)); - } - - // get the current parent of the view that needs to be moved. - final ViewGroup previousParent = (ViewGroup) childView.getParent(); - - if (listener != null) { - final LayoutParams params = layoutParams; - - // there is no support for animating views across layouts, so in case the new and old - // parent views are different we fake the animation through a no animation thread. - if (previousParent != newParentView) { - new Thread("not animated moveChild") { - @Override - public void run() { - Result result = moveView(previousParent, newParentView, childView, index, - params); - if (result.isSuccess() == false) { - listener.done(result); - } - - // ready to do the work, acquire the scene. - result = acquire(250); - if (result.isSuccess() == false) { - listener.done(result); - return; - } - - try { - result = render(false /*freshRender*/); - if (result.isSuccess()) { - listener.onNewFrame(RenderSessionImpl.this.getSession()); - } - } finally { - release(); - } - - listener.done(result); - } - }.start(); - } else { - new AnimationThread(this, "moveChild", listener) { - - @Override - public Result preAnimation() { - // set up the transition for the parent. - LayoutTransition transition = new LayoutTransition(); - previousParent.setLayoutTransition(transition); - - // tweak the animation durations and start delays (to match the duration of - // animation playing just before). - // Note: Cannot user Animation.setDuration() directly. Have to set it - // on the LayoutTransition. - transition.setDuration(LayoutTransition.DISAPPEARING, 100); - // CHANGE_DISAPPEARING plays after DISAPPEARING - transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); - - transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); - - transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); - // CHANGE_APPEARING plays after CHANGE_APPEARING - transition.setStartDelay(LayoutTransition.APPEARING, 100); - - transition.setDuration(LayoutTransition.APPEARING, 100); - - return moveView(previousParent, newParentView, childView, index, params); - } - - @Override - public void postAnimation() { - previousParent.setLayoutTransition(null); - newParentView.setLayoutTransition(null); - } - }.start(); - } - - // always return success since the real status will come through the listener. - return SUCCESS.createResult(layoutParams); - } - - Result result = moveView(previousParent, newParentView, childView, index, layoutParams); - if (result.isSuccess() == false) { - return result; - } - - result = render(false /*freshRender*/); - if (layoutParams != null && result.isSuccess()) { - result = result.getCopyWithData(layoutParams); - } - - return result; - } - - /** - * Moves a View from its current parent to a new given parent at a new given location, with - * an optional new {@link LayoutParams} instance - * - * @param previousParent the previous parent, still owning the child at the time of the call. - * @param newParent the new parent - * @param movedView the view to move - * @param index the new location in the new parent - * @param params an option (can be null) {@link LayoutParams} instance. - * - * @return a Result with {@link Status#SUCCESS} or - * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support - * adding views. - */ - private Result moveView(ViewGroup previousParent, final ViewGroup newParent, - final View movedView, final int index, final LayoutParams params) { - try { - // check if there is a transition on the previousParent. - LayoutTransition previousTransition = previousParent.getLayoutTransition(); - if (previousTransition != null) { - // in this case there is an animation. This means we have to wait for the child's - // parent reference to be null'ed out so that we can add it to the new parent. - // It is technically removed right before the DISAPPEARING animation is done (if - // the animation of this type is not null, otherwise it's after which is impossible - // to handle). - // Because there is no move animation, if the new parent is the same as the old - // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before - // adding the child or the child will appear in its new location before the - // other children have made room for it. - - // add a listener to the transition to be notified of the actual removal. - previousTransition.addTransitionListener(new TransitionListener() { - private int mChangeDisappearingCount = 0; - - @Override - public void startTransition(LayoutTransition transition, ViewGroup container, - View view, int transitionType) { - if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { - mChangeDisappearingCount++; - } - } - - @Override - public void endTransition(LayoutTransition transition, ViewGroup container, - View view, int transitionType) { - if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { - mChangeDisappearingCount--; - } - - if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && - mChangeDisappearingCount == 0) { - // add it to the parentView in the correct location - if (params != null) { - newParent.addView(movedView, index, params); - } else { - newParent.addView(movedView, index); - } - } - } - }); - - // remove the view from the current parent. - previousParent.removeView(movedView); - - // and return since adding the view to the new parent is done in the listener. - return SUCCESS.createResult(); - } else { - // standard code with no animation. pretty simple. - previousParent.removeView(movedView); - - // add it to the parentView in the correct location - if (params != null) { - newParent.addView(movedView, index, params); - } else { - newParent.addView(movedView, index); - } - - return SUCCESS.createResult(); - } - } catch (UnsupportedOperationException e) { - // looks like this is a view class that doesn't support children manipulation! - return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); - } - } - - /** - * Removes a child from its current parent. - * <p> - * {@link #acquire(long)} must have been called before this. - * - * @throws IllegalStateException if the current context is different than the one owned by - * the scene, or if {@link #acquire(long)} was not called. - * - * @see RenderSession#removeChild(Object, IAnimationListener) - */ - public Result removeChild(final View childView, IAnimationListener listener) { - checkLock(); - - invalidateRenderingSize(); - - final ViewGroup parent = (ViewGroup) childView.getParent(); - - if (listener != null) { - new AnimationThread(this, "moveChild", listener) { - - @Override - public Result preAnimation() { - parent.setLayoutTransition(new LayoutTransition()); - return removeView(parent, childView); - } - - @Override - public void postAnimation() { - parent.setLayoutTransition(null); - } - }.start(); - - // always return success since the real status will come through the listener. - return SUCCESS.createResult(); - } - - Result result = removeView(parent, childView); - if (result.isSuccess() == false) { - return result; - } - - return render(false /*freshRender*/); - } - - /** - * Removes a given view from its current parent. - * - * @param view the view to remove from its parent - * - * @return a Result with {@link Status#SUCCESS} or - * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support - * adding views. - */ - private Result removeView(ViewGroup parent, View view) { - try { - parent.removeView(view); - return SUCCESS.createResult(); - } catch (UnsupportedOperationException e) { - // looks like this is a view class that doesn't support children manipulation! - return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); - } - } - - - private void findBackground(RenderResources resources) { - if (getParams().isBgColorOverridden() == false) { - mWindowBackground = resources.findItemInTheme("windowBackground", - true /*isFrameworkAttr*/); - if (mWindowBackground != null) { - mWindowBackground = resources.resolveResValue(mWindowBackground); - } - } - } - - private boolean hasSoftwareButtons() { - return getParams().getHardwareConfig().hasSoftwareButtons(); - } - - private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { - boolean windowFullscreen = getBooleanThemeValue(resources, - "windowFullscreen", false /*defaultValue*/); - - if (windowFullscreen == false && mWindowIsFloating == false) { - // default value - mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; - - // get the real value - ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, - "status_bar_height"); - - if (value != null) { - TypedValue typedValue = ResourceHelper.getValue("status_bar_height", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mStatusBarSize = (int)typedValue.getDimension(metrics); - } - } - } - } - - private void findActionBar(RenderResources resources, DisplayMetrics metrics) { - if (mWindowIsFloating) { - return; - } - - boolean windowActionBar = getBooleanThemeValue(resources, - "windowActionBar", true /*defaultValue*/); - - // if there's a value and it's false (default is true) - if (windowActionBar) { - - // default size of the window title bar - mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT; - - // get value from the theme. - ResourceValue value = resources.findItemInTheme("actionBarSize", - true /*isFrameworkAttr*/); - - // resolve it - value = resources.resolveResValue(value); - - if (value != null) { - // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(), - true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mActionBarSize = (int)typedValue.getDimension(metrics); - } - } - } else { - // action bar overrides title bar so only look for this one if action bar is hidden - boolean windowNoTitle = getBooleanThemeValue(resources, - "windowNoTitle", false /*defaultValue*/); - - if (windowNoTitle == false) { - - // default size of the window title bar - mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT; - - // get value from the theme. - ResourceValue value = resources.findItemInTheme("windowTitleSize", - true /*isFrameworkAttr*/); - - // resolve it - value = resources.resolveResValue(value); - - if (value != null) { - // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue("windowTitleSize", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mTitleBarSize = (int)typedValue.getDimension(metrics); - } - } - } - - } - } - - private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) { - if (hasSoftwareButtons() && mWindowIsFloating == false) { - - // default value - mNavigationBarSize = 48; // ?? - - HardwareConfig hardwareConfig = getParams().getHardwareConfig(); - - boolean barOnBottom = true; - - if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) { - // compute the dp of the screen. - int shortSize = hardwareConfig.getScreenHeight(); - - // compute in dp - int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue(); - - if (shortSizeDp < 600) { - // 0-599dp: "phone" UI with bar on the side - barOnBottom = false; - } else { - // 600+dp: "tablet" UI with bar on the bottom - barOnBottom = true; - } - } - - if (barOnBottom) { - mNavigationBarOrientation = LinearLayout.HORIZONTAL; - } else { - mNavigationBarOrientation = LinearLayout.VERTICAL; - } - - // get the real value - ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, - barOnBottom ? "navigation_bar_height" : "navigation_bar_width"); - - if (value != null) { - TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mNavigationBarSize = (int)typedValue.getDimension(metrics); - } - } - } - } - - /** - * Looks for a attribute in the current theme. The attribute is in the android - * namespace. - * - * @param resources the render resources - * @param name the name of the attribute - * @param defaultValue the default value. - * @return the value of the attribute or the default one if not found. - */ - private boolean getBooleanThemeValue(RenderResources resources, - String name, boolean defaultValue) { - - // get the title bar flag from the current theme. - ResourceValue value = resources.findItemInTheme(name, true /*isFrameworkAttr*/); - - // because it may reference something else, we resolve it. - value = resources.resolveResValue(value); - - // if there's no value, return the default. - if (value == null || value.getValue() == null) { - return defaultValue; - } - - return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); - } - - /** - * 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 QuickContactBadge) { - QuickContactBadge badge = (QuickContactBadge) view; - badge.setImageToDefault(); - } else if (view instanceof AdapterView<?>) { - // get the view ID. - int id = view.getId(); - - BridgeContext context = getContext(); - - // get a ResourceReference from the integer ID. - ResourceReference listRef = context.resolveId(id); - - if (listRef != null) { - SessionParams params = getParams(); - AdapterBinding binding = params.getAdapterBindings().get(listRef); - - // if there was no adapter binding, trying to get it from the call back. - if (binding == null) { - binding = params.getProjectCallback().getAdapterBinding(listRef, - context.getViewKey(view), view); - } - - if (binding != null) { - - if (view instanceof AbsListView) { - if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) && - view instanceof ListView) { - ListView list = (ListView) view; - - boolean skipCallbackParser = false; - - int count = binding.getHeaderCount(); - for (int i = 0 ; i < count ; i++) { - Pair<View, Boolean> pair = context.inflateView( - binding.getHeaderAt(i), - list, false /*attachToRoot*/, skipCallbackParser); - if (pair.getFirst() != null) { - list.addHeaderView(pair.getFirst()); - } - - skipCallbackParser |= pair.getSecond(); - } - - count = binding.getFooterCount(); - for (int i = 0 ; i < count ; i++) { - Pair<View, Boolean> pair = context.inflateView( - binding.getFooterAt(i), - list, false /*attachToRoot*/, skipCallbackParser); - if (pair.getFirst() != null) { - list.addFooterView(pair.getFirst()); - } - - skipCallbackParser |= pair.getSecond(); - } - } - - if (view instanceof ExpandableListView) { - ((ExpandableListView) view).setAdapter( - new FakeExpandableAdapter( - listRef, binding, params.getProjectCallback())); - } else { - ((AbsListView) view).setAdapter( - new FakeAdapter( - listRef, binding, params.getProjectCallback())); - } - } else if (view instanceof AbsSpinner) { - ((AbsSpinner) view).setAdapter( - new FakeAdapter( - listRef, binding, params.getProjectCallback())); - } - } - } - } 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(); - - // this must be called before addTab() so that the TabHost searches its TabWidget - // and FrameLayout. - tabHost.setup(); - - if (count == 0) { - // Create a dummy child to get a single tab - TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label", - tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details)) - .setContent(new TabHost.TabContentFactory() { - @Override - public View createTabContent(String tag) { - return new LinearLayout(getContext()); - } - }); - tabHost.addTab(spec); - return; - } else { - // 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(); - Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id); - String name; - if (resource != null) { - name = resource.getSecond(); - } else { - name = String.format("Tab %d", i+1); // default name if id is unresolved. - } - tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); - } - } - } - - private List<ViewInfo> startVisitingViews(View view, int offset, boolean setExtendedInfo) { - if (view == null) { - return null; - } - - // adjust the offset to this view. - offset += view.getTop(); - - if (view == mContentRoot) { - return visitAllChildren(mContentRoot, offset, setExtendedInfo); - } - - // otherwise, look for mContentRoot in the children - if (view instanceof ViewGroup) { - ViewGroup group = ((ViewGroup) view); - - for (int i = 0; i < group.getChildCount(); i++) { - List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset, - setExtendedInfo); - if (list != null) { - return list; - } - } - } - - return null; - } - - /** - * Visits a View and its children and generate a {@link ViewInfo} containing the - * bounds of all the views. - * @param view the root View - * @param offset an offset for the view bounds. - * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. - */ - private ViewInfo visit(View view, int offset, boolean setExtendedInfo) { - if (view == null) { - return null; - } - - ViewInfo result = new ViewInfo(view.getClass().getName(), - getContext().getViewKey(view), - view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset, - view, view.getLayoutParams()); - - if (setExtendedInfo) { - MarginLayoutParams marginParams = null; - LayoutParams params = view.getLayoutParams(); - if (params instanceof MarginLayoutParams) { - marginParams = (MarginLayoutParams) params; - } - result.setExtendedInfo(view.getBaseline(), - marginParams != null ? marginParams.leftMargin : 0, - marginParams != null ? marginParams.topMargin : 0, - marginParams != null ? marginParams.rightMargin : 0, - marginParams != null ? marginParams.bottomMargin : 0); - } - - if (view instanceof ViewGroup) { - ViewGroup group = ((ViewGroup) view); - result.setChildren(visitAllChildren(group, 0 /*offset*/, setExtendedInfo)); - } - - return result; - } - - /** - * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo} - * containing the bounds of all the views. - * @param view the root View - * @param offset an offset for the view bounds. - * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object. - */ - private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset, - boolean setExtendedInfo) { - if (viewGroup == null) { - return null; - } - - List<ViewInfo> children = new ArrayList<ViewInfo>(); - for (int i = 0; i < viewGroup.getChildCount(); i++) { - children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo)); - } - return children; - } - - - private void invalidateRenderingSize() { - mMeasuredScreenWidth = mMeasuredScreenHeight = -1; - } - - public BufferedImage getImage() { - return mImage; - } - - public boolean isAlphaChannelImage() { - return mIsAlphaChannelImage; - } - - public List<ViewInfo> getViewInfos() { - return mViewInfoList; - } - - public Map<String, String> getDefaultProperties(Object viewObject) { - return getContext().getDefaultPropMap(viewObject); - } - - public void setScene(RenderSession session) { - mScene = session; - } - - public RenderSession getSession() { - return mScene; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java deleted file mode 100644 index 6dcb693..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge.impl; - -import com.android.ide.common.rendering.api.DensityBasedResourceValue; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.ninepatch.NinePatch; -import com.android.ninepatch.NinePatchChunk; -import com.android.resources.Density; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.res.ColorStateList; -import android.graphics.Bitmap; -import android.graphics.Bitmap_Delegate; -import android.graphics.NinePatch_Delegate; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.NinePatchDrawable; -import android.util.TypedValue; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Helper class to provide various conversion method used in handling android resources. - */ -public final class ResourceHelper { - - private final static Pattern sFloatPattern = Pattern.compile("(-?[0-9]+(?:\\.[0-9]+)?)(.*)"); - private final static float[] sFloatOut = new float[1]; - - private final static TypedValue mValue = new TypedValue(); - - /** - * Returns the color value represented by the given string value - * @param value the color value - * @return the color as an int - * @throw NumberFormatException if the conversion failed. - */ - public static int getColor(String value) { - if (value != null) { - if (value.startsWith("#") == false) { - throw new NumberFormatException( - String.format("Color value '%s' must start with #", value)); - } - - value = value.substring(1); - - // make sure it's not longer than 32bit - if (value.length() > 8) { - throw new NumberFormatException(String.format( - "Color value '%s' is too long. Format is either" + - "#AARRGGBB, #RRGGBB, #RGB, or #ARGB", - value)); - } - - if (value.length() == 3) { // RGB format - char[] color = new char[8]; - color[0] = color[1] = 'F'; - color[2] = color[3] = value.charAt(0); - color[4] = color[5] = value.charAt(1); - color[6] = color[7] = value.charAt(2); - value = new String(color); - } else if (value.length() == 4) { // ARGB format - char[] color = new char[8]; - color[0] = color[1] = value.charAt(0); - color[2] = color[3] = value.charAt(1); - color[4] = color[5] = value.charAt(2); - color[6] = color[7] = value.charAt(3); - value = new String(color); - } else if (value.length() == 6) { - value = "FF" + value; - } - - // this is a RRGGBB or AARRGGBB value - - // Integer.parseInt will fail to parse strings like "ff191919", so we use - // a Long, but cast the result back into an int, since we know that we're only - // dealing with 32 bit values. - return (int)Long.parseLong(value, 16); - } - - throw new NumberFormatException(); - } - - public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) { - String value = resValue.getValue(); - if (value != null && RenderResources.REFERENCE_NULL.equals(value) == false) { - // first check if the value is a file (xml most likely) - File f = new File(value); - if (f.isFile()) { - try { - // let the framework inflate the ColorStateList from the XML file, by - // providing an XmlPullParser - XmlPullParser parser = ParserFactory.create(f); - - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - parser, context, resValue.isFramework()); - try { - return ColorStateList.createFromXml(context.getResources(), blockParser); - } finally { - blockParser.ensurePopped(); - } - } catch (XmlPullParserException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to configure parser for " + value, e, null /*data*/); - // we'll return null below. - } catch (Exception e) { - // this is an error and not warning since the file existence is - // checked before attempting to parse it. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed to parse file " + value, e, null /*data*/); - - return null; - } - } else { - // try to load the color state list from an int - try { - int color = ResourceHelper.getColor(value); - return ColorStateList.valueOf(color); - } catch (NumberFormatException e) { - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Failed to convert " + value + " into a ColorStateList", e, - null /*data*/); - return null; - } - } - } - - return null; - } - - /** - * Returns a drawable from the given value. - * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable, - * or an hexadecimal color - * @param context the current context - */ - public static Drawable getDrawable(ResourceValue value, BridgeContext context) { - String stringValue = value.getValue(); - if (RenderResources.REFERENCE_NULL.equals(stringValue)) { - return null; - } - - String lowerCaseValue = stringValue.toLowerCase(); - - Density density = Density.MEDIUM; - if (value instanceof DensityBasedResourceValue) { - density = - ((DensityBasedResourceValue)value).getResourceDensity(); - } - - - if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { - File file = new File(stringValue); - if (file.isFile()) { - try { - return getNinePatchDrawable( - new FileInputStream(file), density, value.isFramework(), - stringValue, context); - } catch (IOException e) { - // failed to read the file, we'll return null below. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); - } - } - - return null; - } else if (lowerCaseValue.endsWith(".xml")) { - // create a block parser for the file - File f = new File(stringValue); - if (f.isFile()) { - try { - // let the framework inflate the Drawable from the XML file. - XmlPullParser parser = ParserFactory.create(f); - - BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( - parser, context, value.isFramework()); - try { - return Drawable.createFromXml(context.getResources(), blockParser); - } finally { - blockParser.ensurePopped(); - } - } catch (Exception e) { - // this is an error and not warning since the file existence is checked before - // attempting to parse it. - Bridge.getLog().error(null, "Failed to parse file " + stringValue, - e, null /*data*/); - } - } else { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("File %s does not exist (or is not a file)", stringValue), - null /*data*/); - } - - return null; - } else { - File bmpFile = new File(stringValue); - if (bmpFile.isFile()) { - try { - Bitmap bitmap = Bridge.getCachedBitmap(stringValue, - value.isFramework() ? null : context.getProjectKey()); - - if (bitmap == null) { - bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, - density); - Bridge.setCachedBitmap(stringValue, bitmap, - value.isFramework() ? null : context.getProjectKey()); - } - - return new BitmapDrawable(context.getResources(), bitmap); - } catch (IOException e) { - // we'll return null below - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/); - } - } else { - // attempt to get a color from the value - try { - int color = getColor(stringValue); - return new ColorDrawable(color); - } catch (NumberFormatException e) { - // we'll return null below. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Failed to convert " + stringValue + " into a drawable", e, - null /*data*/); - } - } - } - - return null; - } - - private static Drawable getNinePatchDrawable(InputStream inputStream, Density density, - boolean isFramework, String cacheKey, BridgeContext context) throws IOException { - // see if we still have both the chunk and the bitmap in the caches - NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey, - isFramework ? null : context.getProjectKey()); - Bitmap bitmap = Bridge.getCachedBitmap(cacheKey, - isFramework ? null : context.getProjectKey()); - - // if either chunk or bitmap is null, then we reload the 9-patch file. - if (chunk == null || bitmap == null) { - try { - NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/, - false /* convert */); - if (ninePatch != null) { - if (chunk == null) { - chunk = ninePatch.getChunk(); - - Bridge.setCached9Patch(cacheKey, chunk, - isFramework ? null : context.getProjectKey()); - } - - if (bitmap == null) { - bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), - false /*isMutable*/, - density); - - Bridge.setCachedBitmap(cacheKey, bitmap, - isFramework ? null : context.getProjectKey()); - } - } - } catch (MalformedURLException e) { - // URL is wrong, we'll return null below - } - } - - if (chunk != null && bitmap != null) { - int[] padding = chunk.getPadding(); - Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); - - return new NinePatchDrawable(context.getResources(), bitmap, - NinePatch_Delegate.serialize(chunk), - paddingRect, null); - } - - return null; - } - - // ------- TypedValue stuff - // This is taken from //device/libs/utils/ResourceTypes.cpp - - private static final class UnitEntry { - String name; - int type; - int unit; - float scale; - - UnitEntry(String name, int type, int unit, float scale) { - this.name = name; - this.type = type; - this.unit = unit; - this.scale = scale; - } - } - - private final static UnitEntry[] sUnitNames = new UnitEntry[] { - new UnitEntry("px", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PX, 1.0f), - new UnitEntry("dip", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), - new UnitEntry("dp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), - new UnitEntry("sp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_SP, 1.0f), - new UnitEntry("pt", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PT, 1.0f), - new UnitEntry("in", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_IN, 1.0f), - new UnitEntry("mm", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_MM, 1.0f), - new UnitEntry("%", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION, 1.0f/100), - new UnitEntry("%p", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION_PARENT, 1.0f/100), - }; - - /** - * Returns the raw value from the given attribute float-type value string. - * This object is only valid until the next call on to {@link ResourceHelper}. - */ - public static TypedValue getValue(String attribute, String value, boolean requireUnit) { - if (parseFloatAttribute(attribute, value, mValue, requireUnit)) { - return mValue; - } - - return null; - } - - /** - * Parse a float attribute and return the parsed value into a given TypedValue. - * @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false. - * @param value the string value of the attribute - * @param outValue the TypedValue to receive the parsed value - * @param requireUnit whether the value is expected to contain a unit. - * @return true if success. - */ - public static boolean parseFloatAttribute(String attribute, String value, - TypedValue outValue, boolean requireUnit) { - assert requireUnit == false || attribute != null; - - // remove the space before and after - value = value.trim(); - int len = value.length(); - - if (len <= 0) { - return false; - } - - // check that there's no non ascii characters. - char[] buf = value.toCharArray(); - for (int i = 0 ; i < len ; i++) { - if (buf[i] > 255) { - return false; - } - } - - // check the first character - if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') { - return false; - } - - // now look for the string that is after the float... - Matcher m = sFloatPattern.matcher(value); - if (m.matches()) { - String f_str = m.group(1); - String end = m.group(2); - - float f; - try { - f = Float.parseFloat(f_str); - } catch (NumberFormatException e) { - // this shouldn't happen with the regexp above. - return false; - } - - if (end.length() > 0 && end.charAt(0) != ' ') { - // Might be a unit... - if (parseUnit(end, outValue, sFloatOut)) { - computeTypedValue(outValue, f, sFloatOut[0]); - return true; - } - return false; - } - - // make sure it's only spaces at the end. - end = end.trim(); - - if (end.length() == 0) { - if (outValue != null) { - if (requireUnit == false) { - outValue.type = TypedValue.TYPE_FLOAT; - outValue.data = Float.floatToIntBits(f); - } else { - // no unit when required? Use dp and out an error. - applyUnit(sUnitNames[1], outValue, sFloatOut); - computeTypedValue(outValue, f, sFloatOut[0]); - - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, - String.format( - "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!", - value, attribute), - null); - } - return true; - } - } - } - - return false; - } - - private static void computeTypedValue(TypedValue outValue, float value, float scale) { - value *= scale; - boolean neg = value < 0; - if (neg) { - value = -value; - } - long bits = (long)(value*(1<<23)+.5f); - int radix; - int shift; - if ((bits&0x7fffff) == 0) { - // Always use 23p0 if there is no fraction, just to make - // things easier to read. - radix = TypedValue.COMPLEX_RADIX_23p0; - shift = 23; - } else if ((bits&0xffffffffff800000L) == 0) { - // Magnitude is zero -- can fit in 0 bits of precision. - radix = TypedValue.COMPLEX_RADIX_0p23; - shift = 0; - } else if ((bits&0xffffffff80000000L) == 0) { - // Magnitude can fit in 8 bits of precision. - radix = TypedValue.COMPLEX_RADIX_8p15; - shift = 8; - } else if ((bits&0xffffff8000000000L) == 0) { - // Magnitude can fit in 16 bits of precision. - radix = TypedValue.COMPLEX_RADIX_16p7; - shift = 16; - } else { - // Magnitude needs entire range, so no fractional part. - radix = TypedValue.COMPLEX_RADIX_23p0; - shift = 23; - } - int mantissa = (int)( - (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK); - if (neg) { - mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK; - } - outValue.data |= - (radix<<TypedValue.COMPLEX_RADIX_SHIFT) - | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT); - } - - private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) { - str = str.trim(); - - for (UnitEntry unit : sUnitNames) { - if (unit.name.equals(str)) { - applyUnit(unit, outValue, outScale); - return true; - } - } - - return false; - } - - private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) { - outValue.type = unit.type; - outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT; - outScale[0] = unit.scale; - } -} - diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java deleted file mode 100644 index 9bd0015..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge.impl; - -import java.util.ArrayList; - -/** - * Custom Stack implementation on top of an {@link ArrayList} instead of - * using {@link java.util.Stack} which is on top of a vector. - * - * @param <T> - */ -public class Stack<T> extends ArrayList<T> { - - private static final long serialVersionUID = 1L; - - public Stack() { - super(); - } - - public Stack(int size) { - super(size); - } - - /** - * Pushes the given object to the stack - * @param object the object to push - */ - public void push(T object) { - add(object); - } - - /** - * Remove the object at the top of the stack and returns it. - * @return the removed object or null if the stack was empty. - */ - public T pop() { - if (size() > 0) { - return remove(size() - 1); - } - - return null; - } - - /** - * Returns the object at the top of the stack. - * @return the object at the top or null if the stack is empty. - */ - public T peek() { - if (size() > 0) { - return get(size() - 1); - } - - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java deleted file mode 100644 index e0414fe..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.impl.binding; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.DataBindingItem; -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.ResourceReference; -import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute; -import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.impl.RenderAction; -import com.android.util.Pair; - -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.Checkable; -import android.widget.ImageView; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Base adapter to do fake data binding in {@link AdapterView} objects. - */ -public class BaseAdapter { - - /** - * This is the items provided by the adapter. They are dynamically generated. - */ - protected final static class AdapterItem { - private final DataBindingItem mItem; - private final int mType; - private final int mFullPosition; - private final int mPositionPerType; - private List<AdapterItem> mChildren; - - protected AdapterItem(DataBindingItem item, int type, int fullPosition, - int positionPerType) { - mItem = item; - mType = type; - mFullPosition = fullPosition; - mPositionPerType = positionPerType; - } - - void addChild(AdapterItem child) { - if (mChildren == null) { - mChildren = new ArrayList<AdapterItem>(); - } - - mChildren.add(child); - } - - List<AdapterItem> getChildren() { - if (mChildren != null) { - return mChildren; - } - - return Collections.emptyList(); - } - - int getType() { - return mType; - } - - int getFullPosition() { - return mFullPosition; - } - - int getPositionPerType() { - return mPositionPerType; - } - - DataBindingItem getDataBindingItem() { - return mItem; - } - } - - private final AdapterBinding mBinding; - private final IProjectCallback mCallback; - private final ResourceReference mAdapterRef; - private boolean mSkipCallbackParser = false; - - protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>(); - - protected BaseAdapter(ResourceReference adapterRef, AdapterBinding binding, - IProjectCallback callback) { - mAdapterRef = adapterRef; - mBinding = binding; - mCallback = callback; - } - - // ------- Some Adapter method used by all children classes. - - public boolean areAllItemsEnabled() { - return true; - } - - public boolean hasStableIds() { - return true; - } - - public boolean isEmpty() { - return mItems.size() == 0; - } - - public void registerDataSetObserver(DataSetObserver observer) { - // pass - } - - public void unregisterDataSetObserver(DataSetObserver observer) { - // pass - } - - // ------- - - - protected AdapterBinding getBinding() { - return mBinding; - } - - protected View getView(AdapterItem item, AdapterItem parentItem, View convertView, - ViewGroup parent) { - // we don't care about recycling here because we never scroll. - DataBindingItem dataBindingItem = item.getDataBindingItem(); - - BridgeContext context = RenderAction.getCurrentContext(); - - Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(), - parent, false /*attachToRoot*/, mSkipCallbackParser); - - View view = pair.getFirst(); - mSkipCallbackParser |= pair.getSecond(); - - if (view != null) { - fillView(context, view, item, parentItem); - } else { - // create a text view to display an error. - TextView tv = new TextView(context); - tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName()); - view = tv; - } - - return view; - } - - private void fillView(BridgeContext context, View view, AdapterItem item, - AdapterItem parentItem) { - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - final int count = group.getChildCount(); - for (int i = 0 ; i < count ; i++) { - fillView(context, group.getChildAt(i), item, parentItem); - } - } else { - int id = view.getId(); - if (id != 0) { - ResourceReference resolvedRef = context.resolveId(id); - if (resolvedRef != null) { - int fullPosition = item.getFullPosition(); - int positionPerType = item.getPositionPerType(); - int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0; - int parentPositionPerType = parentItem != null ? - parentItem.getPositionPerType() : 0; - - if (view instanceof TextView) { - TextView tv = (TextView) view; - Object value = mCallback.getAdapterItemValue( - mAdapterRef, context.getViewKey(view), - item.getDataBindingItem().getViewReference(), - fullPosition, positionPerType, - fullParentPosition, parentPositionPerType, - resolvedRef, ViewAttribute.TEXT, tv.getText().toString()); - if (value != null) { - if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( - "Wrong Adapter Item value class for TEXT. Expected String, got %s", - value.getClass().getName()), null); - } else { - tv.setText((String) value); - } - } - } - - if (view instanceof Checkable) { - Checkable cb = (Checkable) view; - - Object value = mCallback.getAdapterItemValue( - mAdapterRef, context.getViewKey(view), - item.getDataBindingItem().getViewReference(), - fullPosition, positionPerType, - fullParentPosition, parentPositionPerType, - resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked()); - if (value != null) { - if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( - "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s", - value.getClass().getName()), null); - } else { - cb.setChecked((Boolean) value); - } - } - } - - if (view instanceof ImageView) { - ImageView iv = (ImageView) view; - - Object value = mCallback.getAdapterItemValue( - mAdapterRef, context.getViewKey(view), - item.getDataBindingItem().getViewReference(), - fullPosition, positionPerType, - fullParentPosition, parentPositionPerType, - resolvedRef, ViewAttribute.SRC, iv.getDrawable()); - if (value != null) { - if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( - "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s", - value.getClass().getName()), null); - } else { - // FIXME - } - } - } - } - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java deleted file mode 100644 index 22570b9..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.impl.binding; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.DataBindingItem; -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.ResourceReference; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ListAdapter; -import android.widget.SpinnerAdapter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Fake adapter to do fake data binding in {@link AdapterView} objects for {@link ListAdapter} - * and {@link SpinnerAdapter}. - * - */ -public class FakeAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter { - - // don't use a set because the order is important. - private final List<ResourceReference> mTypes = new ArrayList<ResourceReference>(); - - public FakeAdapter(ResourceReference adapterRef, AdapterBinding binding, - IProjectCallback callback) { - super(adapterRef, binding, callback); - - final int repeatCount = getBinding().getRepeatCount(); - final int itemCount = getBinding().getItemCount(); - - // Need an array to count for each type. - // This is likely too big, but is the max it can be. - int[] typeCount = new int[itemCount]; - - // We put several repeating sets. - for (int r = 0 ; r < repeatCount ; r++) { - // loop on the type of list items, and add however many for each type. - for (DataBindingItem dataBindingItem : getBinding()) { - ResourceReference viewRef = dataBindingItem.getViewReference(); - int typeIndex = mTypes.indexOf(viewRef); - if (typeIndex == -1) { - typeIndex = mTypes.size(); - mTypes.add(viewRef); - } - - int count = dataBindingItem.getCount(); - - int index = typeCount[typeIndex]; - typeCount[typeIndex] += count; - - for (int k = 0 ; k < count ; k++) { - mItems.add(new AdapterItem(dataBindingItem, typeIndex, mItems.size(), index++)); - } - } - } - } - - @Override - public boolean isEnabled(int position) { - return true; - } - - @Override - public int getCount() { - return mItems.size(); - } - - @Override - public Object getItem(int position) { - return mItems.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public int getItemViewType(int position) { - return mItems.get(position).getType(); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - // we don't care about recycling here because we never scroll. - AdapterItem item = mItems.get(position); - return getView(item, null /*parentGroup*/, convertView, parent); - } - - @Override - public int getViewTypeCount() { - return mTypes.size(); - } - - // ---- SpinnerAdapter - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - // pass - return null; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java deleted file mode 100644 index 199e040..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.impl.binding; - -import com.android.ide.common.rendering.api.AdapterBinding; -import com.android.ide.common.rendering.api.DataBindingItem; -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.ide.common.rendering.api.ResourceReference; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ExpandableListAdapter; -import android.widget.HeterogeneousExpandableList; - -import java.util.ArrayList; -import java.util.List; - -public class FakeExpandableAdapter extends BaseAdapter implements ExpandableListAdapter, - HeterogeneousExpandableList { - - // don't use a set because the order is important. - private final List<ResourceReference> mGroupTypes = new ArrayList<ResourceReference>(); - private final List<ResourceReference> mChildrenTypes = new ArrayList<ResourceReference>(); - - public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding, - IProjectCallback callback) { - super(adapterRef, binding, callback); - - createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1); - } - - private void createItems(Iterable<DataBindingItem> iterable, final int itemCount, - final int repeatCount, List<ResourceReference> types, int depth) { - // Need an array to count for each type. - // This is likely too big, but is the max it can be. - int[] typeCount = new int[itemCount]; - - // we put several repeating sets. - for (int r = 0 ; r < repeatCount ; r++) { - // loop on the type of list items, and add however many for each type. - for (DataBindingItem dataBindingItem : iterable) { - ResourceReference viewRef = dataBindingItem.getViewReference(); - int typeIndex = types.indexOf(viewRef); - if (typeIndex == -1) { - typeIndex = types.size(); - types.add(viewRef); - } - - List<DataBindingItem> children = dataBindingItem.getChildren(); - int count = dataBindingItem.getCount(); - - // if there are children, we use the count as a repeat count for the children. - if (children.size() > 0) { - count = 1; - } - - int index = typeCount[typeIndex]; - typeCount[typeIndex] += count; - - for (int k = 0 ; k < count ; k++) { - AdapterItem item = new AdapterItem(dataBindingItem, typeIndex, mItems.size(), - index++); - mItems.add(item); - - if (children.size() > 0) { - createItems(dataBindingItem, depth + 1); - } - } - } - } - } - - private void createItems(DataBindingItem item, int depth) { - if (depth == 2) { - createItems(item, item.getChildren().size(), item.getCount(), mChildrenTypes, depth); - } - } - - private AdapterItem getChildItem(int groupPosition, int childPosition) { - AdapterItem item = mItems.get(groupPosition); - - List<AdapterItem> children = item.getChildren(); - return children.get(childPosition); - } - - // ---- ExpandableListAdapter - - @Override - public int getGroupCount() { - return mItems.size(); - } - - @Override - public int getChildrenCount(int groupPosition) { - AdapterItem item = mItems.get(groupPosition); - return item.getChildren().size(); - } - - @Override - public Object getGroup(int groupPosition) { - return mItems.get(groupPosition); - } - - @Override - public Object getChild(int groupPosition, int childPosition) { - return getChildItem(groupPosition, childPosition); - } - - @Override - public View getGroupView(int groupPosition, boolean isExpanded, View convertView, - ViewGroup parent) { - // we don't care about recycling here because we never scroll. - AdapterItem item = mItems.get(groupPosition); - return getView(item, null /*parentItem*/, convertView, parent); - } - - @Override - public View getChildView(int groupPosition, int childPosition, boolean isLastChild, - View convertView, ViewGroup parent) { - // we don't care about recycling here because we never scroll. - AdapterItem parentItem = mItems.get(groupPosition); - AdapterItem item = getChildItem(groupPosition, childPosition); - return getView(item, parentItem, convertView, parent); - } - - @Override - public long getGroupId(int groupPosition) { - return groupPosition; - } - - @Override - public long getChildId(int groupPosition, int childPosition) { - return childPosition; - } - - @Override - public long getCombinedGroupId(long groupId) { - return groupId << 16 | 0x0000FFFF; - } - - @Override - public long getCombinedChildId(long groupId, long childId) { - return groupId << 16 | childId; - } - - @Override - public boolean isChildSelectable(int groupPosition, int childPosition) { - return true; - } - - @Override - public void onGroupCollapsed(int groupPosition) { - // pass - } - - @Override - public void onGroupExpanded(int groupPosition) { - // pass - } - - // ---- HeterogeneousExpandableList - - @Override - public int getChildType(int groupPosition, int childPosition) { - return getChildItem(groupPosition, childPosition).getType(); - } - - @Override - public int getChildTypeCount() { - return mChildrenTypes.size(); - } - - @Override - public int getGroupType(int groupPosition) { - return mItems.get(groupPosition).getType(); - } - - @Override - public int getGroupTypeCount() { - return mGroupTypes.size(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java deleted file mode 100644 index 82eab85..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.util; - -public class Debug { - - public final static boolean DEBUG = false; - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java deleted file mode 100644 index a1fae95..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -package com.android.layoutlib.bridge.util; - -import com.android.resources.ResourceType; -import com.android.util.Pair; - -import android.util.SparseArray; - -import java.util.HashMap; -import java.util.Map; - -public class DynamicIdMap { - - private final Map<Pair<ResourceType, String>, Integer> mDynamicIds = new HashMap<Pair<ResourceType, String>, Integer>(); - private final SparseArray<Pair<ResourceType, String>> mRevDynamicIds = new SparseArray<Pair<ResourceType, String>>(); - private int mDynamicSeed; - - public DynamicIdMap(int seed) { - mDynamicSeed = seed; - } - - public void reset(int seed) { - mDynamicIds.clear(); - mRevDynamicIds.clear(); - mDynamicSeed = seed; - } - - /** - * Returns a dynamic integer for the given resource type/name, creating it if it doesn't - * already exist. - * - * @param type the type of the resource - * @param name the name of the resource - * @return an integer. - */ - public Integer getId(ResourceType type, String name) { - return getId(Pair.of(type, name)); - } - - /** - * Returns a dynamic integer for the given resource type/name, creating it if it doesn't - * already exist. - * - * @param resource the type/name of the resource - * @return an integer. - */ - public Integer getId(Pair<ResourceType, String> resource) { - Integer value = mDynamicIds.get(resource); - if (value == null) { - value = Integer.valueOf(++mDynamicSeed); - mDynamicIds.put(resource, value); - mRevDynamicIds.put(value, resource); - } - - return value; - } - - public Pair<ResourceType, String> resolveId(int id) { - return mRevDynamicIds.get(id); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java deleted file mode 100644 index 4d0c9ce..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.layoutlib.bridge.util; - - -import com.android.internal.util.ArrayUtils; - -import android.util.SparseArray; - -import java.lang.ref.WeakReference; - -/** - * This is a custom {@link SparseArray} that uses {@link WeakReference} around the objects added - * to it. When the array is compacted, not only deleted indices but also empty references - * are removed, making the array efficient at removing references that were reclaimed. - * - * The code is taken from {@link SparseArray} directly and adapted to use weak references. - * - * Because our usage means that we never actually call {@link #remove(int)} or {@link #delete(int)}, - * we must manually check if there are reclaimed references to trigger an internal compact step - * (which is normally only triggered when an item is manually removed). - * - * SparseArrays map integers to Objects. Unlike a normal array of Objects, - * there can be gaps in the indices. It is intended to be more efficient - * than using a HashMap to map Integers to Objects. - */ -@SuppressWarnings("unchecked") -public class SparseWeakArray<E> { - - private static final Object DELETED_REF = new Object(); - private static final WeakReference<?> DELETED = new WeakReference(DELETED_REF); - private boolean mGarbage = false; - - /** - * Creates a new SparseArray containing no mappings. - */ - public SparseWeakArray() { - this(10); - } - - /** - * Creates a new SparseArray containing no mappings that will not - * require any additional memory allocation to store the specified - * number of mappings. - */ - public SparseWeakArray(int initialCapacity) { - initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity); - - mKeys = new int[initialCapacity]; - mValues = new WeakReference[initialCapacity]; - mSize = 0; - } - - /** - * Gets the Object mapped from the specified key, or <code>null</code> - * if no such mapping has been made. - */ - public E get(int key) { - return get(key, null); - } - - /** - * Gets the Object mapped from the specified key, or the specified Object - * if no such mapping has been made. - */ - public E get(int key, E valueIfKeyNotFound) { - int i = binarySearch(mKeys, 0, mSize, key); - - if (i < 0 || mValues[i] == DELETED || mValues[i].get() == null) { - return valueIfKeyNotFound; - } else { - return (E) mValues[i].get(); - } - } - - /** - * Removes the mapping from the specified key, if there was any. - */ - public void delete(int key) { - int i = binarySearch(mKeys, 0, mSize, key); - - if (i >= 0) { - if (mValues[i] != DELETED) { - mValues[i] = DELETED; - mGarbage = true; - } - } - } - - /** - * Alias for {@link #delete(int)}. - */ - public void remove(int key) { - delete(key); - } - - /** - * Removes the mapping at the specified index. - */ - public void removeAt(int index) { - if (mValues[index] != DELETED) { - mValues[index] = DELETED; - mGarbage = true; - } - } - - private void gc() { - int n = mSize; - int o = 0; - int[] keys = mKeys; - WeakReference<?>[] values = mValues; - - for (int i = 0; i < n; i++) { - WeakReference<?> val = values[i]; - - // Don't keep any non DELETED values, but only the one that still have a valid - // reference. - if (val != DELETED && val.get() != null) { - if (i != o) { - keys[o] = keys[i]; - values[o] = val; - } - - o++; - } - } - - mGarbage = false; - mSize = o; - - int newSize = ArrayUtils.idealIntArraySize(mSize); - if (newSize < mKeys.length) { - int[] nkeys = new int[newSize]; - WeakReference<?>[] nvalues = new WeakReference[newSize]; - - System.arraycopy(mKeys, 0, nkeys, 0, newSize); - System.arraycopy(mValues, 0, nvalues, 0, newSize); - - mKeys = nkeys; - mValues = nvalues; - } - } - - /** - * Adds a mapping from the specified key to the specified value, - * replacing the previous mapping from the specified key if there - * was one. - */ - public void put(int key, E value) { - int i = binarySearch(mKeys, 0, mSize, key); - - if (i >= 0) { - mValues[i] = new WeakReference(value); - } else { - i = ~i; - - if (i < mSize && (mValues[i] == DELETED || mValues[i].get() == null)) { - mKeys[i] = key; - mValues[i] = new WeakReference(value); - return; - } - - if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) { - gc(); - - // Search again because indices may have changed. - i = ~binarySearch(mKeys, 0, mSize, key); - } - - if (mSize >= mKeys.length) { - int n = ArrayUtils.idealIntArraySize(mSize + 1); - - int[] nkeys = new int[n]; - WeakReference<?>[] nvalues = new WeakReference[n]; - - // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); - System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); - System.arraycopy(mValues, 0, nvalues, 0, mValues.length); - - mKeys = nkeys; - mValues = nvalues; - } - - if (mSize - i != 0) { - // Log.e("SparseArray", "move " + (mSize - i)); - System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i); - System.arraycopy(mValues, i, mValues, i + 1, mSize - i); - } - - mKeys[i] = key; - mValues[i] = new WeakReference(value); - mSize++; - } - } - - /** - * Returns the number of key-value mappings that this SparseArray - * currently stores. - */ - public int size() { - if (mGarbage) { - gc(); - } - - return mSize; - } - - /** - * Given an index in the range <code>0...size()-1</code>, returns - * the key from the <code>index</code>th key-value mapping that this - * SparseArray stores. - */ - public int keyAt(int index) { - if (mGarbage) { - gc(); - } - - return mKeys[index]; - } - - /** - * Given an index in the range <code>0...size()-1</code>, returns - * the value from the <code>index</code>th key-value mapping that this - * SparseArray stores. - */ - public E valueAt(int index) { - if (mGarbage) { - gc(); - } - - return (E) mValues[index].get(); - } - - /** - * Given an index in the range <code>0...size()-1</code>, sets a new - * value for the <code>index</code>th key-value mapping that this - * SparseArray stores. - */ - public void setValueAt(int index, E value) { - if (mGarbage) { - gc(); - } - - mValues[index] = new WeakReference(value); - } - - /** - * Returns the index for which {@link #keyAt} would return the - * specified key, or a negative number if the specified - * key is not mapped. - */ - public int indexOfKey(int key) { - if (mGarbage) { - gc(); - } - - return binarySearch(mKeys, 0, mSize, key); - } - - /** - * Returns an index for which {@link #valueAt} would return the - * specified key, or a negative number if no keys map to the - * specified value. - * Beware that this is a linear search, unlike lookups by key, - * and that multiple keys can map to the same value and this will - * find only one of them. - */ - public int indexOfValue(E value) { - if (mGarbage) { - gc(); - } - - for (int i = 0; i < mSize; i++) - if (mValues[i].get() == value) - return i; - - return -1; - } - - /** - * Removes all key-value mappings from this SparseArray. - */ - public void clear() { - int n = mSize; - WeakReference<?>[] values = mValues; - - for (int i = 0; i < n; i++) { - values[i] = null; - } - - mSize = 0; - mGarbage = false; - } - - /** - * Puts a key/value pair into the array, optimizing for the case where - * the key is greater than all existing keys in the array. - */ - public void append(int key, E value) { - if (mSize != 0 && key <= mKeys[mSize - 1]) { - put(key, value); - return; - } - - if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) { - gc(); - } - - int pos = mSize; - if (pos >= mKeys.length) { - int n = ArrayUtils.idealIntArraySize(pos + 1); - - int[] nkeys = new int[n]; - WeakReference<?>[] nvalues = new WeakReference[n]; - - // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); - System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); - System.arraycopy(mValues, 0, nvalues, 0, mValues.length); - - mKeys = nkeys; - mValues = nvalues; - } - - mKeys[pos] = key; - mValues[pos] = new WeakReference(value); - mSize = pos + 1; - } - - private boolean hasReclaimedRefs() { - for (int i = 0 ; i < mSize ; i++) { - if (mValues[i].get() == null) { // DELETED.get() never returns null. - return true; - } - } - - return false; - } - - private static int binarySearch(int[] a, int start, int len, int key) { - int high = start + len, low = start - 1, guess; - - while (high - low > 1) { - guess = (high + low) / 2; - - if (a[guess] < key) - low = guess; - else - high = guess; - } - - if (high == start + len) - return ~(start + len); - else if (a[high] == key) - return high; - else - return ~high; - } - - private int[] mKeys; - private WeakReference<?>[] mValues; - private int mSize; -} diff --git a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java deleted file mode 100644 index 6d013bb..0000000 --- a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.google.android.maps; - -import com.android.layoutlib.bridge.MockView; - -import android.content.Context; -import android.os.Bundle; -import android.util.AttributeSet; -import android.view.View; - -/** - * Mock version of the MapView. - * Only non override public methods from the real MapView have been added in there. - * Methods that take an unknown class as parameter or as return object, have been removed for now. - * - * TODO: generate automatically. - * - */ -public class MapView extends MockView { - - /** - * Construct a new WebView with a Context object. - * @param context A Context object used to access application assets. - */ - public MapView(Context context) { - this(context, null); - } - - /** - * Construct a new WebView with layout parameters. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - */ - public MapView(Context context, AttributeSet attrs) { - this(context, attrs, com.android.internal.R.attr.mapViewStyle); - } - - /** - * Construct a new WebView with layout parameters and a default style. - * @param context A Context object used to access application assets. - * @param attrs An AttributeSet passed to our parent. - * @param defStyle The default style resource ID. - */ - public MapView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - // START FAKE PUBLIC METHODS - - public void displayZoomControls(boolean takeFocus) { - } - - public boolean canCoverCenter() { - return false; - } - - public void preLoad() { - } - - public int getZoomLevel() { - return 0; - } - - public void setSatellite(boolean on) { - } - - public boolean isSatellite() { - return false; - } - - public void setTraffic(boolean on) { - } - - public boolean isTraffic() { - return false; - } - - public void setStreetView(boolean on) { - } - - public boolean isStreetView() { - return false; - } - - public int getLatitudeSpan() { - return 0; - } - - public int getLongitudeSpan() { - return 0; - } - - public int getMaxZoomLevel() { - return 0; - } - - public void onSaveInstanceState(Bundle state) { - } - - public void onRestoreInstanceState(Bundle state) { - } - - public View getZoomControls() { - return null; - } -} diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java deleted file mode 100644 index cd4f82b..0000000 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package libcore.icu; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import java.util.Locale; - -/** - * Delegate implementing the native methods of libcore.icu.ICU - * - * Through the layoutlib_create tool, the original native methods of ICU have been replaced - * by calls to methods of the same name in this delegate class. - * - */ -public class ICU_Delegate { - - // --- Java delegates - - @LayoutlibDelegate - /*package*/ static String toLowerCase(String s, String localeName) { - return s.toLowerCase(); - } - - @LayoutlibDelegate - /*package*/ static String toUpperCase(String s, String localeName) { - return s.toUpperCase(); - } - - // --- Native methods accessing ICU's database. - - @LayoutlibDelegate - /*package*/ static String getBestDateTimePattern(String skeleton, String localeName) { - return ""; // TODO: check what the right value should be. - } - - @LayoutlibDelegate - /*package*/ static String getCldrVersion() { - return "22.1.1"; // TODO: check what the right value should be. - } - - @LayoutlibDelegate - /*package*/ static String getIcuVersion() { - return "unknown_layoutlib"; - } - - @LayoutlibDelegate - /*package*/ static String getUnicodeVersion() { - return "5.2"; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableBreakIteratorLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableCalendarLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableCollatorLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableDateFormatLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableNumberFormatLocalesNative() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String[] getAvailableCurrencyCodes() { - return new String[0]; - } - - @LayoutlibDelegate - /*package*/ static String getCurrencyCode(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getCurrencyDisplayName(String locale, String currencyCode) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static int getCurrencyFractionDigits(String currencyCode) { - return 0; - } - - @LayoutlibDelegate - /*package*/ static String getCurrencySymbol(String locale, String currencyCode) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayCountryNative(String countryCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayLanguageNative(String languageCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getDisplayVariantNative(String variantCode, String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getISO3CountryNative(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getISO3LanguageNative(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String addLikelySubtags(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String getScript(String locale) { - return ""; - } - - @LayoutlibDelegate - /*package*/ static String[] getISOLanguagesNative() { - return Locale.getISOLanguages(); - } - - @LayoutlibDelegate - /*package*/ static String[] getISOCountriesNative() { - return Locale.getISOCountries(); - } - - @LayoutlibDelegate - /*package*/ static boolean initLocaleDataImpl(String locale, LocaleData result) { - - // Used by Calendar. - result.firstDayOfWeek = Integer.valueOf(1); - result.minimalDaysInFirstWeek = Integer.valueOf(1); - - // Used by DateFormatSymbols. - result.amPm = new String[] { "AM", "PM" }; - result.eras = new String[] { "BC", "AD" }; - - result.longMonthNames = new String[] { "January", "February", "March", "April", "May", - "June", "July", "August", "September", "October", "November", "December" }; - result.shortMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - result.longStandAloneMonthNames = result.longMonthNames; - result.shortStandAloneMonthNames = result.shortMonthNames; - - result.longWeekdayNames = new String[] { - "Monday" ,"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; - result.shortWeekdayNames = new String[] { - "Mon" ,"Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; - result.longStandAloneWeekdayNames = result.longWeekdayNames; - result.shortStandAloneWeekdayNames = result.shortWeekdayNames; - - result.fullTimeFormat = ""; - result.longTimeFormat = ""; - result.mediumTimeFormat = ""; - result.shortTimeFormat = ""; - - result.fullDateFormat = ""; - result.longDateFormat = ""; - result.mediumDateFormat = ""; - result.shortDateFormat = ""; - - // Used by DecimalFormatSymbols. - result.zeroDigit = '0'; - result.decimalSeparator = '.'; - result.groupingSeparator = ','; - result.patternSeparator = ' '; - result.percent = '%'; - result.perMill = '\u2030'; - result.monetarySeparator = ' '; - result.minusSign = '-'; - result.exponentSeparator = "e"; - result.infinity = "\u221E"; - result.NaN = "NaN"; - // Also used by Currency. - result.currencySymbol = "$"; - result.internationalCurrencySymbol = "USD"; - - // Used by DecimalFormat and NumberFormat. - result.numberPattern = "%f"; - result.integerPattern = "%d"; - result.currencyPattern = "%s"; - result.percentPattern = "%f"; - - return true; - } -} diff --git a/tools/layoutlib/bridge/tests/.classpath b/tools/layoutlib/bridge/tests/.classpath deleted file mode 100644 index 2b32e09..0000000 --- a/tools/layoutlib/bridge/tests/.classpath +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="src" path="res"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_bridge"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/> - <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/> - <classpathentry kind="output" path="bin"/> -</classpath> diff --git a/tools/layoutlib/bridge/tests/.project b/tools/layoutlib/bridge/tests/.project deleted file mode 100644 index 2325eed..0000000 --- a/tools/layoutlib/bridge/tests/.project +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>layoutlib_bridge-tests</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk deleted file mode 100644 index 98cade9..0000000 --- a/tools/layoutlib/bridge/tests/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2011 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. - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -# Only compile source java files in this lib. -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_JAVA_RESOURCE_DIRS := res - -LOCAL_MODULE := layoutlib-tests -LOCAL_MODULE_TAGS := optional - -LOCAL_JAVA_LIBRARIES := layoutlib kxml2-2.3.0 junit - -include $(BUILD_HOST_JAVA_LIBRARY) - -# Build all sub-directories -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml b/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml deleted file mode 100644 index b8fc947..0000000 --- a/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - Copyright (C) 2008 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. ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" -> - <Button - android:id="@+id/bouton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_weight="1" - android:text="My Button Text" - > - </Button> - <View - android:id="@+id/surface" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_weight="2" - /> - <TextView - android:id="@+id/status" - android:paddingLeft="2dip" - android:layout_weight="0" - android:background="@drawable/black" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:lines="1" - android:gravity="center_vertical|center_horizontal" - android:text="My TextView Text" - /> -</LinearLayout> diff --git a/tools/layoutlib/bridge/tests/src/android/graphics/Matrix_DelegateTest.java b/tools/layoutlib/bridge/tests/src/android/graphics/Matrix_DelegateTest.java deleted file mode 100644 index ec4edac..0000000 --- a/tools/layoutlib/bridge/tests/src/android/graphics/Matrix_DelegateTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package android.graphics; - -import junit.framework.TestCase; - -/** - * - */ -public class Matrix_DelegateTest extends TestCase { - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testIdentity() { - Matrix m1 = new Matrix(); - - assertTrue(m1.isIdentity()); - - m1.setValues(new float[] { 1,0,0, 0,1,0, 0,0,1 }); - assertTrue(m1.isIdentity()); - } - - public void testCopyConstructor() { - Matrix m1 = new Matrix(); - Matrix m2 = new Matrix(m1); - - float[] v1 = new float[9]; - float[] v2 = new float[9]; - m1.getValues(v1); - m2.getValues(v2); - - for (int i = 0 ; i < 9; i++) { - assertEquals(v1[i], v2[i]); - } - } -} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java deleted file mode 100644 index d3218db..0000000 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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. - */ - -package com.android.layoutlib.bridge; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import com.android.tools.layoutlib.create.CreateInfo; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -/** - * Tests that native delegate classes implement all the required methods. - * - * This looks at {@link CreateInfo#DELEGATE_CLASS_NATIVES} to get the list of classes that - * have their native methods reimplemented through a delegate. - * - * Since the reimplemented methods are not native anymore, we look for the annotation - * {@link LayoutlibDelegate}, and look for a matching method in the delegate (named the same - * as the modified class with _Delegate added as a suffix). - * If the original native method is not static, then we make sure the delegate method also - * include the original class as first parameter (to access "this"). - * - */ -public class TestDelegates extends TestCase { - - public void testNativeDelegates() { - - final String[] classes = CreateInfo.DELEGATE_CLASS_NATIVES; - final int count = classes.length; - for (int i = 0 ; i < count ; i++) { - loadAndCompareClasses(classes[i], classes[i] + "_Delegate"); - } - } - - public void testMethodDelegates() { - final String[] methods = CreateInfo.DELEGATE_METHODS; - final int count = methods.length; - for (int i = 0 ; i < count ; i++) { - String methodName = methods[i]; - - // extract the class name - String className = methodName.substring(0, methodName.indexOf('#')); - String targetClassName = className.replace('$', '_') + "_Delegate"; - - loadAndCompareClasses(className, targetClassName); - } - } - - private void loadAndCompareClasses(String originalClassName, String delegateClassName) { - // load the classes - try { - ClassLoader classLoader = TestDelegates.class.getClassLoader(); - Class<?> originalClass = classLoader.loadClass(originalClassName); - Class<?> delegateClass = classLoader.loadClass(delegateClassName); - - compare(originalClass, delegateClass); - } catch (ClassNotFoundException e) { - fail("Failed to load class: " + e.getMessage()); - } catch (SecurityException e) { - fail("Failed to load class: " + e.getMessage()); - } - } - - private void compare(Class<?> originalClass, Class<?> delegateClass) throws SecurityException { - List<Method> checkedDelegateMethods = new ArrayList<Method>(); - - // loop on the methods of the original class, and for the ones that are annotated - // with @LayoutlibDelegate, look for a matching method in the delegate class. - // The annotation is automatically added by layoutlib_create when it replace a method - // by a call to a delegate - Method[] originalMethods = originalClass.getDeclaredMethods(); - for (Method originalMethod : originalMethods) { - // look for methods that are delegated: they have the LayoutlibDelegate annotation - if (originalMethod.getAnnotation(LayoutlibDelegate.class) == null) { - continue; - } - - // get the signature. - Class<?>[] parameters = originalMethod.getParameterTypes(); - - // if the method is not static, then the class is added as the first parameter - // (for "this") - if ((originalMethod.getModifiers() & Modifier.STATIC) == 0) { - - Class<?>[] newParameters = new Class<?>[parameters.length + 1]; - newParameters[0] = originalClass; - System.arraycopy(parameters, 0, newParameters, 1, parameters.length); - parameters = newParameters; - } - - // if the original class is an inner class that's not static, then - // we add this on the enclosing class at the beginning - if (originalClass.getEnclosingClass() != null && - (originalClass.getModifiers() & Modifier.STATIC) == 0) { - Class<?>[] newParameters = new Class<?>[parameters.length + 1]; - newParameters[0] = originalClass.getEnclosingClass(); - System.arraycopy(parameters, 0, newParameters, 1, parameters.length); - parameters = newParameters; - } - - try { - // try to load the method with the given parameter types. - Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(), - parameters); - - // check that the method has the annotation - assertNotNull( - String.format( - "Delegate method %1$s for class %2$s does not have the @LayoutlibDelegate annotation", - delegateMethod.getName(), - originalClass.getName()), - delegateMethod.getAnnotation(LayoutlibDelegate.class)); - - // check that the method is static - assertTrue( - String.format( - "Delegate method %1$s for class %2$s is not static", - delegateMethod.getName(), - originalClass.getName()), - (delegateMethod.getModifiers() & Modifier.STATIC) == Modifier.STATIC); - - // add the method as checked. - checkedDelegateMethods.add(delegateMethod); - } catch (NoSuchMethodException e) { - String name = getMethodName(originalMethod, parameters); - fail(String.format("Missing %1$s.%2$s", delegateClass.getName(), name)); - } - } - - // look for dead (delegate) code. - // This looks for all methods in the delegate class, and if they have the - // @LayoutlibDelegate annotation, make sure they have been previously found as a - // match for a method in the original class. - // If not, this means the method is a delegate for a method that either doesn't exist - // anymore or is not delegated anymore. - Method[] delegateMethods = delegateClass.getDeclaredMethods(); - for (Method delegateMethod : delegateMethods) { - // look for methods that are delegates: they have the LayoutlibDelegate annotation - if (delegateMethod.getAnnotation(LayoutlibDelegate.class) == null) { - continue; - } - - assertTrue( - String.format( - "Delegate method %1$s.%2$s is not used anymore and must be removed", - delegateClass.getName(), - getMethodName(delegateMethod)), - checkedDelegateMethods.contains(delegateMethod)); - } - - } - - private String getMethodName(Method method) { - return getMethodName(method, method.getParameterTypes()); - } - - private String getMethodName(Method method, Class<?>[] parameters) { - // compute a full class name that's long but not too long. - StringBuilder sb = new StringBuilder(method.getName() + "("); - for (int j = 0; j < parameters.length; j++) { - Class<?> theClass = parameters[j]; - sb.append(theClass.getName()); - int dimensions = 0; - while (theClass.isArray()) { - dimensions++; - theClass = theClass.getComponentType(); - } - for (int i = 0; i < dimensions; i++) { - sb.append("[]"); - } - if (j < (parameters.length - 1)) { - sb.append(","); - } - } - sb.append(")"); - - return sb.toString(); - } -} diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java deleted file mode 100644 index 865a008..0000000 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.layoutlib.bridge.impl.ParserFactory; - -import org.w3c.dom.Node; -import org.xmlpull.v1.XmlPullParser; - -import junit.framework.TestCase; - -public class BridgeXmlBlockParserTest extends TestCase { - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testXmlBlockParser() throws Exception { - - XmlPullParser parser = ParserFactory.create( - getClass().getResourceAsStream("/com/android/layoutlib/testdata/layout1.xml"), - "layout1.xml"); - - parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */); - - assertEquals(XmlPullParser.START_DOCUMENT, parser.next()); - - assertEquals(XmlPullParser.START_TAG, parser.next()); - assertEquals("LinearLayout", parser.getName()); - - assertEquals(XmlPullParser.TEXT, parser.next()); - - assertEquals(XmlPullParser.START_TAG, parser.next()); - assertEquals("Button", parser.getName()); - assertEquals(XmlPullParser.TEXT, parser.next()); - assertEquals(XmlPullParser.END_TAG, parser.next()); - - assertEquals(XmlPullParser.TEXT, parser.next()); - - assertEquals(XmlPullParser.START_TAG, parser.next()); - assertEquals("View", parser.getName()); - assertEquals(XmlPullParser.END_TAG, parser.next()); - - assertEquals(XmlPullParser.TEXT, parser.next()); - - assertEquals(XmlPullParser.START_TAG, parser.next()); - assertEquals("TextView", parser.getName()); - assertEquals(XmlPullParser.END_TAG, parser.next()); - - assertEquals(XmlPullParser.TEXT, parser.next()); - - assertEquals(XmlPullParser.END_TAG, parser.next()); - assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); - } - - //------------ - - /** - * Quick'n'dirty debug helper that dumps an XML structure to stdout. - */ - @SuppressWarnings("unused") - private void dump(Node node, String prefix) { - Node n; - - String[] types = { - "unknown", - "ELEMENT_NODE", - "ATTRIBUTE_NODE", - "TEXT_NODE", - "CDATA_SECTION_NODE", - "ENTITY_REFERENCE_NODE", - "ENTITY_NODE", - "PROCESSING_INSTRUCTION_NODE", - "COMMENT_NODE", - "DOCUMENT_NODE", - "DOCUMENT_TYPE_NODE", - "DOCUMENT_FRAGMENT_NODE", - "NOTATION_NODE" - }; - - String s = String.format("%s<%s> %s %s", - prefix, - types[node.getNodeType()], - node.getNodeName(), - node.getNodeValue() == null ? "" : node.getNodeValue().trim()); - - System.out.println(s); - - n = node.getFirstChild(); - if (n != null) { - dump(n, prefix + "- "); - } - - n = node.getNextSibling(); - if (n != null) { - dump(n, prefix); - } - - } - -} diff --git a/tools/layoutlib/create/.classpath b/tools/layoutlib/create/.classpath deleted file mode 100644 index dbc4cfd..0000000 --- a/tools/layoutlib/create/.classpath +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry excluding="mock_android/" kind="src" path="tests"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar"/> - <classpathentry kind="output" path="bin"/> -</classpath> diff --git a/tools/layoutlib/create/.project b/tools/layoutlib/create/.project deleted file mode 100644 index e100d17..0000000 --- a/tools/layoutlib/create/.project +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>layoutlib_create</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/tools/layoutlib/create/.settings/README.txt b/tools/layoutlib/create/.settings/README.txt deleted file mode 100644 index 9120b20..0000000 --- a/tools/layoutlib/create/.settings/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -Copy this in eclipse project as a .settings folder at the root. -This ensure proper compilation compliance and warning/error levels.
\ No newline at end of file diff --git a/tools/layoutlib/create/.settings/org.eclipse.jdt.core.prefs b/tools/layoutlib/create/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5381a0e..0000000 --- a/tools/layoutlib/create/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,93 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled -org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullReference=error -org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/tools/layoutlib/create/Android.mk b/tools/layoutlib/create/Android.mk deleted file mode 100644 index 9bd48ab..0000000 --- a/tools/layoutlib/create/Android.mk +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (C) 2008 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. -# -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(call all-java-files-under,src) - -LOCAL_JAR_MANIFEST := manifest.txt -LOCAL_STATIC_JAVA_LIBRARIES := \ - asm-4.0 - -LOCAL_MODULE := layoutlib_create - -include $(BUILD_HOST_JAVA_LIBRARY) - diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt deleted file mode 100644 index 894611b..0000000 --- a/tools/layoutlib/create/README.txt +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (C) 2008 The Android Open Source Project - - -- Description - ---------------- - -Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor -to perform layout. - - -- Usage - ---------- - - ./layoutlib_create path/to/android.jar destination.jar - - -- Design Overview - -------------------- - -Layoutlib_create uses the "android.jar" containing all the Java code used by Android -as generated by the Android build, right before the classes are converted to a DEX format. - -The Android JAR can't be used directly in Eclipse: -- it contains references to native code (which we want to avoid in Eclipse), -- some classes need to be overridden, for example all the drawing code that is - replaced by Java 2D calls in Eclipse. -- some of the classes that need to be changed are final and/or we need access - to their private internal state. - -Consequently this tool: -- parses the input JAR, -- modifies some of the classes directly using some bytecode manipulation, -- filters some packages and removes those we don't want in the output JAR, -- injects some new classes, -- generates a modified JAR file that is suitable for the Android plugin - for Eclipse to perform rendering. - -The ASM library is used to do the bytecode modification using its visitor pattern API. - -The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the -configuration is done in the main() method and the CreateInfo structure is expected to -change with the Android platform as new classes are added, changed or removed. - -The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the -platform, that provides all the necessary missing implementation for rendering graphics -in Eclipse. - - - -- Implementation Notes - ------------------------- - -The tool works in two phases: -- first analyze the input jar (AsmAnalyzer class) -- then generate the output jar (AsmGenerator class), - - -- Analyzer ----------- - -The goal of the analyzer is to create a graph of all the classes from the input JAR -with their dependencies and then only keep the ones we want. - -To do that, the analyzer is created with a list of base classes to keep -- everything -that derives from these is kept. Currently the one such class is android.view.View: -since we want to render layouts, anything that is sort of a view needs to be kept. - -The analyzer is also given a list of class names to keep in the output. -This is done using shell-like glob patterns that filter on the fully-qualified -class names, for example "android.*.R**" ("*" does not matches dots whilst "**" does, -and "." and "$" are interpreted as-is). -In practice we almost but not quite request the inclusion of full packages. - -With this information, the analyzer parses the input zip to find all the classes. -All classes deriving from the requested bases classes are kept. -All classes which name matched the glob pattern are kept. -The analysis then finds all the dependencies of the classes that are to be kept -using an ASM visitor on the class, the field types, the method types and annotations types. -Classes that belong to the current JRE are excluded. - -The output of the analyzer is a set of ASM ClassReader instances which are then -fed to the generator. - - -- Generator ------------ - -The generator is constructed from a CreateInfo struct that acts as a config file -and lists: -- the classes to inject in the output JAR -- these classes are directly implemented - in layoutlib_create and will be used to interface with the renderer in Eclipse. -- specific methods to override (see method stubs details below). -- specific methods for which to delegate calls. -- specific methods to remove based on their return type. -- specific classes to rename. - -Each of these are specific strategies we use to be able to modify the Android code -to fit within the Eclipse renderer. These strategies are explained beow. - -The core method of the generator is transform(): it takes an input ASM ClassReader -and modifies it to produce a byte array suitable for the final JAR file. - -The first step of the transformation is changing the name of the class in case -we requested the class to be renamed. This uses the RenameClassAdapter to also rename -all inner classes and references in methods and types. Note that other classes are -not transformed and keep referencing the original name. - -The TransformClassAdapter is then used to process the potentially renamed class. -All protected or private classes are market as public. -All classes are made non-final. -Interfaces are left as-is. - -If a method has a return type that must be erased, the whole method is skipped. -Methods are also changed from protected/private to public. -The code of the methods is then kept as-is, except for native methods which are -replaced by a stub. Methods that are to be overridden are also replaced by a stub. - -The transformed class is then fed through the DelegateClassAdapter to implement -method delegates. - -Finally fields are also visited and changed from protected/private to public. - - -- Method stubs --------------- - -As indicated above, all native and overridden methods are replaced by a stub. -We don't have the code to replace with in layoutlib_create. -Instead the StubMethodAdapter replaces the code of the method by a call to -OverrideMethod.invokeX(). When using the final JAR, the bridge can register -listeners from these overridden method calls based on the method signatures. - -The listeners are currently pretty basic: we only pass the signature of the -method being called, its caller object and a flag indicating whether the -method was native. We do not currently provide the parameters. The listener -can however specify the return value of the overridden method. - -This strategy is now obsolete and replaced by the method delegates. - - -- Strategies ------------- - -We currently have 4 strategies to deal with overriding the rendering code -and make it run in Eclipse. Most of these strategies are implemented hand-in-hand -by the bridge (which runs in Eclipse) and the generator. - - -1- Class Injection - -This is the easiest: we currently inject 4 classes, namely: -- OverrideMethod and its associated MethodListener and MethodAdapter are used - to intercept calls to some specific methods that are stubbed out and change - their return value. -- CreateInfo class, which configured the generator. Not used yet, but could - in theory help us track what the generator changed. - - -2- Overriding methods - -As explained earlier, the creator doesn't have any replacement code for -methods to override. Instead it removes the original code and replaces it -by a call to a specific OveriddeMethod.invokeX(). The bridge then registers -a listener on the method signature and can provide an implementation. - -This strategy is now obsolete and replaced by the method delegates. -See strategy 5 below. - - -3- Renaming classes - -This simply changes the name of a class in its definition, as well as all its -references in internal inner classes and methods. -Calls from other classes are not modified -- they keep referencing the original -class name. This allows the bridge to literally replace an implementation. - -An example will make this easier: android.graphics.Paint is the main drawing -class that we need to replace. To do so, the generator renames Paint to _original_Paint. -Later the bridge provides its own replacement version of Paint which will be used -by the rest of the Android stack. The replacement version of Paint can still use -(either by inheritance or delegation) all the original non-native code of _original_Paint -if it so desires. - -Some of the Android classes are basically wrappers over native objects and since -we don't have the native code in Eclipse, we need to provide a full alternate -implementation. Sub-classing doesn't work as some native methods are static and -we don't control object creation. - -This won't rename/replace the inner static methods of a given class. - - -4- Method erasure based on return type - -This is mostly an implementation detail of the bridge: in the Paint class -mentioned above, some inner static classes are used to pass around -attributes (e.g. FontMetrics, or the Style enum) and all the original implementation -is native. - -In this case we have a strategy that tells the generator that anything returning, for -example, the inner class Paint$Style in the Paint class should be discarded and the -bridge will provide its own implementation. - - -5- Method Delegates - -This strategy is used to override method implementations. -Given a method SomeClass.MethodName(), 1 or 2 methods are generated: -a- A copy of the original method named SomeClass.MethodName_Original(). - The content is the original method as-is from the reader. - This step is omitted if the method is native, since it has no Java implementation. -b- A brand new implementation of SomeClass.MethodName() which calls to a - non-existing static method named SomeClass_Delegate.MethodName(). - The implementation of this 'delegate' method is done in layoutlib_brigde. - -The delegate method is a static method. -If the original method is non-static, the delegate method receives the original 'this' -as its first argument. If the original method is an inner non-static method, it also -receives the inner 'this' as the second argument. - - - -- References - --------------- - - -The JVM Specification 2nd edition: - http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - -Understanding bytecode: - http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/ - -Bytecode opcode list: - http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings - -ASM user guide: - http://download.forge.objectweb.org/asm/asm-guide.pdf - - --- -end diff --git a/tools/layoutlib/create/manifest.txt b/tools/layoutlib/create/manifest.txt deleted file mode 100644 index 238e7f9..0000000 --- a/tools/layoutlib/create/manifest.txt +++ /dev/null @@ -1 +0,0 @@ -Main-Class: com.android.tools.layoutlib.create.Main diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java deleted file mode 100644 index 9a48ea6..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Denotes a method that has been converted to a delegate by layoutlib_create. - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface LayoutlibDelegate { -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/Nullable.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/Nullable.java deleted file mode 100644 index 0689c92..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/Nullable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Denotes a parameter or field can be null. - * <p/> - * When decorating a method call parameter, this denotes the parameter can - * legitimately be null and the method will gracefully deal with it. Typically used - * on optional parameters. - * <p/> - * When decorating a method, this denotes the method might legitimately return null. - * <p/> - * This is a marker annotation and it has no specific attributes. - */ -@Retention(RetentionPolicy.SOURCE) -public @interface Nullable { -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java deleted file mode 100644 index e4e016b..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Denotes that the class, method or field has its visibility relaxed so - * that unit tests can access it. - * <p/> - * The <code>visibility</code> argument can be used to specific what the original - * visibility should have been if it had not been made public or package-private for testing. - * The default is to consider the element private. - */ -@Retention(RetentionPolicy.SOURCE) -public @interface VisibleForTesting { - /** - * Intended visibility if the element had not been made public or package-private for - * testing. - */ - enum Visibility { - /** The element should be considered protected. */ - PROTECTED, - /** The element should be considered package-private. */ - PACKAGE, - /** The element should be considered private. */ - PRIVATE - } - - /** - * Intended visibility if the element had not been made public or package-private for testing. - * If not specified, one should assume the element originally intended to be private. - */ - Visibility visibility() default Visibility.PRIVATE; -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java deleted file mode 100644 index 412695f..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java +++ /dev/null @@ -1,845 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.signature.SignatureReader; -import org.objectweb.asm.signature.SignatureVisitor; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * Analyzes the input JAR using the ASM java bytecode manipulation library - * to list the desired classes and their dependencies. - */ -public class AsmAnalyzer { - - // Note: a bunch of stuff has package-level access for unit tests. Consider it private. - - /** Output logger. */ - private final Log mLog; - /** The input source JAR to parse. */ - private final List<String> mOsSourceJar; - /** The generator to fill with the class list and dependency list. */ - private final AsmGenerator mGen; - /** Keep all classes that derive from these one (these included). */ - private final String[] mDeriveFrom; - /** Glob patterns of classes to keep, e.g. "com.foo.*" */ - private final String[] mIncludeGlobs; - - /** - * Creates a new analyzer. - * - * @param log The log output. - * @param osJarPath The input source JARs to parse. - * @param gen The generator to fill with the class list and dependency list. - * @param deriveFrom Keep all classes that derive from these one (these included). - * @param includeGlobs Glob patterns of classes to keep, e.g. "com.foo.*" - * ("*" does not matches dots whilst "**" does, "." and "$" are interpreted as-is) - */ - public AsmAnalyzer(Log log, List<String> osJarPath, AsmGenerator gen, - String[] deriveFrom, String[] includeGlobs) { - mLog = log; - mGen = gen; - mOsSourceJar = osJarPath != null ? osJarPath : new ArrayList<String>(); - mDeriveFrom = deriveFrom != null ? deriveFrom : new String[0]; - mIncludeGlobs = includeGlobs != null ? includeGlobs : new String[0]; - } - - /** - * Starts the analysis using parameters from the constructor. - * Fills the generator with classes & dependencies found. - */ - public void analyze() throws IOException, LogAbortException { - - AsmAnalyzer visitor = this; - - Map<String, ClassReader> zipClasses = parseZip(mOsSourceJar); - mLog.info("Found %d classes in input JAR%s.", zipClasses.size(), - mOsSourceJar.size() > 1 ? "s" : ""); - - Map<String, ClassReader> found = findIncludes(zipClasses); - Map<String, ClassReader> deps = findDeps(zipClasses, found); - - if (mGen != null) { - mGen.setKeep(found); - mGen.setDeps(deps); - } - } - - /** - * Parses a JAR file and returns a list of all classes founds using a map - * class name => ASM ClassReader. Class names are in the form "android.view.View". - */ - Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException { - TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>(); - - for (String jarPath : jarPathList) { - ZipFile zip = new ZipFile(jarPath); - Enumeration<? extends ZipEntry> entries = zip.entries(); - ZipEntry entry; - while (entries.hasMoreElements()) { - entry = entries.nextElement(); - if (entry.getName().endsWith(".class")) { - ClassReader cr = new ClassReader(zip.getInputStream(entry)); - String className = classReaderToClassName(cr); - classes.put(className, cr); - } - } - } - - return classes; - } - - /** - * Utility that returns the fully qualified binary class name for a ClassReader. - * E.g. it returns something like android.view.View. - */ - static String classReaderToClassName(ClassReader classReader) { - if (classReader == null) { - return null; - } else { - return classReader.getClassName().replace('/', '.'); - } - } - - /** - * Utility that returns the fully qualified binary class name from a path-like FQCN. - * E.g. it returns android.view.View from android/view/View. - */ - static String internalToBinaryClassName(String className) { - if (className == null) { - return null; - } else { - return className.replace('/', '.'); - } - } - - /** - * Process the "includes" arrays. - * <p/> - * This updates the in_out_found map. - */ - Map<String, ClassReader> findIncludes(Map<String, ClassReader> zipClasses) - throws LogAbortException { - TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); - - mLog.debug("Find classes to include."); - - for (String s : mIncludeGlobs) { - findGlobs(s, zipClasses, found); - } - for (String s : mDeriveFrom) { - findClassesDerivingFrom(s, zipClasses, found); - } - - return found; - } - - - /** - * Uses ASM to find the class reader for the given FQCN class name. - * If found, insert it in the in_out_found map. - * Returns the class reader object. - */ - ClassReader findClass(String className, Map<String, ClassReader> zipClasses, - Map<String, ClassReader> inOutFound) throws LogAbortException { - ClassReader classReader = zipClasses.get(className); - if (classReader == null) { - throw new LogAbortException("Class %s not found by ASM in %s", - className, mOsSourceJar); - } - - inOutFound.put(className, classReader); - return classReader; - } - - /** - * Insert in the inOutFound map all classes found in zipClasses that match the - * given glob pattern. - * <p/> - * The glob pattern is not a regexp. It only accepts the "*" keyword to mean - * "anything but a period". The "." and "$" characters match themselves. - * The "**" keyword means everything including ".". - * <p/> - * Examples: - * <ul> - * <li>com.foo.* matches all classes in the package com.foo but NOT sub-packages. - * <li>com.foo*.*$Event matches all internal Event classes in a com.foo*.* class. - * </ul> - */ - void findGlobs(String globPattern, Map<String, ClassReader> zipClasses, - Map<String, ClassReader> inOutFound) throws LogAbortException { - // transforms the glob pattern in a regexp: - // - escape "." with "\." - // - replace "*" by "[^.]*" - // - escape "$" with "\$" - // - add end-of-line match $ - globPattern = globPattern.replaceAll("\\$", "\\\\\\$"); - globPattern = globPattern.replaceAll("\\.", "\\\\."); - // prevent ** from being altered by the next rule, then process the * rule and finally - // the real ** rule (which is now @) - globPattern = globPattern.replaceAll("\\*\\*", "@"); - globPattern = globPattern.replaceAll("\\*", "[^.]*"); - globPattern = globPattern.replaceAll("@", ".*"); - globPattern += "$"; - - Pattern regexp = Pattern.compile(globPattern); - - for (Entry<String, ClassReader> entry : zipClasses.entrySet()) { - String class_name = entry.getKey(); - if (regexp.matcher(class_name).matches()) { - findClass(class_name, zipClasses, inOutFound); - } - } - } - - /** - * Checks all the classes defined in the JarClassName instance and uses BCEL to - * determine if they are derived from the given FQCN super class name. - * Inserts the super class and all the class objects found in the map. - */ - void findClassesDerivingFrom(String super_name, Map<String, ClassReader> zipClasses, - Map<String, ClassReader> inOutFound) throws LogAbortException { - ClassReader super_clazz = findClass(super_name, zipClasses, inOutFound); - - for (Entry<String, ClassReader> entry : zipClasses.entrySet()) { - String className = entry.getKey(); - if (super_name.equals(className)) { - continue; - } - ClassReader classReader = entry.getValue(); - ClassReader parent_cr = classReader; - while (parent_cr != null) { - String parent_name = internalToBinaryClassName(parent_cr.getSuperName()); - if (parent_name == null) { - // not found - break; - } else if (super_name.equals(parent_name)) { - inOutFound.put(className, classReader); - break; - } - parent_cr = zipClasses.get(parent_name); - } - } - } - - /** - * Instantiates a new DependencyVisitor. Useful for unit tests. - */ - DependencyVisitor getVisitor(Map<String, ClassReader> zipClasses, - Map<String, ClassReader> inKeep, - Map<String, ClassReader> outKeep, - Map<String, ClassReader> inDeps, - Map<String, ClassReader> outDeps) { - return new DependencyVisitor(zipClasses, inKeep, outKeep, inDeps, outDeps); - } - - /** - * Finds all dependencies for all classes in keepClasses which are also - * listed in zipClasses. Returns a map of all the dependencies found. - */ - Map<String, ClassReader> findDeps(Map<String, ClassReader> zipClasses, - Map<String, ClassReader> inOutKeepClasses) { - - TreeMap<String, ClassReader> deps = new TreeMap<String, ClassReader>(); - TreeMap<String, ClassReader> new_deps = new TreeMap<String, ClassReader>(); - TreeMap<String, ClassReader> new_keep = new TreeMap<String, ClassReader>(); - TreeMap<String, ClassReader> temp = new TreeMap<String, ClassReader>(); - - DependencyVisitor visitor = getVisitor(zipClasses, - inOutKeepClasses, new_keep, - deps, new_deps); - - for (ClassReader cr : inOutKeepClasses.values()) { - cr.accept(visitor, 0 /* flags */); - } - - while (new_deps.size() > 0 || new_keep.size() > 0) { - deps.putAll(new_deps); - inOutKeepClasses.putAll(new_keep); - - temp.clear(); - temp.putAll(new_deps); - temp.putAll(new_keep); - new_deps.clear(); - new_keep.clear(); - mLog.debug("Found %1$d to keep, %2$d dependencies.", - inOutKeepClasses.size(), deps.size()); - - for (ClassReader cr : temp.values()) { - cr.accept(visitor, 0 /* flags */); - } - } - - mLog.info("Found %1$d classes to keep, %2$d class dependencies.", - inOutKeepClasses.size(), deps.size()); - - return deps; - } - - - - // ---------------------------------- - - /** - * Visitor to collect all the type dependencies from a class. - */ - public class DependencyVisitor extends ClassVisitor { - - /** All classes found in the source JAR. */ - private final Map<String, ClassReader> mZipClasses; - /** Classes from which dependencies are to be found. */ - private final Map<String, ClassReader> mInKeep; - /** Dependencies already known. */ - private final Map<String, ClassReader> mInDeps; - /** New dependencies found by this visitor. */ - private final Map<String, ClassReader> mOutDeps; - /** New classes to keep as-is found by this visitor. */ - private final Map<String, ClassReader> mOutKeep; - - /** - * Creates a new visitor that will find all the dependencies for the visited class. - * Types which are already in the zipClasses, keepClasses or inDeps are not marked. - * New dependencies are marked in outDeps. - * - * @param zipClasses All classes found in the source JAR. - * @param inKeep Classes from which dependencies are to be found. - * @param inDeps Dependencies already known. - * @param outDeps New dependencies found by this visitor. - */ - public DependencyVisitor(Map<String, ClassReader> zipClasses, - Map<String, ClassReader> inKeep, - Map<String, ClassReader> outKeep, - Map<String,ClassReader> inDeps, - Map<String,ClassReader> outDeps) { - super(Opcodes.ASM4); - mZipClasses = zipClasses; - mInKeep = inKeep; - mOutKeep = outKeep; - mInDeps = inDeps; - mOutDeps = outDeps; - } - - /** - * Considers the given class name as a dependency. - * If it does, add to the mOutDeps map. - */ - public void considerName(String className) { - if (className == null) { - return; - } - - className = internalToBinaryClassName(className); - - // exclude classes that have already been found - if (mInKeep.containsKey(className) || - mOutKeep.containsKey(className) || - mInDeps.containsKey(className) || - mOutDeps.containsKey(className)) { - return; - } - - // exclude classes that are not part of the JAR file being examined - ClassReader cr = mZipClasses.get(className); - if (cr == null) { - return; - } - - try { - // exclude classes that are part of the default JRE (the one executing this program) - if (getClass().getClassLoader().loadClass(className) != null) { - return; - } - } catch (ClassNotFoundException e) { - // ignore - } - - // accept this class: - // - android classes are added to dependencies - // - non-android classes are added to the list of classes to keep as-is (they don't need - // to be stubbed). - if (className.indexOf("android") >= 0) { // TODO make configurable - mOutDeps.put(className, cr); - } else { - mOutKeep.put(className, cr); - } - } - - /** - * Considers this array of names using considerName(). - */ - public void considerNames(String[] classNames) { - if (classNames != null) { - for (String className : classNames) { - considerName(className); - } - } - } - - /** - * Considers this signature or type signature by invoking the {@link SignatureVisitor} - * on it. - */ - public void considerSignature(String signature) { - if (signature != null) { - SignatureReader sr = new SignatureReader(signature); - // SignatureReader.accept will call accessType so we don't really have - // to differentiate where the signature comes from. - sr.accept(new MySignatureVisitor()); - } - } - - /** - * Considers this {@link Type}. For arrays, the element type is considered. - * If the type is an object, it's internal name is considered. - */ - public void considerType(Type t) { - if (t != null) { - if (t.getSort() == Type.ARRAY) { - t = t.getElementType(); - } - if (t.getSort() == Type.OBJECT) { - considerName(t.getInternalName()); - } - } - } - - /** - * Considers a descriptor string. The descriptor is converted to a {@link Type} - * and then considerType() is invoked. - */ - public void considerDesc(String desc) { - if (desc != null) { - try { - Type t = Type.getType(desc); - considerType(t); - } catch (ArrayIndexOutOfBoundsException e) { - // ignore, not a valid type. - } - } - } - - - // --------------------------------------------------- - // --- ClassVisitor, FieldVisitor - // --------------------------------------------------- - - // Visits a class header - @Override - public void visit(int version, int access, String name, - String signature, String superName, String[] interfaces) { - // signature is the signature of this class. May be null if the class is not a generic - // one, and does not extend or implement generic classes or interfaces. - - if (signature != null) { - considerSignature(signature); - } - - // superName is the internal of name of the super class (see getInternalName). - // For interfaces, the super class is Object. May be null but only for the Object class. - considerName(superName); - - // interfaces is the internal names of the class's interfaces (see getInternalName). - // May be null. - considerNames(interfaces); - } - - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - // desc is the class descriptor of the annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public void visitAttribute(Attribute attr) { - // pass - } - - // Visits the end of a class - @Override - public void visitEnd() { - // pass - } - - private class MyFieldVisitor extends FieldVisitor { - - public MyFieldVisitor() { - super(Opcodes.ASM4); - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - // desc is the class descriptor of the annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public void visitAttribute(Attribute attr) { - // pass - } - - // Visits the end of a class - @Override - public void visitEnd() { - // pass - } - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - // desc is the field's descriptor (see Type). - considerDesc(desc); - - // signature is the field's signature. May be null if the field's type does not use - // generic types. - considerSignature(signature); - - return new MyFieldVisitor(); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - // name is the internal name of an inner class (see getInternalName). - considerName(name); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - // desc is the method's descriptor (see Type). - considerDesc(desc); - // signature is the method's signature. May be null if the method parameters, return - // type and exceptions do not use generic types. - considerSignature(signature); - - return new MyMethodVisitor(); - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - // pass - } - - @Override - public void visitSource(String source, String debug) { - // pass - } - - - // --------------------------------------------------- - // --- MethodVisitor - // --------------------------------------------------- - - private class MyMethodVisitor extends MethodVisitor { - - public MyMethodVisitor() { - super(Opcodes.ASM4); - } - - - @Override - public AnnotationVisitor visitAnnotationDefault() { - return new MyAnnotationVisitor(); - } - - @Override - public void visitCode() { - // pass - } - - // field instruction - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - // name is the field's name. - considerName(name); - // desc is the field's descriptor (see Type). - considerDesc(desc); - } - - @Override - public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) { - // pass - } - - @Override - public void visitIincInsn(int var, int increment) { - // pass -- an IINC instruction - } - - @Override - public void visitInsn(int opcode) { - // pass -- a zero operand instruction - } - - @Override - public void visitIntInsn(int opcode, int operand) { - // pass -- a single int operand instruction - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - // pass -- a jump instruction - } - - @Override - public void visitLabel(Label label) { - // pass -- a label target - } - - // instruction to load a constant from the stack - @Override - public void visitLdcInsn(Object cst) { - if (cst instanceof Type) { - considerType((Type) cst); - } - } - - @Override - public void visitLineNumber(int line, Label start) { - // pass - } - - @Override - public void visitLocalVariable(String name, String desc, - String signature, Label start, Label end, int index) { - // desc is the type descriptor of this local variable. - considerDesc(desc); - // signature is the type signature of this local variable. May be null if the local - // variable type does not use generic types. - considerSignature(signature); - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - // pass -- a lookup switch instruction - } - - @Override - public void visitMaxs(int maxStack, int maxLocals) { - // pass - } - - // instruction that invokes a method - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) { - - // owner is the internal name of the method's owner class - considerName(owner); - // desc is the method's descriptor (see Type). - considerDesc(desc); - } - - // instruction multianewarray, whatever that is - @Override - public void visitMultiANewArrayInsn(String desc, int dims) { - - // desc an array type descriptor. - considerDesc(desc); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, - boolean visible) { - // desc is the class descriptor of the annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { - // pass -- table switch instruction - - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - // type is the internal name of the type of exceptions handled by the handler, - // or null to catch any exceptions (for "finally" blocks). - considerName(type); - } - - // type instruction - @Override - public void visitTypeInsn(int opcode, String type) { - // type is the operand of the instruction to be visited. This operand must be the - // internal name of an object or array class. - considerName(type); - } - - @Override - public void visitVarInsn(int opcode, int var) { - // pass -- local variable instruction - } - } - - private class MySignatureVisitor extends SignatureVisitor { - - public MySignatureVisitor() { - super(Opcodes.ASM4); - } - - // --------------------------------------------------- - // --- SignatureVisitor - // --------------------------------------------------- - - private String mCurrentSignatureClass = null; - - // Starts the visit of a signature corresponding to a class or interface type - @Override - public void visitClassType(String name) { - mCurrentSignatureClass = name; - considerName(name); - } - - // Visits an inner class - @Override - public void visitInnerClassType(String name) { - if (mCurrentSignatureClass != null) { - mCurrentSignatureClass += "$" + name; - considerName(mCurrentSignatureClass); - } - } - - @Override - public SignatureVisitor visitArrayType() { - return new MySignatureVisitor(); - } - - @Override - public void visitBaseType(char descriptor) { - // pass -- a primitive type, ignored - } - - @Override - public SignatureVisitor visitClassBound() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitExceptionType() { - return new MySignatureVisitor(); - } - - @Override - public void visitFormalTypeParameter(String name) { - // pass - } - - @Override - public SignatureVisitor visitInterface() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitInterfaceBound() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitParameterType() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitReturnType() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitSuperclass() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitTypeArgument(char wildcard) { - return new MySignatureVisitor(); - } - - @Override - public void visitTypeVariable(String name) { - // pass - } - - @Override - public void visitTypeArgument() { - // pass - } - } - - - // --------------------------------------------------- - // --- AnnotationVisitor - // --------------------------------------------------- - - private class MyAnnotationVisitor extends AnnotationVisitor { - - public MyAnnotationVisitor() { - super(Opcodes.ASM4); - } - - // Visits a primitive value of an annotation - @Override - public void visit(String name, Object value) { - // value is the actual value, whose type must be Byte, Boolean, Character, Short, - // Integer, Long, Float, Double, String or Type - if (value instanceof Type) { - considerType((Type) value); - } - } - - @Override - public AnnotationVisitor visitAnnotation(String name, String desc) { - // desc is the class descriptor of the nested annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public AnnotationVisitor visitArray(String name) { - return new MyAnnotationVisitor(); - } - - @Override - public void visitEnum(String name, String desc, String value) { - // desc is the class descriptor of the enumeration class. - considerDesc(desc); - } - } - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java deleted file mode 100644 index a9ede26..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; - -/** - * Class that generates a new JAR from a list of classes, some of which are to be kept as-is - * and some of which are to be stubbed partially or totally. - */ -public class AsmGenerator { - - /** Output logger. */ - private final Log mLog; - /** The path of the destination JAR to create. */ - private final String mOsDestJar; - /** List of classes to inject in the final JAR from _this_ archive. */ - private final Class<?>[] mInjectClasses; - /** The set of methods to stub out. */ - private final Set<String> mStubMethods; - /** All classes to output as-is, except if they have native methods. */ - private Map<String, ClassReader> mKeep; - /** All dependencies that must be completely stubbed. */ - private Map<String, ClassReader> mDeps; - /** Counter of number of classes renamed during transform. */ - private int mRenameCount; - /** FQCN Names of the classes to rename: map old-FQCN => new-FQCN */ - private final HashMap<String, String> mRenameClasses; - /** FQCN Names of "old" classes that were NOT renamed. This starts with the full list of - * old-FQCN to rename and they get erased as they get renamed. At the end, classes still - * left here are not in the code base anymore and thus were not renamed. */ - private HashSet<String> mClassesNotRenamed; - /** A map { FQCN => set { list of return types to delete from the FQCN } }. */ - private HashMap<String, Set<String>> mDeleteReturns; - /** A map { FQCN => set { method names } } of methods to rewrite as delegates. - * The special name {@link DelegateClassAdapter#ALL_NATIVES} can be used as in internal set. */ - private final HashMap<String, Set<String>> mDelegateMethods; - - /** - * Creates a new generator that can generate the output JAR with the stubbed classes. - * - * @param log Output logger. - * @param osDestJar The path of the destination JAR to create. - * @param createInfo Creation parameters. Must not be null. - */ - public AsmGenerator(Log log, String osDestJar, ICreateInfo createInfo) { - mLog = log; - mOsDestJar = osDestJar; - mInjectClasses = createInfo.getInjectedClasses(); - mStubMethods = new HashSet<String>(Arrays.asList(createInfo.getOverriddenMethods())); - - // Create the map/set of methods to change to delegates - mDelegateMethods = new HashMap<String, Set<String>>(); - for (String signature : createInfo.getDelegateMethods()) { - int pos = signature.indexOf('#'); - if (pos <= 0 || pos >= signature.length() - 1) { - continue; - } - String className = binaryToInternalClassName(signature.substring(0, pos)); - String methodName = signature.substring(pos + 1); - Set<String> methods = mDelegateMethods.get(className); - if (methods == null) { - methods = new HashSet<String>(); - mDelegateMethods.put(className, methods); - } - methods.add(methodName); - } - for (String className : createInfo.getDelegateClassNatives()) { - className = binaryToInternalClassName(className); - Set<String> methods = mDelegateMethods.get(className); - if (methods == null) { - methods = new HashSet<String>(); - mDelegateMethods.put(className, methods); - } - methods.add(DelegateClassAdapter.ALL_NATIVES); - } - - // Create the map of classes to rename. - mRenameClasses = new HashMap<String, String>(); - mClassesNotRenamed = new HashSet<String>(); - String[] renameClasses = createInfo.getRenamedClasses(); - int n = renameClasses.length; - for (int i = 0; i < n; i += 2) { - assert i + 1 < n; - // The ASM class names uses "/" separators, whereas regular FQCN use "." - String oldFqcn = binaryToInternalClassName(renameClasses[i]); - String newFqcn = binaryToInternalClassName(renameClasses[i + 1]); - mRenameClasses.put(oldFqcn, newFqcn); - mClassesNotRenamed.add(oldFqcn); - } - - // create the map of renamed class -> return type of method to delete. - mDeleteReturns = new HashMap<String, Set<String>>(); - String[] deleteReturns = createInfo.getDeleteReturns(); - Set<String> returnTypes = null; - String renamedClass = null; - for (String className : deleteReturns) { - // if we reach the end of a section, add it to the main map - if (className == null) { - if (returnTypes != null) { - mDeleteReturns.put(renamedClass, returnTypes); - } - - renamedClass = null; - continue; - } - - // if the renamed class is null, this is the beginning of a section - if (renamedClass == null) { - renamedClass = binaryToInternalClassName(className); - continue; - } - - // just a standard return type, we add it to the list. - if (returnTypes == null) { - returnTypes = new HashSet<String>(); - } - returnTypes.add(binaryToInternalClassName(className)); - } - } - - /** - * Returns the list of classes that have not been renamed yet. - * <p/> - * The names are "internal class names" rather than FQCN, i.e. they use "/" instead "." - * as package separators. - */ - public Set<String> getClassesNotRenamed() { - return mClassesNotRenamed; - } - - /** - * Utility that returns the internal ASM class name from a fully qualified binary class - * name. E.g. it returns android/view/View from android.view.View. - */ - String binaryToInternalClassName(String className) { - if (className == null) { - return null; - } else { - return className.replace('.', '/'); - } - } - - /** Sets the map of classes to output as-is, except if they have native methods */ - public void setKeep(Map<String, ClassReader> keep) { - mKeep = keep; - } - - /** Sets the map of dependencies that must be completely stubbed */ - public void setDeps(Map<String, ClassReader> deps) { - mDeps = deps; - } - - /** Gets the map of classes to output as-is, except if they have native methods */ - public Map<String, ClassReader> getKeep() { - return mKeep; - } - - /** Gets the map of dependencies that must be completely stubbed */ - public Map<String, ClassReader> getDeps() { - return mDeps; - } - - /** Generates the final JAR */ - public void generate() throws FileNotFoundException, IOException { - TreeMap<String, byte[]> all = new TreeMap<String, byte[]>(); - - for (Class<?> clazz : mInjectClasses) { - String name = classToEntryPath(clazz); - InputStream is = ClassLoader.getSystemResourceAsStream(name); - ClassReader cr = new ClassReader(is); - byte[] b = transform(cr, true /* stubNativesOnly */); - name = classNameToEntryPath(transformName(cr.getClassName())); - all.put(name, b); - } - - for (Entry<String, ClassReader> entry : mDeps.entrySet()) { - ClassReader cr = entry.getValue(); - byte[] b = transform(cr, true /* stubNativesOnly */); - String name = classNameToEntryPath(transformName(cr.getClassName())); - all.put(name, b); - } - - for (Entry<String, ClassReader> entry : mKeep.entrySet()) { - ClassReader cr = entry.getValue(); - byte[] b = transform(cr, true /* stubNativesOnly */); - String name = classNameToEntryPath(transformName(cr.getClassName())); - all.put(name, b); - } - - mLog.info("# deps classes: %d", mDeps.size()); - mLog.info("# keep classes: %d", mKeep.size()); - mLog.info("# renamed : %d", mRenameCount); - - createJar(new FileOutputStream(mOsDestJar), all); - mLog.info("Created JAR file %s", mOsDestJar); - } - - /** - * Writes the JAR file. - * - * @param outStream The file output stream were to write the JAR. - * @param all The map of all classes to output. - * @throws IOException if an I/O error has occurred - */ - void createJar(FileOutputStream outStream, Map<String,byte[]> all) throws IOException { - JarOutputStream jar = new JarOutputStream(outStream); - for (Entry<String, byte[]> entry : all.entrySet()) { - String name = entry.getKey(); - JarEntry jar_entry = new JarEntry(name); - jar.putNextEntry(jar_entry); - jar.write(entry.getValue()); - jar.closeEntry(); - } - jar.flush(); - jar.close(); - } - - /** - * Utility method that converts a fully qualified java name into a JAR entry path - * e.g. for the input "android.view.View" it returns "android/view/View.class" - */ - String classNameToEntryPath(String className) { - return className.replaceAll("\\.", "/").concat(".class"); - } - - /** - * Utility method to get the JAR entry path from a Class name. - * e.g. it returns someting like "com/foo/OuterClass$InnerClass1$InnerClass2.class" - */ - private String classToEntryPath(Class<?> clazz) { - String name = ""; - Class<?> parent; - while ((parent = clazz.getEnclosingClass()) != null) { - name = "$" + clazz.getSimpleName() + name; - clazz = parent; - } - return classNameToEntryPath(clazz.getCanonicalName() + name); - } - - /** - * Transforms a class. - * <p/> - * There are 3 kind of transformations: - * - * 1- For "mock" dependencies classes, we want to remove all code from methods and replace - * by a stub. Native methods must be implemented with this stub too. Abstract methods are - * left intact. Modified classes must be overridable (non-private, non-final). - * Native methods must be made non-final, non-private. - * - * 2- For "keep" classes, we want to rewrite all native methods as indicated above. - * If a class has native methods, it must also be made non-private, non-final. - * - * Note that unfortunately static methods cannot be changed to non-static (since static and - * non-static are invoked differently.) - */ - byte[] transform(ClassReader cr, boolean stubNativesOnly) { - - boolean hasNativeMethods = hasNativeMethods(cr); - - // Get the class name, as an internal name (e.g. com/android/SomeClass$InnerClass) - String className = cr.getClassName(); - - String newName = transformName(className); - // transformName returns its input argument if there's no need to rename the class - if (newName != className) { - mRenameCount++; - // This class is being renamed, so remove it from the list of classes not renamed. - mClassesNotRenamed.remove(className); - } - - mLog.debug("Transform %s%s%s%s", className, - newName == className ? "" : " (renamed to " + newName + ")", - hasNativeMethods ? " -- has natives" : "", - stubNativesOnly ? " -- stub natives only" : ""); - - // Rewrite the new class from scratch, without reusing the constant pool from the - // original class reader. - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - - ClassVisitor rv = cw; - if (newName != className) { - rv = new RenameClassAdapter(cw, className, newName); - } - - ClassVisitor cv = new TransformClassAdapter(mLog, mStubMethods, - mDeleteReturns.get(className), - newName, rv, - stubNativesOnly, stubNativesOnly || hasNativeMethods); - - Set<String> delegateMethods = mDelegateMethods.get(className); - if (delegateMethods != null && !delegateMethods.isEmpty()) { - // If delegateMethods only contains one entry ALL_NATIVES and the class is - // known to have no native methods, just skip this step. - if (hasNativeMethods || - !(delegateMethods.size() == 1 && - delegateMethods.contains(DelegateClassAdapter.ALL_NATIVES))) { - cv = new DelegateClassAdapter(mLog, cv, className, delegateMethods); - } - } - - cr.accept(cv, 0 /* flags */); - return cw.toByteArray(); - } - - /** - * Should this class be renamed, this returns the new name. Otherwise it returns the - * original name. - * - * @param className The internal ASM name of the class that may have to be renamed - * @return A new transformed name or the original input argument. - */ - String transformName(String className) { - String newName = mRenameClasses.get(className); - if (newName != null) { - return newName; - } - int pos = className.indexOf('$'); - if (pos > 0) { - // Is this an inner class of a renamed class? - String base = className.substring(0, pos); - newName = mRenameClasses.get(base); - if (newName != null) { - return newName + className.substring(pos); - } - } - - return className; - } - - /** - * Returns true if a class has any native methods. - */ - boolean hasNativeMethods(ClassReader cr) { - ClassHasNativeVisitor cv = new ClassHasNativeVisitor(); - cr.accept(cv, 0 /* flags */); - return cv.hasNativeMethods(); - } - -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java deleted file mode 100644 index 2c955fd..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import com.android.tools.layoutlib.annotations.VisibleForTesting; -import com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -/** - * Indicates if a class contains any native methods. - */ -public class ClassHasNativeVisitor extends ClassVisitor { - public ClassHasNativeVisitor() { - super(Opcodes.ASM4); - } - - private boolean mHasNativeMethods = false; - - public boolean hasNativeMethods() { - return mHasNativeMethods; - } - - @VisibleForTesting(visibility=Visibility.PRIVATE) - protected void setHasNativeMethods(boolean hasNativeMethods, String methodName) { - mHasNativeMethods = hasNativeMethods; - } - - @Override - public void visit(int version, int access, String name, String signature, - String superName, String[] interfaces) { - // pass - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - // pass - return null; - } - - @Override - public void visitAttribute(Attribute attr) { - // pass - } - - @Override - public void visitEnd() { - // pass - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - // pass - return null; - } - - @Override - public void visitInnerClass(String name, String outerName, - String innerName, int access) { - // pass - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - if ((access & Opcodes.ACC_NATIVE) != 0) { - setHasNativeMethods(true, name); - } - return null; - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - // pass - } - - @Override - public void visitSource(String source, String debug) { - // pass - } - -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java deleted file mode 100644 index d955040..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Describes the work to be done by {@link AsmGenerator}. - */ -public final class CreateInfo implements ICreateInfo { - - /** - * Returns the list of class from layoutlib_create to inject in layoutlib. - * The list can be empty but must not be null. - */ - @Override - public Class<?>[] getInjectedClasses() { - return INJECTED_CLASSES; - } - - /** - * Returns the list of methods to rewrite as delegates. - * The list can be empty but must not be null. - */ - @Override - public String[] getDelegateMethods() { - return DELEGATE_METHODS; - } - - /** - * Returns the list of classes on which to delegate all native methods. - * The list can be empty but must not be null. - */ - @Override - public String[] getDelegateClassNatives() { - return DELEGATE_CLASS_NATIVES; - } - - /** - * Returns The list of methods to stub out. Each entry must be in the form - * "package.package.OuterClass$InnerClass#MethodName". - * The list can be empty but must not be null. - * <p/> - * This usage is deprecated. Please use method 'delegates' instead. - */ - @Override - public String[] getOverriddenMethods() { - return OVERRIDDEN_METHODS; - } - - /** - * Returns the list of classes to rename, must be an even list: the binary FQCN - * of class to replace followed by the new FQCN. - * The list can be empty but must not be null. - */ - @Override - public String[] getRenamedClasses() { - return RENAMED_CLASSES; - } - - /** - * Returns the list of classes for which the methods returning them should be deleted. - * The array contains a list of null terminated section starting with the name of the class - * to rename in which the methods are deleted, followed by a list of return types identifying - * the methods to delete. - * The list can be empty but must not be null. - */ - @Override - public String[] getDeleteReturns() { - return DELETE_RETURNS; - } - - //----- - - /** - * The list of class from layoutlib_create to inject in layoutlib. - */ - private final static Class<?>[] INJECTED_CLASSES = new Class<?>[] { - OverrideMethod.class, - MethodListener.class, - MethodAdapter.class, - ICreateInfo.class, - CreateInfo.class, - LayoutlibDelegate.class - }; - - /** - * The list of methods to rewrite as delegates. - */ - public final static String[] DELEGATE_METHODS = new String[] { - "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;", - "android.content.res.Resources$Theme#obtainStyledAttributes", - "android.content.res.Resources$Theme#resolveAttribute", - "android.content.res.TypedArray#getValueAt", - "android.graphics.BitmapFactory#finishDecode", - "android.os.Handler#sendMessageAtTime", - "android.os.HandlerThread#run", - "android.os.Build#getString", - "android.text.format.DateFormat#is24HourFormat", - "android.view.Choreographer#getRefreshRate", - "android.view.Display#updateDisplayInfoLocked", - "android.view.LayoutInflater#rInflate", - "android.view.LayoutInflater#parseInclude", - "android.view.View#isInEditMode", - "android.view.ViewRootImpl#isInTouchMode", - "android.view.WindowManagerGlobal#getWindowManagerService", - "android.view.inputmethod.InputMethodManager#getInstance", - "com.android.internal.util.XmlUtils#convertValueToInt", - "com.android.internal.textservice.ITextServicesManager$Stub#asInterface", - }; - - /** - * The list of classes on which to delegate all native methods. - */ - public final static String[] DELEGATE_CLASS_NATIVES = new String[] { - "android.animation.PropertyValuesHolder", - "android.graphics.AvoidXfermode", - "android.graphics.Bitmap", - "android.graphics.BitmapFactory", - "android.graphics.BitmapShader", - "android.graphics.BlurMaskFilter", - "android.graphics.Canvas", - "android.graphics.ColorFilter", - "android.graphics.ColorMatrixColorFilter", - "android.graphics.ComposePathEffect", - "android.graphics.ComposeShader", - "android.graphics.CornerPathEffect", - "android.graphics.DashPathEffect", - "android.graphics.DiscretePathEffect", - "android.graphics.DrawFilter", - "android.graphics.EmbossMaskFilter", - "android.graphics.LayerRasterizer", - "android.graphics.LightingColorFilter", - "android.graphics.LinearGradient", - "android.graphics.MaskFilter", - "android.graphics.Matrix", - "android.graphics.NinePatch", - "android.graphics.Paint", - "android.graphics.PaintFlagsDrawFilter", - "android.graphics.Path", - "android.graphics.PathDashPathEffect", - "android.graphics.PathEffect", - "android.graphics.PixelXorXfermode", - "android.graphics.PorterDuffColorFilter", - "android.graphics.PorterDuffXfermode", - "android.graphics.RadialGradient", - "android.graphics.Rasterizer", - "android.graphics.Region", - "android.graphics.Shader", - "android.graphics.SumPathEffect", - "android.graphics.SweepGradient", - "android.graphics.Typeface", - "android.graphics.Xfermode", - "android.os.SystemClock", - "android.text.AndroidBidi", - "android.util.FloatMath", - "android.view.Display", - "libcore.icu.ICU", - }; - - /** - * The list of methods to stub out. Each entry must be in the form - * "package.package.OuterClass$InnerClass#MethodName". - * This usage is deprecated. Please use method 'delegates' instead. - */ - private final static String[] OVERRIDDEN_METHODS = new String[] { - }; - - /** - * The list of classes to rename, must be an even list: the binary FQCN - * of class to replace followed by the new FQCN. - */ - private final static String[] RENAMED_CLASSES = - new String[] { - "android.os.ServiceManager", "android.os._Original_ServiceManager", - "android.util.LruCache", "android.util._Original_LruCache", - "android.view.SurfaceView", "android.view._Original_SurfaceView", - "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager", - "android.webkit.WebView", "android.webkit._Original_WebView", - "com.android.internal.policy.PolicyManager", "com.android.internal.policy._Original_PolicyManager", - }; - - /** - * List of classes for which the methods returning them should be deleted. - * The array contains a list of null terminated section starting with the name of the class - * to rename in which the methods are deleted, followed by a list of return types identifying - * the methods to delete. - */ - private final static String[] DELETE_RETURNS = - new String[] { - null }; // separator, for next class/methods list. -} - diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java deleted file mode 100644 index 927be97..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -import java.util.Set; - -/** - * A {@link DelegateClassAdapter} can transform some methods from a class into - * delegates that defer the call to an associated delegate class. - * <p/> - * This is used to override specific methods and or all native methods in classes. - */ -public class DelegateClassAdapter extends ClassVisitor { - - /** Suffix added to original methods. */ - private static final String ORIGINAL_SUFFIX = "_Original"; - private static String CONSTRUCTOR = "<init>"; - private static String CLASS_INIT = "<clinit>"; - - public final static String ALL_NATIVES = "<<all_natives>>"; - - private final String mClassName; - private final Set<String> mDelegateMethods; - private final Log mLog; - - /** - * Creates a new {@link DelegateClassAdapter} that can transform some methods - * from a class into delegates that defer the call to an associated delegate class. - * <p/> - * This is used to override specific methods and or all native methods in classes. - * - * @param log The logger object. Must not be null. - * @param cv the class visitor to which this adapter must delegate calls. - * @param className The internal class name of the class to visit, - * e.g. <code>com/android/SomeClass$InnerClass</code>. - * @param delegateMethods The set of method names to modify and/or the - * special constant {@link #ALL_NATIVES} to convert all native methods. - */ - public DelegateClassAdapter(Log log, - ClassVisitor cv, - String className, - Set<String> delegateMethods) { - super(Opcodes.ASM4, cv); - mLog = log; - mClassName = className; - mDelegateMethods = delegateMethods; - } - - //---------------------------------- - // Methods from the ClassAdapter - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - - boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; - boolean isNative = (access & Opcodes.ACC_NATIVE) != 0; - - boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) || - mDelegateMethods.contains(name); - - if (!useDelegate) { - // Not creating a delegate for this method, pass it as-is from the reader - // to the writer. - return super.visitMethod(access, name, desc, signature, exceptions); - } - - if (useDelegate) { - if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) { - // We don't currently support generating delegates for constructors. - throw new UnsupportedOperationException( - String.format( - "Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)", //$NON-NLS-1$ - mClassName, name, desc)); - } - } - - if (isNative) { - // Remove native flag - access = access & ~Opcodes.ACC_NATIVE; - MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions); - - DelegateMethodAdapter2 a = new DelegateMethodAdapter2( - mLog, null /*mwOriginal*/, mwDelegate, mClassName, name, desc, isStatic); - - // A native has no code to visit, so we need to generate it directly. - a.generateDelegateCode(); - - return mwDelegate; - } - - // Given a non-native SomeClass.MethodName(), we want to generate 2 methods: - // - A copy of the original method named SomeClass.MethodName_Original(). - // The content is the original method as-is from the reader. - // - A brand new implementation of SomeClass.MethodName() which calls to a - // non-existing method named SomeClass_Delegate.MethodName(). - // The implementation of this 'delegate' method is done in layoutlib_brigde. - - int accessDelegate = access; - // change access to public for the original one - if (Main.sOptions.generatePublicAccess) { - access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); - access |= Opcodes.ACC_PUBLIC; - } - - MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX, - desc, signature, exceptions); - MethodVisitor mwDelegate = super.visitMethod(accessDelegate, name, - desc, signature, exceptions); - - DelegateMethodAdapter2 a = new DelegateMethodAdapter2( - mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStatic); - return a; - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java deleted file mode 100644 index 0000b22..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import java.util.ArrayList; - -/** - * This method adapter generates delegate methods. - * <p/> - * Given a method {@code SomeClass.MethodName()}, this generates 1 or 2 methods: - * <ul> - * <li> A copy of the original method named {@code SomeClass.MethodName_Original()}. - * The content is the original method as-is from the reader. - * This step is omitted if the method is native, since it has no Java implementation. - * <li> A brand new implementation of {@code SomeClass.MethodName()} which calls to a - * non-existing method named {@code SomeClass_Delegate.MethodName()}. - * The implementation of this 'delegate' method is done in layoutlib_brigde. - * </ul> - * A method visitor is generally constructed to generate a single method; however - * here we might want to generate one or two depending on the context. To achieve - * that, the visitor here generates the 'original' method and acts as a no-op if - * no such method exists (e.g. when the original is a native method). - * The delegate method is generated after the {@code visitEnd} of the original method - * or by having the class adapter <em>directly</em> call {@link #generateDelegateCode()} - * for native methods. - * <p/> - * When generating the 'delegate', the implementation generates a call to a class - * class named <code><className>_Delegate</code> with static methods matching - * the methods to be overridden here. The methods have the same return type. - * The argument type list is the same except the "this" reference is passed first - * for non-static methods. - * <p/> - * A new annotation is added to these 'delegate' methods so that we can easily find them - * for automated testing. - * <p/> - * This class isn't intended to be generic or reusable. - * It is called by {@link DelegateClassAdapter}, which takes care of properly initializing - * the two method writers for the original and the delegate class, as needed, with their - * expected names. - * <p/> - * The class adapter also takes care of calling {@link #generateDelegateCode()} directly for - * a native and use the visitor pattern for non-natives. - * Note that native methods have, by definition, no code so there's nothing a visitor - * can visit. - * <p/> - * Instances of this class are not re-usable. - * The class adapter creates a new instance for each method. - */ -class DelegateMethodAdapter2 extends MethodVisitor { - - /** Suffix added to delegate classes. */ - public static final String DELEGATE_SUFFIX = "_Delegate"; - - /** The parent method writer to copy of the original method. - * Null when dealing with a native original method. */ - private MethodVisitor mOrgWriter; - /** The parent method writer to generate the delegating method. Never null. */ - private MethodVisitor mDelWriter; - /** The original method descriptor (return type + argument types.) */ - private String mDesc; - /** True if the original method is static. */ - private final boolean mIsStatic; - /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */ - private final String mClassName; - /** The method name. */ - private final String mMethodName; - /** Logger object. */ - private final Log mLog; - - /** Array used to capture the first line number information from the original method - * and duplicate it in the delegate. */ - private Object[] mDelegateLineNumber; - - /** - * Creates a new {@link DelegateMethodAdapter2} that will transform this method - * into a delegate call. - * <p/> - * See {@link DelegateMethodAdapter2} for more details. - * - * @param log The logger object. Must not be null. - * @param mvOriginal The parent method writer to copy of the original method. - * Must be {@code null} when dealing with a native original method. - * @param mvDelegate The parent method writer to generate the delegating method. - * Must never be null. - * @param className The internal class name of the class to visit, - * e.g. <code>com/android/SomeClass$InnerClass</code>. - * @param methodName The simple name of the method. - * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} + - * {@link Type#getArgumentTypes(String)}) - * @param isStatic True if the method is declared static. - */ - public DelegateMethodAdapter2(Log log, - MethodVisitor mvOriginal, - MethodVisitor mvDelegate, - String className, - String methodName, - String desc, - boolean isStatic) { - super(Opcodes.ASM4); - mLog = log; - mOrgWriter = mvOriginal; - mDelWriter = mvDelegate; - mClassName = className; - mMethodName = methodName; - mDesc = desc; - mIsStatic = isStatic; - } - - /** - * Generates the new code for the method. - * <p/> - * For native methods, this must be invoked directly by {@link DelegateClassAdapter} - * (since they have no code to visit). - * <p/> - * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to - * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern - * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then - * this method will be invoked from {@link MethodVisitor#visitEnd()}. - */ - public void generateDelegateCode() { - /* - * The goal is to generate a call to a static delegate method. - * If this method is non-static, the first parameter will be 'this'. - * All the parameters must be passed and then the eventual return type returned. - * - * Example, let's say we have a method such as - * public void myMethod(int a, Object b, ArrayList<String> c) { ... } - * - * We'll want to create a body that calls a delegate method like this: - * TheClass_Delegate.myMethod(this, a, b, c); - * - * If the method is non-static and the class name is an inner class (e.g. has $ in its - * last segment), we want to push the 'this' of the outer class first: - * OuterClass_InnerClass_Delegate.myMethod( - * OuterClass.this, - * OuterClass$InnerClass.this, - * a, b, c); - * - * Only one level of inner class is supported right now, for simplicity and because - * we don't need more. - * - * The generated class name is the current class name with "_Delegate" appended to it. - * One thing to realize is that we don't care about generics -- since generic types - * are erased at build time, they have no influence on the method name being called. - */ - - // Add our annotation - AnnotationVisitor aw = mDelWriter.visitAnnotation( - Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), - true); // visible at runtime - if (aw != null) { - aw.visitEnd(); - } - - mDelWriter.visitCode(); - - if (mDelegateLineNumber != null) { - Object[] p = mDelegateLineNumber; - mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]); - } - - ArrayList<Type> paramTypes = new ArrayList<Type>(); - String delegateClassName = mClassName + DELEGATE_SUFFIX; - boolean pushedArg0 = false; - int maxStack = 0; - - // Check if the last segment of the class name has inner an class. - // Right now we only support one level of inner classes. - Type outerType = null; - int slash = mClassName.lastIndexOf('/'); - int dol = mClassName.lastIndexOf('$'); - if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) { - String outerClass = mClassName.substring(0, dol); - outerType = Type.getObjectType(outerClass); - - // Change a delegate class name to "com/foo/Outer_Inner_Delegate" - delegateClassName = delegateClassName.replace('$', '_'); - } - - // For an instance method (e.g. non-static), push the 'this' preceded - // by the 'this' of any outer class, if any. - if (!mIsStatic) { - - if (outerType != null) { - // The first-level inner class has a package-protected member called 'this$0' - // that points to the outer class. - - // Push this.getField("this$0") on the call stack. - mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this - mDelWriter.visitFieldInsn(Opcodes.GETFIELD, - mClassName, // class where the field is defined - "this$0", // field name - outerType.getDescriptor()); // type of the field - maxStack++; - paramTypes.add(outerType); - - } - - // Push "this" for the instance method, which is always ALOAD 0 - mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); - maxStack++; - pushedArg0 = true; - paramTypes.add(Type.getObjectType(mClassName)); - } - - // Push all other arguments. Start at arg 1 if we already pushed 'this' above. - Type[] argTypes = Type.getArgumentTypes(mDesc); - int maxLocals = pushedArg0 ? 1 : 0; - for (Type t : argTypes) { - int size = t.getSize(); - mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals); - maxLocals += size; - maxStack += size; - paramTypes.add(t); - } - - // Construct the descriptor of the delegate based on the parameters - // we pushed on the call stack. The return type remains unchanged. - String desc = Type.getMethodDescriptor( - Type.getReturnType(mDesc), - paramTypes.toArray(new Type[paramTypes.size()])); - - // Invoke the static delegate - mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC, - delegateClassName, - mMethodName, - desc); - - Type returnType = Type.getReturnType(mDesc); - mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); - - mDelWriter.visitMaxs(maxStack, maxLocals); - mDelWriter.visitEnd(); - - // For debugging now. Maybe we should collect these and store them in - // a text file for helping create the delegates. We could also compare - // the text file to a golden and break the build on unsupported changes - // or regressions. Even better we could fancy-print something that looks - // like the expected Java method declaration. - mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc); - } - - /* Pass down to visitor writer. In this implementation, either do nothing. */ - @Override - public void visitCode() { - if (mOrgWriter != null) { - mOrgWriter.visitCode(); - } - } - - /* - * visitMaxs is called just before visitEnd if there was any code to rewrite. - */ - @Override - public void visitMaxs(int maxStack, int maxLocals) { - if (mOrgWriter != null) { - mOrgWriter.visitMaxs(maxStack, maxLocals); - } - } - - /** End of visiting. Generate the delegating code. */ - @Override - public void visitEnd() { - if (mOrgWriter != null) { - mOrgWriter.visitEnd(); - } - generateDelegateCode(); - } - - /* Writes all annotation from the original method. */ - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - if (mOrgWriter != null) { - return mOrgWriter.visitAnnotation(desc, visible); - } else { - return null; - } - } - - /* Writes all annotation default values from the original method. */ - @Override - public AnnotationVisitor visitAnnotationDefault() { - if (mOrgWriter != null) { - return mOrgWriter.visitAnnotationDefault(); - } else { - return null; - } - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, - boolean visible) { - if (mOrgWriter != null) { - return mOrgWriter.visitParameterAnnotation(parameter, desc, visible); - } else { - return null; - } - } - - /* Writes all attributes from the original method. */ - @Override - public void visitAttribute(Attribute attr) { - if (mOrgWriter != null) { - mOrgWriter.visitAttribute(attr); - } - } - - /* - * Only writes the first line number present in the original code so that source - * viewers can direct to the correct method, even if the content doesn't match. - */ - @Override - public void visitLineNumber(int line, Label start) { - // Capture the first line values for the new delegate method - if (mDelegateLineNumber == null) { - mDelegateLineNumber = new Object[] { line, start }; - } - if (mOrgWriter != null) { - mOrgWriter.visitLineNumber(line, start); - } - } - - @Override - public void visitInsn(int opcode) { - if (mOrgWriter != null) { - mOrgWriter.visitInsn(opcode); - } - } - - @Override - public void visitLabel(Label label) { - if (mOrgWriter != null) { - mOrgWriter.visitLabel(label); - } - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - if (mOrgWriter != null) { - mOrgWriter.visitTryCatchBlock(start, end, handler, type); - } - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) { - if (mOrgWriter != null) { - mOrgWriter.visitMethodInsn(opcode, owner, name, desc); - } - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - if (mOrgWriter != null) { - mOrgWriter.visitFieldInsn(opcode, owner, name, desc); - } - } - - @Override - public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { - if (mOrgWriter != null) { - mOrgWriter.visitFrame(type, nLocal, local, nStack, stack); - } - } - - @Override - public void visitIincInsn(int var, int increment) { - if (mOrgWriter != null) { - mOrgWriter.visitIincInsn(var, increment); - } - } - - @Override - public void visitIntInsn(int opcode, int operand) { - if (mOrgWriter != null) { - mOrgWriter.visitIntInsn(opcode, operand); - } - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - if (mOrgWriter != null) { - mOrgWriter.visitJumpInsn(opcode, label); - } - } - - @Override - public void visitLdcInsn(Object cst) { - if (mOrgWriter != null) { - mOrgWriter.visitLdcInsn(cst); - } - } - - @Override - public void visitLocalVariable(String name, String desc, String signature, - Label start, Label end, int index) { - if (mOrgWriter != null) { - mOrgWriter.visitLocalVariable(name, desc, signature, start, end, index); - } - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - if (mOrgWriter != null) { - mOrgWriter.visitLookupSwitchInsn(dflt, keys, labels); - } - } - - @Override - public void visitMultiANewArrayInsn(String desc, int dims) { - if (mOrgWriter != null) { - mOrgWriter.visitMultiANewArrayInsn(desc, dims); - } - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { - if (mOrgWriter != null) { - mOrgWriter.visitTableSwitchInsn(min, max, dflt, labels); - } - } - - @Override - public void visitTypeInsn(int opcode, String type) { - if (mOrgWriter != null) { - mOrgWriter.visitTypeInsn(opcode, type); - } - } - - @Override - public void visitVarInsn(int opcode, int var) { - if (mOrgWriter != null) { - mOrgWriter.visitVarInsn(opcode, var); - } - } - -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java deleted file mode 100644 index c988c70..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java +++ /dev/null @@ -1,787 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -package com.android.tools.layoutlib.create; - -import com.android.tools.layoutlib.annotations.VisibleForTesting; -import com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.signature.SignatureReader; -import org.objectweb.asm.signature.SignatureVisitor; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * Analyzes the input JAR using the ASM java bytecode manipulation library - * to list the classes and their dependencies. A "dependency" is a class - * used by another class. - */ -public class DependencyFinder { - - // Note: a bunch of stuff has package-level access for unit tests. Consider it private. - - /** Output logger. */ - private final Log mLog; - - /** - * Creates a new analyzer. - * - * @param log The log output. - */ - public DependencyFinder(Log log) { - mLog = log; - } - - /** - * Starts the analysis using parameters from the constructor. - * - * @param osJarPath The input source JARs to parse. - * @return A pair: [0]: map { class FQCN => set of FQCN class dependencies }. - * [1]: map { missing class FQCN => set of FQCN class that uses it. } - */ - public List<Map<String, Set<String>>> findDeps(List<String> osJarPath) throws IOException { - - Map<String, ClassReader> zipClasses = parseZip(osJarPath); - mLog.info("Found %d classes in input JAR%s.", - zipClasses.size(), - osJarPath.size() > 1 ? "s" : ""); - - Map<String, Set<String>> deps = findClassesDeps(zipClasses); - - Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet()); - - List<Map<String, Set<String>>> result = new ArrayList<Map<String,Set<String>>>(2); - result.add(deps); - result.add(missing); - return result; - } - - /** - * Prints dependencies to the current logger, found stuff and missing stuff. - */ - public void printAllDeps(List<Map<String, Set<String>>> result) { - assert result.size() == 2; - Map<String, Set<String>> deps = result.get(0); - Map<String, Set<String>> missing = result.get(1); - - // Print all dependences found in the format: - // +Found: <FQCN from zip> - // uses: FQCN - - mLog.info("++++++ %d Entries found in source JARs", deps.size()); - mLog.info(""); - - for (Entry<String, Set<String>> entry : deps.entrySet()) { - mLog.info( "+Found : %s", entry.getKey()); - for (String dep : entry.getValue()) { - mLog.info(" uses: %s", dep); - } - - mLog.info(""); - } - - - // Now print all missing dependences in the format: - // -Missing <FQCN>: - // used by: <FQCN> - - mLog.info(""); - mLog.info("------ %d Entries missing from source JARs", missing.size()); - mLog.info(""); - - for (Entry<String, Set<String>> entry : missing.entrySet()) { - mLog.info( "-Missing : %s", entry.getKey()); - for (String dep : entry.getValue()) { - mLog.info(" used by: %s", dep); - } - - mLog.info(""); - } - } - - /** - * Prints only a summary of the missing dependencies to the current logger. - */ - public void printMissingDeps(List<Map<String, Set<String>>> result) { - assert result.size() == 2; - @SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0); - Map<String, Set<String>> missing = result.get(1); - - for (String fqcn : missing.keySet()) { - mLog.info("%s", fqcn); - } - } - - // ---------------- - - /** - * Parses a JAR file and returns a list of all classes founds using a map - * class name => ASM ClassReader. Class names are in the form "android.view.View". - */ - Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException { - TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>(); - - for (String jarPath : jarPathList) { - ZipFile zip = new ZipFile(jarPath); - Enumeration<? extends ZipEntry> entries = zip.entries(); - ZipEntry entry; - while (entries.hasMoreElements()) { - entry = entries.nextElement(); - if (entry.getName().endsWith(".class")) { - ClassReader cr = new ClassReader(zip.getInputStream(entry)); - String className = classReaderToClassName(cr); - classes.put(className, cr); - } - } - } - - return classes; - } - - /** - * Utility that returns the fully qualified binary class name for a ClassReader. - * E.g. it returns something like android.view.View. - */ - static String classReaderToClassName(ClassReader classReader) { - if (classReader == null) { - return null; - } else { - return classReader.getClassName().replace('/', '.'); - } - } - - /** - * Utility that returns the fully qualified binary class name from a path-like FQCN. - * E.g. it returns android.view.View from android/view/View. - */ - static String internalToBinaryClassName(String className) { - if (className == null) { - return null; - } else { - return className.replace('/', '.'); - } - } - - /** - * Finds all dependencies for all classes in keepClasses which are also - * listed in zipClasses. Returns a map of all the dependencies found. - */ - Map<String, Set<String>> findClassesDeps(Map<String, ClassReader> zipClasses) { - - // The dependencies that we'll collect. - // It's a map Class name => uses class names. - Map<String, Set<String>> dependencyMap = new TreeMap<String, Set<String>>(); - - DependencyVisitor visitor = getVisitor(); - - int count = 0; - try { - for (Entry<String, ClassReader> entry : zipClasses.entrySet()) { - String name = entry.getKey(); - - TreeSet<String> set = new TreeSet<String>(); - dependencyMap.put(name, set); - visitor.setDependencySet(set); - - ClassReader cr = entry.getValue(); - cr.accept(visitor, 0 /* flags */); - - visitor.setDependencySet(null); - - mLog.debugNoln("Visited %d classes\r", ++count); - } - } finally { - mLog.debugNoln("\n"); - } - - return dependencyMap; - } - - /** - * Computes which classes FQCN were found as dependencies that are NOT listed - * in the original JAR classes. - * - * @param deps The map { FQCN => dependencies[] } returned by {@link #findClassesDeps(Map)}. - * @param zipClasses The set of all classes FQCN found in the JAR files. - * @return A map { FQCN not found in the zipClasses => classes using it } - */ - private Map<String, Set<String>> findMissingClasses( - Map<String, Set<String>> deps, - Set<String> zipClasses) { - Map<String, Set<String>> missing = new TreeMap<String, Set<String>>(); - - for (Entry<String, Set<String>> entry : deps.entrySet()) { - String name = entry.getKey(); - - for (String dep : entry.getValue()) { - if (!zipClasses.contains(dep)) { - // This dependency doesn't exist in the zip classes. - Set<String> set = missing.get(dep); - if (set == null) { - set = new TreeSet<String>(); - missing.put(dep, set); - } - set.add(name); - } - } - - } - - return missing; - } - - - // ---------------------------------- - - /** - * Instantiates a new DependencyVisitor. Useful for unit tests. - */ - @VisibleForTesting(visibility=Visibility.PRIVATE) - DependencyVisitor getVisitor() { - return new DependencyVisitor(); - } - - /** - * Visitor to collect all the type dependencies from a class. - */ - public class DependencyVisitor extends ClassVisitor { - - private Set<String> mCurrentDepSet; - - /** - * Creates a new visitor that will find all the dependencies for the visited class. - */ - public DependencyVisitor() { - super(Opcodes.ASM4); - } - - /** - * Sets the {@link Set} where to record direct dependencies for this class. - * This will change before each {@link ClassReader#accept(ClassVisitor, int)} call. - */ - public void setDependencySet(Set<String> set) { - mCurrentDepSet = set; - } - - /** - * Considers the given class name as a dependency. - */ - public void considerName(String className) { - if (className == null) { - return; - } - - className = internalToBinaryClassName(className); - - try { - // exclude classes that are part of the default JRE (the one executing this program) - if (getClass().getClassLoader().loadClass(className) != null) { - return; - } - } catch (ClassNotFoundException e) { - // ignore - } - - // Add it to the dependency set for the currently visited class, as needed. - assert mCurrentDepSet != null; - if (mCurrentDepSet != null) { - mCurrentDepSet.add(className); - } - } - - /** - * Considers this array of names using considerName(). - */ - public void considerNames(String[] classNames) { - if (classNames != null) { - for (String className : classNames) { - considerName(className); - } - } - } - - /** - * Considers this signature or type signature by invoking the {@link SignatureVisitor} - * on it. - */ - public void considerSignature(String signature) { - if (signature != null) { - SignatureReader sr = new SignatureReader(signature); - // SignatureReader.accept will call accessType so we don't really have - // to differentiate where the signature comes from. - sr.accept(new MySignatureVisitor()); - } - } - - /** - * Considers this {@link Type}. For arrays, the element type is considered. - * If the type is an object, it's internal name is considered. - */ - public void considerType(Type t) { - if (t != null) { - if (t.getSort() == Type.ARRAY) { - t = t.getElementType(); - } - if (t.getSort() == Type.OBJECT) { - considerName(t.getInternalName()); - } - } - } - - /** - * Considers a descriptor string. The descriptor is converted to a {@link Type} - * and then considerType() is invoked. - */ - public boolean considerDesc(String desc) { - if (desc != null) { - try { - if (desc.length() > 0 && desc.charAt(0) == '(') { - // This is a method descriptor with arguments and a return type. - Type t = Type.getReturnType(desc); - considerType(t); - - for (Type arg : Type.getArgumentTypes(desc)) { - considerType(arg); - } - - } else { - Type t = Type.getType(desc); - considerType(t); - } - return true; - } catch (ArrayIndexOutOfBoundsException e) { - // ignore, not a valid type. - } - } - return false; - } - - - // --------------------------------------------------- - // --- ClassVisitor, FieldVisitor - // --------------------------------------------------- - - // Visits a class header - @Override - public void visit(int version, int access, String name, - String signature, String superName, String[] interfaces) { - // signature is the signature of this class. May be null if the class is not a generic - // one, and does not extend or implement generic classes or interfaces. - - if (signature != null) { - considerSignature(signature); - } - - // superName is the internal of name of the super class (see getInternalName). - // For interfaces, the super class is Object. May be null but only for the Object class. - considerName(superName); - - // interfaces is the internal names of the class's interfaces (see getInternalName). - // May be null. - considerNames(interfaces); - } - - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - // desc is the class descriptor of the annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public void visitAttribute(Attribute attr) { - // pass - } - - // Visits the end of a class - @Override - public void visitEnd() { - // pass - } - - private class MyFieldVisitor extends FieldVisitor { - - public MyFieldVisitor() { - super(Opcodes.ASM4); - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - // desc is the class descriptor of the annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public void visitAttribute(Attribute attr) { - // pass - } - - // Visits the end of a class - @Override - public void visitEnd() { - // pass - } - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - // desc is the field's descriptor (see Type). - considerDesc(desc); - - // signature is the field's signature. May be null if the field's type does not use - // generic types. - considerSignature(signature); - - return new MyFieldVisitor(); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - // name is the internal name of an inner class (see getInternalName). - // Note: outerName/innerName seems to be null when we're reading the - // _Original_ClassName classes generated by layoutlib_create. - if (outerName != null) { - considerName(name); - } - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - // desc is the method's descriptor (see Type). - considerDesc(desc); - // signature is the method's signature. May be null if the method parameters, return - // type and exceptions do not use generic types. - considerSignature(signature); - - return new MyMethodVisitor(); - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - // pass - } - - @Override - public void visitSource(String source, String debug) { - // pass - } - - - // --------------------------------------------------- - // --- MethodVisitor - // --------------------------------------------------- - - private class MyMethodVisitor extends MethodVisitor { - - public MyMethodVisitor() { - super(Opcodes.ASM4); - } - - - @Override - public AnnotationVisitor visitAnnotationDefault() { - return new MyAnnotationVisitor(); - } - - @Override - public void visitCode() { - // pass - } - - // field instruction - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - // name is the field's name. - // desc is the field's descriptor (see Type). - considerDesc(desc); - } - - @Override - public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) { - // pass - } - - @Override - public void visitIincInsn(int var, int increment) { - // pass -- an IINC instruction - } - - @Override - public void visitInsn(int opcode) { - // pass -- a zero operand instruction - } - - @Override - public void visitIntInsn(int opcode, int operand) { - // pass -- a single int operand instruction - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - // pass -- a jump instruction - } - - @Override - public void visitLabel(Label label) { - // pass -- a label target - } - - // instruction to load a constant from the stack - @Override - public void visitLdcInsn(Object cst) { - if (cst instanceof Type) { - considerType((Type) cst); - } - } - - @Override - public void visitLineNumber(int line, Label start) { - // pass - } - - @Override - public void visitLocalVariable(String name, String desc, - String signature, Label start, Label end, int index) { - // desc is the type descriptor of this local variable. - considerDesc(desc); - // signature is the type signature of this local variable. May be null if the local - // variable type does not use generic types. - considerSignature(signature); - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - // pass -- a lookup switch instruction - } - - @Override - public void visitMaxs(int maxStack, int maxLocals) { - // pass - } - - // instruction that invokes a method - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) { - - // owner is the internal name of the method's owner class - if (!considerDesc(owner) && owner.indexOf('/') != -1) { - considerName(owner); - } - // desc is the method's descriptor (see Type). - considerDesc(desc); - } - - // instruction multianewarray, whatever that is - @Override - public void visitMultiANewArrayInsn(String desc, int dims) { - - // desc an array type descriptor. - considerDesc(desc); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, - boolean visible) { - // desc is the class descriptor of the annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { - // pass -- table switch instruction - - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - // type is the internal name of the type of exceptions handled by the handler, - // or null to catch any exceptions (for "finally" blocks). - considerName(type); - } - - // type instruction - @Override - public void visitTypeInsn(int opcode, String type) { - // type is the operand of the instruction to be visited. This operand must be the - // internal name of an object or array class. - considerName(type); - } - - @Override - public void visitVarInsn(int opcode, int var) { - // pass -- local variable instruction - } - } - - private class MySignatureVisitor extends SignatureVisitor { - - public MySignatureVisitor() { - super(Opcodes.ASM4); - } - - // --------------------------------------------------- - // --- SignatureVisitor - // --------------------------------------------------- - - private String mCurrentSignatureClass = null; - - // Starts the visit of a signature corresponding to a class or interface type - @Override - public void visitClassType(String name) { - mCurrentSignatureClass = name; - considerName(name); - } - - // Visits an inner class - @Override - public void visitInnerClassType(String name) { - if (mCurrentSignatureClass != null) { - mCurrentSignatureClass += "$" + name; - considerName(mCurrentSignatureClass); - } - } - - @Override - public SignatureVisitor visitArrayType() { - return new MySignatureVisitor(); - } - - @Override - public void visitBaseType(char descriptor) { - // pass -- a primitive type, ignored - } - - @Override - public SignatureVisitor visitClassBound() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitExceptionType() { - return new MySignatureVisitor(); - } - - @Override - public void visitFormalTypeParameter(String name) { - // pass - } - - @Override - public SignatureVisitor visitInterface() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitInterfaceBound() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitParameterType() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitReturnType() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitSuperclass() { - return new MySignatureVisitor(); - } - - @Override - public SignatureVisitor visitTypeArgument(char wildcard) { - return new MySignatureVisitor(); - } - - @Override - public void visitTypeVariable(String name) { - // pass - } - - @Override - public void visitTypeArgument() { - // pass - } - } - - - // --------------------------------------------------- - // --- AnnotationVisitor - // --------------------------------------------------- - - private class MyAnnotationVisitor extends AnnotationVisitor { - - public MyAnnotationVisitor() { - super(Opcodes.ASM4); - } - - // Visits a primitive value of an annotation - @Override - public void visit(String name, Object value) { - // value is the actual value, whose type must be Byte, Boolean, Character, Short, - // Integer, Long, Float, Double, String or Type - if (value instanceof Type) { - considerType((Type) value); - } - } - - @Override - public AnnotationVisitor visitAnnotation(String name, String desc) { - // desc is the class descriptor of the nested annotation class. - considerDesc(desc); - return new MyAnnotationVisitor(); - } - - @Override - public AnnotationVisitor visitArray(String name) { - return new MyAnnotationVisitor(); - } - - @Override - public void visitEnum(String name, String desc, String value) { - // desc is the class descriptor of the enumeration class. - considerDesc(desc); - } - } - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java deleted file mode 100644 index 40c1706..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create; - -/** - * Interface describing the work to be done by {@link AsmGenerator}. - */ -public interface ICreateInfo { - - /** - * Returns the list of class from layoutlib_create to inject in layoutlib. - * The list can be empty but must not be null. - */ - public abstract Class<?>[] getInjectedClasses(); - - /** - * Returns the list of methods to rewrite as delegates. - * The list can be empty but must not be null. - */ - public abstract String[] getDelegateMethods(); - - /** - * Returns the list of classes on which to delegate all native methods. - * The list can be empty but must not be null. - */ - public abstract String[] getDelegateClassNatives(); - - /** - * Returns The list of methods to stub out. Each entry must be in the form - * "package.package.OuterClass$InnerClass#MethodName". - * The list can be empty but must not be null. - */ - public abstract String[] getOverriddenMethods(); - - /** - * Returns the list of classes to rename, must be an even list: the binary FQCN - * of class to replace followed by the new FQCN. - * The list can be empty but must not be null. - */ - public abstract String[] getRenamedClasses(); - - /** - * Returns the list of classes for which the methods returning them should be deleted. - * The array contains a list of null terminated section starting with the name of the class - * to rename in which the methods are deleted, followed by a list of return types identifying - * the methods to delete. - * The list can be empty but must not be null. - */ - public abstract String[] getDeleteReturns(); - -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java deleted file mode 100644 index c3ba591..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import java.io.PrintWriter; -import java.io.StringWriter; - -public class Log { - - private boolean mVerbose = false; - - public void setVerbose(boolean verbose) { - mVerbose = verbose; - } - - public void debug(String format, Object... args) { - if (mVerbose) { - info(format, args); - } - } - - /** Similar to debug() but doesn't do a \n automatically. */ - public void debugNoln(String format, Object... args) { - if (mVerbose) { - String s = String.format(format, args); - System.out.print(s); - } - } - - public void info(String format, Object... args) { - String s = String.format(format, args); - outPrintln(s); - } - - public void error(String format, Object... args) { - String s = String.format(format, args); - errPrintln(s); - } - - public void exception(Throwable t, String format, Object... args) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - t.printStackTrace(pw); - pw.flush(); - error(format + "\n" + sw.toString(), args); - } - - /** for unit testing */ - protected void errPrintln(String msg) { - System.err.println(msg); - } - - /** for unit testing */ - protected void outPrintln(String msg) { - System.out.println(msg); - } - -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/LogAbortException.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/LogAbortException.java deleted file mode 100644 index dc4b4a7..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/LogAbortException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -public class LogAbortException extends Exception { - - private final String mFormat; - private final Object[] mArgs; - - public LogAbortException(String format, Object... args) { - mFormat = format; - mArgs = args; - } - - public void error(Log log) { - log.error(mFormat, mArgs); - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java deleted file mode 100644 index 9cd74db..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - - -/** - * Entry point for the layoutlib_create tool. - * <p/> - * The tool does not currently rely on any external configuration file. - * Instead the configuration is mostly done via the {@link CreateInfo} class. - * <p/> - * For a complete description of the tool and its implementation, please refer to - * the "README.txt" file at the root of this project. - * <p/> - * For a quick test, invoke this as follows: - * <pre> - * $ make layoutlib - * </pre> - * which does: - * <pre> - * $ make layoutlib_create <bunch of framework jars> - * $ java -jar out/host/linux-x86/framework/layoutlib_create.jar \ - * out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar \ - * out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar \ - * out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar - * </pre> - */ -public class Main { - - public static class Options { - public boolean generatePublicAccess = true; - public boolean listAllDeps = false; - public boolean listOnlyMissingDeps = false; - } - - public static final Options sOptions = new Options(); - - public static void main(String[] args) { - - Log log = new Log(); - - ArrayList<String> osJarPath = new ArrayList<String>(); - String[] osDestJar = { null }; - - if (!processArgs(log, args, osJarPath, osDestJar)) { - log.error("Usage: layoutlib_create [-v] [-p] output.jar input.jar ..."); - log.error("Usage: layoutlib_create [-v] [--list-deps|--missing-deps] input.jar ..."); - System.exit(1); - } - - if (sOptions.listAllDeps || sOptions.listOnlyMissingDeps) { - System.exit(listDeps(osJarPath, log)); - - } else { - System.exit(createLayoutLib(osDestJar[0], osJarPath, log)); - } - - - System.exit(1); - } - - private static int createLayoutLib(String osDestJar, ArrayList<String> osJarPath, Log log) { - log.info("Output: %1$s", osDestJar); - for (String path : osJarPath) { - log.info("Input : %1$s", path); - } - - try { - AsmGenerator agen = new AsmGenerator(log, osDestJar, new CreateInfo()); - - AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen, - new String[] { // derived from - "android.view.View", - "android.app.Fragment" - }, - new String[] { // include classes - "android.*", // for android.R - "android.util.*", - "com.android.internal.util.*", - "android.view.*", - "android.widget.*", - "com.android.internal.widget.*", - "android.text.**", - "android.graphics.*", - "android.graphics.drawable.*", - "android.content.*", - "android.content.res.*", - "org.apache.harmony.xml.*", - "com.android.internal.R**", - "android.pim.*", // for datepicker - "android.os.*", // for android.os.Handler - "android.database.ContentObserver", // for Digital clock - }); - aa.analyze(); - agen.generate(); - - // Throw an error if any class failed to get renamed by the generator - // - // IMPORTANT: if you're building the platform and you get this error message, - // it means the renameClasses[] array in AsmGenerator needs to be updated: some - // class should have been renamed but it was not found in the input JAR files. - Set<String> notRenamed = agen.getClassesNotRenamed(); - if (notRenamed.size() > 0) { - // (80-column guide below for error formatting) - // 01234567890123456789012345678901234567890123456789012345678901234567890123456789 - log.error( - "ERROR when running layoutlib_create: the following classes are referenced\n" + - "by tools/layoutlib/create but were not actually found in the input JAR files.\n" + - "This may be due to some platform classes having been renamed."); - for (String fqcn : notRenamed) { - log.error("- Class not found: %s", fqcn.replace('/', '.')); - } - for (String path : osJarPath) { - log.info("- Input JAR : %1$s", path); - } - return 1; - } - - return 0; - } catch (IOException e) { - log.exception(e, "Failed to load jar"); - } catch (LogAbortException e) { - e.error(log); - } - - return 1; - } - - private static int listDeps(ArrayList<String> osJarPath, Log log) { - DependencyFinder df = new DependencyFinder(log); - try { - List<Map<String, Set<String>>> result = df.findDeps(osJarPath); - if (sOptions.listAllDeps) { - df.printAllDeps(result); - } else if (sOptions.listOnlyMissingDeps) { - df.printMissingDeps(result); - } - } catch (IOException e) { - log.exception(e, "Failed to load jar"); - } - - return 0; - } - - /** - * Returns true if args where properly parsed. - * Returns false if program should exit with command-line usage. - * <p/> - * Note: the String[0] is an output parameter wrapped in an array, since there is no - * "out" parameter support. - */ - private static boolean processArgs(Log log, String[] args, - ArrayList<String> osJarPath, String[] osDestJar) { - boolean needs_dest = true; - for (int i = 0; i < args.length; i++) { - String s = args[i]; - if (s.equals("-v")) { - log.setVerbose(true); - } else if (s.equals("-p")) { - sOptions.generatePublicAccess = false; - } else if (s.equals("--list-deps")) { - sOptions.listAllDeps = true; - needs_dest = false; - } else if (s.equals("--missing-deps")) { - sOptions.listOnlyMissingDeps = true; - needs_dest = false; - } else if (!s.startsWith("-")) { - if (needs_dest && osDestJar[0] == null) { - osDestJar[0] = s; - } else { - osJarPath.add(s); - } - } else { - log.error("Unknow argument: %s", s); - return false; - } - } - - if (osJarPath.isEmpty()) { - log.error("Missing parameter: path to input jar"); - return false; - } - if (needs_dest && osDestJar[0] == null) { - log.error("Missing parameter: path to output jar"); - return false; - } - - sOptions.generatePublicAccess = false; - - return true; - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java deleted file mode 100644 index 7d1e4cf..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - - -/** - * An adapter to make it easier to use {@link MethodListener}. - * <p/> - * The adapter calls the void {@link #onInvokeV(String, boolean, Object)} listener - * for all types (I, L, F, D and A), returning 0 or null as appropriate. - */ -public class MethodAdapter implements MethodListener { - /** - * A stub method is being invoked. - * <p/> - * Known limitation: caller arguments are not available. - * - * @param signature The signature of the method being invoked, composed of the - * binary class name followed by the method descriptor (aka argument - * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V". - * @param isNative True if the method was a native method. - * @param caller The calling object. Null for static methods, "this" for instance methods. - */ - @Override - public void onInvokeV(String signature, boolean isNative, Object caller) { - } - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar. - * @see #onInvokeV(String, boolean, Object) - * @return an integer, or a boolean, or a short or a byte. - */ - @Override - public int onInvokeI(String signature, boolean isNative, Object caller) { - onInvokeV(signature, isNative, caller); - return 0; - } - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long. - * @see #onInvokeV(String, boolean, Object) - * @return a long. - */ - @Override - public long onInvokeL(String signature, boolean isNative, Object caller) { - onInvokeV(signature, isNative, caller); - return 0; - } - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float. - * @see #onInvokeV(String, boolean, Object) - * @return a float. - */ - @Override - public float onInvokeF(String signature, boolean isNative, Object caller) { - onInvokeV(signature, isNative, caller); - return 0; - } - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double. - * @see #onInvokeV(String, boolean, Object) - * @return a double. - */ - @Override - public double onInvokeD(String signature, boolean isNative, Object caller) { - onInvokeV(signature, isNative, caller); - return 0; - } - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object. - * @see #onInvokeV(String, boolean, Object) - * @return an object. - */ - @Override - public Object onInvokeA(String signature, boolean isNative, Object caller) { - onInvokeV(signature, isNative, caller); - return null; - } -} - diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java deleted file mode 100644 index 6fc2b24..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - - -/** - * Interface to allow a method invocation to be listened upon. - * <p/> - * This is used by {@link OverrideMethod} to register a listener for methods that - * have been stubbed by the {@link AsmGenerator}. At runtime the stub will call either a - * default global listener or a specific listener based on the method signature. - */ -public interface MethodListener { - /** - * A stub method is being invoked. - * <p/> - * Known limitation: caller arguments are not available. - * - * @param signature The signature of the method being invoked, composed of the - * binary class name followed by the method descriptor (aka argument - * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V". - * @param isNative True if the method was a native method. - * @param caller The calling object. Null for static methods, "this" for instance methods. - */ - public void onInvokeV(String signature, boolean isNative, Object caller); - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar. - * @see #onInvokeV(String, boolean, Object) - * @return an integer, or a boolean, or a short or a byte. - */ - public int onInvokeI(String signature, boolean isNative, Object caller); - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long. - * @see #onInvokeV(String, boolean, Object) - * @return a long. - */ - public long onInvokeL(String signature, boolean isNative, Object caller); - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float. - * @see #onInvokeV(String, boolean, Object) - * @return a float. - */ - public float onInvokeF(String signature, boolean isNative, Object caller); - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double. - * @see #onInvokeV(String, boolean, Object) - * @return a double. - */ - public double onInvokeD(String signature, boolean isNative, Object caller); - - /** - * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object. - * @see #onInvokeV(String, boolean, Object) - * @return an object. - */ - public Object onInvokeA(String signature, boolean isNative, Object caller); -} - diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java deleted file mode 100644 index a6aff99..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import java.util.HashMap; - -/** - * Allows stub methods from LayoutLib to be overriden at runtime. - * <p/> - * Implementation note: all types required by this class(inner/outer classes & interfaces) - * must be referenced by the injectClass argument to {@link AsmGenerator} in Main.java; - * Otherwise they won't be accessible in layoutlib.jar at runtime. - */ -public final class OverrideMethod { - - /** Map of method overridden. */ - private static HashMap<String, MethodListener> sMethods = new HashMap<String, MethodListener>(); - /** Default listener for all method not listed in sMethods. Nothing if null. */ - private static MethodListener sDefaultListener = null; - - /** - * Sets the default listener for all methods not specifically handled. - * Null means to do nothing. - */ - public static void setDefaultListener(MethodListener listener) { - sDefaultListener = listener; - } - - /** - * Defines or reset a listener for the given method signature. - * - * @param signature The signature of the method being invoked, composed of the - * binary class name followed by the method descriptor (aka argument - * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V" - * @param listener The new listener. Removes it if null. - */ - public static void setMethodListener(String signature, MethodListener listener) { - if (listener == null) { - sMethods.remove(signature); - } else { - sMethods.put(signature, listener); - } - } - - /** - * Invokes the specific listener for the given signature or the default one if defined. - * <p/> - * This version invokes the method listener for the void return type. - * <p/> - * Note: this is not intended to be used by the LayoutLib Bridge. It is intended to be called - * by the stubbed methods generated by the LayoutLib_create tool. - * - * @param signature The signature of the method being invoked, composed of the - * binary class name followed by the method descriptor (aka argument - * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V". - * @param isNative True if the method was a native method. - * @param caller The calling object. Null for static methods, "this" for instance methods. - */ - public static void invokeV(String signature, boolean isNative, Object caller) { - MethodListener i = sMethods.get(signature); - if (i != null) { - i.onInvokeV(signature, isNative, caller); - } else if (sDefaultListener != null) { - sDefaultListener.onInvokeV(signature, isNative, caller); - } - } - - /** - * Invokes the specific listener for the int return type. - * @see #invokeV(String, boolean, Object) - */ - public static int invokeI(String signature, boolean isNative, Object caller) { - MethodListener i = sMethods.get(signature); - if (i != null) { - return i.onInvokeI(signature, isNative, caller); - } else if (sDefaultListener != null) { - return sDefaultListener.onInvokeI(signature, isNative, caller); - } - return 0; - } - - /** - * Invokes the specific listener for the long return type. - * @see #invokeV(String, boolean, Object) - */ - public static long invokeL(String signature, boolean isNative, Object caller) { - MethodListener i = sMethods.get(signature); - if (i != null) { - return i.onInvokeL(signature, isNative, caller); - } else if (sDefaultListener != null) { - return sDefaultListener.onInvokeL(signature, isNative, caller); - } - return 0; - } - - /** - * Invokes the specific listener for the float return type. - * @see #invokeV(String, boolean, Object) - */ - public static float invokeF(String signature, boolean isNative, Object caller) { - MethodListener i = sMethods.get(signature); - if (i != null) { - return i.onInvokeF(signature, isNative, caller); - } else if (sDefaultListener != null) { - return sDefaultListener.onInvokeF(signature, isNative, caller); - } - return 0; - } - - /** - * Invokes the specific listener for the double return type. - * @see #invokeV(String, boolean, Object) - */ - public static double invokeD(String signature, boolean isNative, Object caller) { - MethodListener i = sMethods.get(signature); - if (i != null) { - return i.onInvokeD(signature, isNative, caller); - } else if (sDefaultListener != null) { - return sDefaultListener.onInvokeD(signature, isNative, caller); - } - return 0; - } - - /** - * Invokes the specific listener for the object return type. - * @see #invokeV(String, boolean, Object) - */ - public static Object invokeA(String signature, boolean isNative, Object caller) { - MethodListener i = sMethods.get(signature); - if (i != null) { - return i.onInvokeA(signature, isNative, caller); - } else if (sDefaultListener != null) { - return sDefaultListener.onInvokeA(signature, isNative, caller); - } - return null; - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java deleted file mode 100644 index 383cbb8..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.signature.SignatureReader; -import org.objectweb.asm.signature.SignatureVisitor; -import org.objectweb.asm.signature.SignatureWriter; - -/** - * This class visitor renames a class from a given old name to a given new name. - * The class visitor will also rename all inner classes and references in the methods. - * <p/> - * - * For inner classes, this handles only the case where the outer class name changes. - * The inner class name should remain the same. - */ -public class RenameClassAdapter extends ClassVisitor { - - - private final String mOldName; - private final String mNewName; - private String mOldBase; - private String mNewBase; - - /** - * Creates a class visitor that renames a class from a given old name to a given new name. - * The class visitor will also rename all inner classes and references in the methods. - * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass). - */ - public RenameClassAdapter(ClassWriter cv, String oldName, String newName) { - super(Opcodes.ASM4, cv); - mOldBase = mOldName = oldName; - mNewBase = mNewName = newName; - - int pos = mOldName.indexOf('$'); - if (pos > 0) { - mOldBase = mOldName.substring(0, pos); - } - pos = mNewName.indexOf('$'); - if (pos > 0) { - mNewBase = mNewName.substring(0, pos); - } - - assert (mOldBase == null && mNewBase == null) || (mOldBase != null && mNewBase != null); - } - - - /** - * Renames a type descriptor, e.g. "Lcom.package.MyClass;" - * If the type doesn't need to be renamed, returns the input string as-is. - */ - String renameTypeDesc(String desc) { - if (desc == null) { - return null; - } - - return renameType(Type.getType(desc)); - } - - /** - * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an - * object element, e.g. "[Lcom.package.MyClass;" - * If the type doesn't need to be renamed, returns the internal name of the input type. - */ - String renameType(Type type) { - if (type == null) { - return null; - } - - if (type.getSort() == Type.OBJECT) { - String in = type.getInternalName(); - return "L" + renameInternalType(in) + ";"; - } else if (type.getSort() == Type.ARRAY) { - StringBuilder sb = new StringBuilder(); - for (int n = type.getDimensions(); n > 0; n--) { - sb.append('['); - } - sb.append(renameType(type.getElementType())); - return sb.toString(); - } - return type.getDescriptor(); - } - - /** - * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an - * object element, e.g. "[Lcom.package.MyClass;". - * This is like renameType() except that it returns a Type object. - * If the type doesn't need to be renamed, returns the input type object. - */ - Type renameTypeAsType(Type type) { - if (type == null) { - return null; - } - - if (type.getSort() == Type.OBJECT) { - String in = type.getInternalName(); - String newIn = renameInternalType(in); - if (newIn != in) { - return Type.getType("L" + newIn + ";"); - } - } else if (type.getSort() == Type.ARRAY) { - StringBuilder sb = new StringBuilder(); - for (int n = type.getDimensions(); n > 0; n--) { - sb.append('['); - } - sb.append(renameType(type.getElementType())); - return Type.getType(sb.toString()); - } - return type; - } - - /** - * Renames an internal type name, e.g. "com.package.MyClass". - * If the type doesn't need to be renamed, returns the input string as-is. - * <p/> - * The internal type of some of the MethodVisitor turns out to be a type - descriptor sometimes so descriptors are renamed too. - */ - String renameInternalType(String type) { - if (type == null) { - return null; - } - - if (type.equals(mOldName)) { - return mNewName; - } - - if (mOldBase != mOldName && type.equals(mOldBase)) { - return mNewBase; - } - - int pos = type.indexOf('$'); - if (pos == mOldBase.length() && type.startsWith(mOldBase)) { - return mNewBase + type.substring(pos); - } - - // The internal type of some of the MethodVisitor turns out to be a type - // descriptor sometimes. This is the case with visitTypeInsn(type) and - // visitMethodInsn(owner). We try to detect it and adjust it here. - if (type.indexOf(';') > 0) { - type = renameTypeDesc(type); - } - - return type; - } - - /** - * Renames a method descriptor, i.e. applies renameType to all arguments and to the - * return value. - */ - String renameMethodDesc(String desc) { - if (desc == null) { - return null; - } - - Type[] args = Type.getArgumentTypes(desc); - - StringBuilder sb = new StringBuilder("("); - for (Type arg : args) { - String name = renameType(arg); - sb.append(name); - } - sb.append(')'); - - Type ret = Type.getReturnType(desc); - String name = renameType(ret); - sb.append(name); - - return sb.toString(); - } - - - /** - * Renames the ClassSignature handled by ClassVisitor.visit - * or the MethodTypeSignature handled by ClassVisitor.visitMethod. - */ - String renameTypeSignature(String sig) { - if (sig == null) { - return null; - } - SignatureReader reader = new SignatureReader(sig); - SignatureWriter writer = new SignatureWriter(); - reader.accept(new RenameSignatureAdapter(writer)); - sig = writer.toString(); - return sig; - } - - - /** - * Renames the FieldTypeSignature handled by ClassVisitor.visitField - * or MethodVisitor.visitLocalVariable. - */ - String renameFieldSignature(String sig) { - if (sig == null) { - return null; - } - SignatureReader reader = new SignatureReader(sig); - SignatureWriter writer = new SignatureWriter(); - reader.acceptType(new RenameSignatureAdapter(writer)); - sig = writer.toString(); - return sig; - } - - - //---------------------------------- - // Methods from the ClassAdapter - - @Override - public void visit(int version, int access, String name, String signature, - String superName, String[] interfaces) { - name = renameInternalType(name); - superName = renameInternalType(superName); - signature = renameTypeSignature(signature); - - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - assert outerName.equals(mOldName); - outerName = renameInternalType(outerName); - name = outerName + "$" + innerName; - super.visitInnerClass(name, outerName, innerName, access); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - desc = renameMethodDesc(desc); - signature = renameTypeSignature(signature); - MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions); - return new RenameMethodAdapter(mw); - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - desc = renameTypeDesc(desc); - return super.visitAnnotation(desc, visible); - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - desc = renameTypeDesc(desc); - signature = renameFieldSignature(signature); - return super.visitField(access, name, desc, signature, value); - } - - - //---------------------------------- - - /** - * A method visitor that renames all references from an old class name to a new class name. - */ - public class RenameMethodAdapter extends MethodVisitor { - - /** - * Creates a method visitor that renames all references from a given old name to a given new - * name. The method visitor will also rename all inner classes. - * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass). - */ - public RenameMethodAdapter(MethodVisitor mv) { - super(Opcodes.ASM4, mv); - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - desc = renameTypeDesc(desc); - - return super.visitAnnotation(desc, visible); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { - desc = renameTypeDesc(desc); - - return super.visitParameterAnnotation(parameter, desc, visible); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - type = renameInternalType(type); - - super.visitTypeInsn(opcode, type); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - owner = renameInternalType(owner); - desc = renameTypeDesc(desc); - - super.visitFieldInsn(opcode, owner, name, desc); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) { - owner = renameInternalType(owner); - desc = renameMethodDesc(desc); - - super.visitMethodInsn(opcode, owner, name, desc); - } - - @Override - public void visitLdcInsn(Object cst) { - // If cst is a Type, this means the code is trying to pull the .class constant - // for this class, so it needs to be renamed too. - if (cst instanceof Type) { - cst = renameTypeAsType((Type) cst); - } - super.visitLdcInsn(cst); - } - - @Override - public void visitMultiANewArrayInsn(String desc, int dims) { - desc = renameTypeDesc(desc); - - super.visitMultiANewArrayInsn(desc, dims); - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - type = renameInternalType(type); - - super.visitTryCatchBlock(start, end, handler, type); - } - - @Override - public void visitLocalVariable(String name, String desc, String signature, - Label start, Label end, int index) { - desc = renameTypeDesc(desc); - signature = renameFieldSignature(signature); - - super.visitLocalVariable(name, desc, signature, start, end, index); - } - - } - - //---------------------------------- - - public class RenameSignatureAdapter extends SignatureVisitor { - - private final SignatureVisitor mSv; - - public RenameSignatureAdapter(SignatureVisitor sv) { - super(Opcodes.ASM4); - mSv = sv; - } - - @Override - public void visitClassType(String name) { - name = renameInternalType(name); - mSv.visitClassType(name); - } - - @Override - public void visitInnerClassType(String name) { - name = renameInternalType(name); - mSv.visitInnerClassType(name); - } - - @Override - public SignatureVisitor visitArrayType() { - SignatureVisitor sv = mSv.visitArrayType(); - return new RenameSignatureAdapter(sv); - } - - @Override - public void visitBaseType(char descriptor) { - mSv.visitBaseType(descriptor); - } - - @Override - public SignatureVisitor visitClassBound() { - SignatureVisitor sv = mSv.visitClassBound(); - return new RenameSignatureAdapter(sv); - } - - @Override - public void visitEnd() { - mSv.visitEnd(); - } - - @Override - public SignatureVisitor visitExceptionType() { - SignatureVisitor sv = mSv.visitExceptionType(); - return new RenameSignatureAdapter(sv); - } - - @Override - public void visitFormalTypeParameter(String name) { - mSv.visitFormalTypeParameter(name); - } - - @Override - public SignatureVisitor visitInterface() { - SignatureVisitor sv = mSv.visitInterface(); - return new RenameSignatureAdapter(sv); - } - - @Override - public SignatureVisitor visitInterfaceBound() { - SignatureVisitor sv = mSv.visitInterfaceBound(); - return new RenameSignatureAdapter(sv); - } - - @Override - public SignatureVisitor visitParameterType() { - SignatureVisitor sv = mSv.visitParameterType(); - return new RenameSignatureAdapter(sv); - } - - @Override - public SignatureVisitor visitReturnType() { - SignatureVisitor sv = mSv.visitReturnType(); - return new RenameSignatureAdapter(sv); - } - - @Override - public SignatureVisitor visitSuperclass() { - SignatureVisitor sv = mSv.visitSuperclass(); - return new RenameSignatureAdapter(sv); - } - - @Override - public void visitTypeArgument() { - mSv.visitTypeArgument(); - } - - @Override - public SignatureVisitor visitTypeArgument(char wildcard) { - SignatureVisitor sv = mSv.visitTypeArgument(wildcard); - return new RenameSignatureAdapter(sv); - } - - @Override - public void visitTypeVariable(String name) { - mSv.visitTypeVariable(name); - } - - } -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java deleted file mode 100644 index 51e7535..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -/** - * This method adapter rewrites a method by discarding the original code and generating - * a stub depending on the return type. Original annotations are passed along unchanged. - */ -class StubMethodAdapter extends MethodVisitor { - - private static String CONSTRUCTOR = "<init>"; - private static String CLASS_INIT = "<clinit>"; - - /** The parent method writer */ - private MethodVisitor mParentVisitor; - /** The method return type. Can be null. */ - private Type mReturnType; - /** Message to be printed by stub methods. */ - private String mInvokeSignature; - /** Flag to output the first line number. */ - private boolean mOutputFirstLineNumber = true; - /** Flag that is true when implementing a constructor, to accept all original - * code calling the original super constructor. */ - private boolean mIsInitMethod = false; - - private boolean mMessageGenerated; - private final boolean mIsStatic; - private final boolean mIsNative; - - public StubMethodAdapter(MethodVisitor mv, String methodName, Type returnType, - String invokeSignature, boolean isStatic, boolean isNative) { - super(Opcodes.ASM4); - mParentVisitor = mv; - mReturnType = returnType; - mInvokeSignature = invokeSignature; - mIsStatic = isStatic; - mIsNative = isNative; - - if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) { - mIsInitMethod = true; - } - } - - private void generateInvoke() { - /* Generates the code: - * OverrideMethod.invoke("signature", mIsNative ? true : false, null or this); - */ - mParentVisitor.visitLdcInsn(mInvokeSignature); - // push true or false - mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0); - // push null or this - if (mIsStatic) { - mParentVisitor.visitInsn(Opcodes.ACONST_NULL); - } else { - mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); - } - - int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID; - switch(sort) { - case Type.VOID: - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invokeV", - "(Ljava/lang/String;ZLjava/lang/Object;)V"); - mParentVisitor.visitInsn(Opcodes.RETURN); - break; - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invokeI", - "(Ljava/lang/String;ZLjava/lang/Object;)I"); - switch(sort) { - case Type.BOOLEAN: - Label l1 = new Label(); - mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1); - mParentVisitor.visitInsn(Opcodes.ICONST_1); - mParentVisitor.visitInsn(Opcodes.IRETURN); - mParentVisitor.visitLabel(l1); - mParentVisitor.visitInsn(Opcodes.ICONST_0); - break; - case Type.CHAR: - mParentVisitor.visitInsn(Opcodes.I2C); - break; - case Type.BYTE: - mParentVisitor.visitInsn(Opcodes.I2B); - break; - case Type.SHORT: - mParentVisitor.visitInsn(Opcodes.I2S); - break; - } - mParentVisitor.visitInsn(Opcodes.IRETURN); - break; - case Type.LONG: - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invokeL", - "(Ljava/lang/String;ZLjava/lang/Object;)J"); - mParentVisitor.visitInsn(Opcodes.LRETURN); - break; - case Type.FLOAT: - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invokeF", - "(Ljava/lang/String;ZLjava/lang/Object;)F"); - mParentVisitor.visitInsn(Opcodes.FRETURN); - break; - case Type.DOUBLE: - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invokeD", - "(Ljava/lang/String;ZLjava/lang/Object;)D"); - mParentVisitor.visitInsn(Opcodes.DRETURN); - break; - case Type.ARRAY: - case Type.OBJECT: - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invokeA", - "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;"); - mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName()); - mParentVisitor.visitInsn(Opcodes.ARETURN); - break; - } - - } - - private void generatePop() { - /* Pops the stack, depending on the return type. - */ - switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) { - case Type.VOID: - break; - case Type.BOOLEAN: - case Type.CHAR: - case Type.BYTE: - case Type.SHORT: - case Type.INT: - case Type.FLOAT: - case Type.ARRAY: - case Type.OBJECT: - mParentVisitor.visitInsn(Opcodes.POP); - break; - case Type.LONG: - case Type.DOUBLE: - mParentVisitor.visitInsn(Opcodes.POP2); - break; - } - } - - /* Pass down to visitor writer. In this implementation, either do nothing. */ - @Override - public void visitCode() { - mParentVisitor.visitCode(); - } - - /* - * visitMaxs is called just before visitEnd if there was any code to rewrite. - * For non-constructor, generate the messaging code and the return statement - * if it hasn't been done before. - */ - @Override - public void visitMaxs(int maxStack, int maxLocals) { - if (!mIsInitMethod && !mMessageGenerated) { - generateInvoke(); - mMessageGenerated = true; - } - mParentVisitor.visitMaxs(maxStack, maxLocals); - } - - /** - * End of visiting. - * For non-constructor, generate the messaging code and the return statement - * if it hasn't been done before. - */ - @Override - public void visitEnd() { - if (!mIsInitMethod && !mMessageGenerated) { - generateInvoke(); - mMessageGenerated = true; - mParentVisitor.visitMaxs(1, 1); - } - mParentVisitor.visitEnd(); - } - - /* Writes all annotation from the original method. */ - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - return mParentVisitor.visitAnnotation(desc, visible); - } - - /* Writes all annotation default values from the original method. */ - @Override - public AnnotationVisitor visitAnnotationDefault() { - return mParentVisitor.visitAnnotationDefault(); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, - boolean visible) { - return mParentVisitor.visitParameterAnnotation(parameter, desc, visible); - } - - /* Writes all attributes from the original method. */ - @Override - public void visitAttribute(Attribute attr) { - mParentVisitor.visitAttribute(attr); - } - - /* - * Only writes the first line number present in the original code so that source - * viewers can direct to the correct method, even if the content doesn't match. - */ - @Override - public void visitLineNumber(int line, Label start) { - if (mIsInitMethod || mOutputFirstLineNumber) { - mParentVisitor.visitLineNumber(line, start); - mOutputFirstLineNumber = false; - } - } - - /** - * For non-constructor, rewrite existing "return" instructions to write the message. - */ - @Override - public void visitInsn(int opcode) { - if (mIsInitMethod) { - switch (opcode) { - case Opcodes.RETURN: - case Opcodes.ARETURN: - case Opcodes.DRETURN: - case Opcodes.FRETURN: - case Opcodes.IRETURN: - case Opcodes.LRETURN: - // Pop the last word from the stack since invoke will generate its own return. - generatePop(); - generateInvoke(); - mMessageGenerated = true; - //$FALL-THROUGH$ - default: - mParentVisitor.visitInsn(opcode); - } - } - } - - @Override - public void visitLabel(Label label) { - if (mIsInitMethod) { - mParentVisitor.visitLabel(label); - } - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - if (mIsInitMethod) { - mParentVisitor.visitTryCatchBlock(start, end, handler, type); - } - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) { - if (mIsInitMethod) { - mParentVisitor.visitMethodInsn(opcode, owner, name, desc); - } - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - if (mIsInitMethod) { - mParentVisitor.visitFieldInsn(opcode, owner, name, desc); - } - } - - @Override - public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { - if (mIsInitMethod) { - mParentVisitor.visitFrame(type, nLocal, local, nStack, stack); - } - } - - @Override - public void visitIincInsn(int var, int increment) { - if (mIsInitMethod) { - mParentVisitor.visitIincInsn(var, increment); - } - } - - @Override - public void visitIntInsn(int opcode, int operand) { - if (mIsInitMethod) { - mParentVisitor.visitIntInsn(opcode, operand); - } - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - if (mIsInitMethod) { - mParentVisitor.visitJumpInsn(opcode, label); - } - } - - @Override - public void visitLdcInsn(Object cst) { - if (mIsInitMethod) { - mParentVisitor.visitLdcInsn(cst); - } - } - - @Override - public void visitLocalVariable(String name, String desc, String signature, - Label start, Label end, int index) { - if (mIsInitMethod) { - mParentVisitor.visitLocalVariable(name, desc, signature, start, end, index); - } - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - if (mIsInitMethod) { - mParentVisitor.visitLookupSwitchInsn(dflt, keys, labels); - } - } - - @Override - public void visitMultiANewArrayInsn(String desc, int dims) { - if (mIsInitMethod) { - mParentVisitor.visitMultiANewArrayInsn(desc, dims); - } - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) { - if (mIsInitMethod) { - mParentVisitor.visitTableSwitchInsn(min, max, dflt, labels); - } - } - - @Override - public void visitTypeInsn(int opcode, String type) { - if (mIsInitMethod) { - mParentVisitor.visitTypeInsn(opcode, type); - } - } - - @Override - public void visitVarInsn(int opcode, int var) { - if (mIsInitMethod) { - mParentVisitor.visitVarInsn(opcode, var); - } - } - -} diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java deleted file mode 100644 index d45a183..0000000 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; - -import java.util.Set; - -/** - * Class adapter that can stub some or all of the methods of the class. - */ -class TransformClassAdapter extends ClassVisitor { - - /** True if all methods should be stubbed, false if only native ones must be stubbed. */ - private final boolean mStubAll; - /** True if the class is an interface. */ - private boolean mIsInterface; - private final String mClassName; - private final Log mLog; - private final Set<String> mStubMethods; - private Set<String> mDeleteReturns; - - /** - * Creates a new class adapter that will stub some or all methods. - * @param logger - * @param stubMethods list of method signatures to always stub out - * @param deleteReturns list of types that trigger the deletion of methods returning them. - * @param className The name of the class being modified - * @param cv The parent class writer visitor - * @param stubNativesOnly True if only native methods should be stubbed. False if all - * methods should be stubbed. - * @param hasNative True if the method has natives, in which case its access should be - * changed. - */ - public TransformClassAdapter(Log logger, Set<String> stubMethods, - Set<String> deleteReturns, String className, ClassVisitor cv, - boolean stubNativesOnly, boolean hasNative) { - super(Opcodes.ASM4, cv); - mLog = logger; - mStubMethods = stubMethods; - mClassName = className; - mStubAll = !stubNativesOnly; - mIsInterface = false; - mDeleteReturns = deleteReturns; - } - - /* Visits the class header. */ - @Override - public void visit(int version, int access, String name, - String signature, String superName, String[] interfaces) { - - // This class might be being renamed. - name = mClassName; - - // remove protected or private and set as public - if (Main.sOptions.generatePublicAccess) { - access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); - access |= Opcodes.ACC_PUBLIC; - } - // remove final - access = access & ~Opcodes.ACC_FINAL; - // note: leave abstract classes as such - // don't try to implement stub for interfaces - - mIsInterface = ((access & Opcodes.ACC_INTERFACE) != 0); - super.visit(version, access, name, signature, superName, interfaces); - } - - /* Visits the header of an inner class. */ - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - // remove protected or private and set as public - if (Main.sOptions.generatePublicAccess) { - access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED); - access |= Opcodes.ACC_PUBLIC; - } - // remove final - access = access & ~Opcodes.ACC_FINAL; - // note: leave abstract classes as such - // don't try to implement stub for interfaces - - super.visitInnerClass(name, outerName, innerName, access); - } - - /* Visits a method. */ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, - String signature, String[] exceptions) { - - if (mDeleteReturns != null) { - Type t = Type.getReturnType(desc); - if (t.getSort() == Type.OBJECT) { - String returnType = t.getInternalName(); - if (returnType != null) { - if (mDeleteReturns.contains(returnType)) { - return null; - } - } - } - } - - String methodSignature = mClassName.replace('/', '.') + "#" + name; - - // change access to public - if (Main.sOptions.generatePublicAccess) { - access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); - access |= Opcodes.ACC_PUBLIC; - } - - // remove final - access = access & ~Opcodes.ACC_FINAL; - - // stub this method if they are all to be stubbed or if it is a native method - // and don't try to stub interfaces nor abstract non-native methods. - if (!mIsInterface && - ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) != Opcodes.ACC_ABSTRACT) && - (mStubAll || - (access & Opcodes.ACC_NATIVE) != 0) || - mStubMethods.contains(methodSignature)) { - - boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; - boolean isNative = (access & Opcodes.ACC_NATIVE) != 0; - - // remove abstract, final and native - access = access & ~(Opcodes.ACC_ABSTRACT | Opcodes.ACC_FINAL | Opcodes.ACC_NATIVE); - - String invokeSignature = methodSignature + desc; - mLog.debug(" Stub: %s (%s)", invokeSignature, isNative ? "native" : ""); - - MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions); - return new StubMethodAdapter(mw, name, returnType(desc), invokeSignature, - isStatic, isNative); - - } else { - mLog.debug(" Keep: %s %s", name, desc); - return super.visitMethod(access, name, desc, signature, exceptions); - } - } - - /* Visits a field. Makes it public. */ - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, - Object value) { - // change access to public - if (Main.sOptions.generatePublicAccess) { - access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE); - access |= Opcodes.ACC_PUBLIC; - } - return super.visitField(access, name, desc, signature, value); - } - - /** - * Extracts the return {@link Type} of this descriptor. - */ - Type returnType(String desc) { - if (desc != null) { - try { - return Type.getReturnType(desc); - } catch (ArrayIndexOutOfBoundsException e) { - // ignore, not a valid type. - } - } - return null; - } -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java deleted file mode 100644 index d6dba6a..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - - -package com.android.tools.layoutlib.create; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import com.android.tools.layoutlib.create.AsmAnalyzer.DependencyVisitor; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.objectweb.asm.ClassReader; - -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Map; -import java.util.TreeMap; - -/** - * Unit tests for some methods of {@link AsmAnalyzer}. - */ -public class AsmAnalyzerTest { - - private MockLog mLog; - private ArrayList<String> mOsJarPath; - private AsmAnalyzer mAa; - - @Before - public void setUp() throws Exception { - mLog = new MockLog(); - URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar"); - - mOsJarPath = new ArrayList<String>(); - mOsJarPath.add(url.getFile()); - - mAa = new AsmAnalyzer(mLog, mOsJarPath, null /* gen */, - null /* deriveFrom */, null /* includeGlobs */ ); - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testParseZip() throws IOException { - Map<String, ClassReader> map = mAa.parseZip(mOsJarPath); - - assertArrayEquals(new String[] { - "mock_android.dummy.InnerTest", - "mock_android.dummy.InnerTest$DerivingClass", - "mock_android.dummy.InnerTest$MyGenerics1", - "mock_android.dummy.InnerTest$MyIntEnum", - "mock_android.dummy.InnerTest$MyStaticInnerClass", - "mock_android.dummy.InnerTest$NotStaticInner1", - "mock_android.dummy.InnerTest$NotStaticInner2", - "mock_android.view.View", - "mock_android.view.ViewGroup", - "mock_android.view.ViewGroup$LayoutParams", - "mock_android.view.ViewGroup$MarginLayoutParams", - "mock_android.widget.LinearLayout", - "mock_android.widget.LinearLayout$LayoutParams", - "mock_android.widget.TableLayout", - "mock_android.widget.TableLayout$LayoutParams" - }, - map.keySet().toArray()); - } - - @Test - public void testFindClass() throws IOException, LogAbortException { - Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); - TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); - - ClassReader cr = mAa.findClass("mock_android.view.ViewGroup$LayoutParams", - zipClasses, found); - - assertNotNull(cr); - assertEquals("mock_android/view/ViewGroup$LayoutParams", cr.getClassName()); - assertArrayEquals(new String[] { "mock_android.view.ViewGroup$LayoutParams" }, - found.keySet().toArray()); - assertArrayEquals(new ClassReader[] { cr }, found.values().toArray()); - } - - @Test - public void testFindGlobs() throws IOException, LogAbortException { - Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); - TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); - - // this matches classes, a package match returns nothing - found.clear(); - mAa.findGlobs("mock_android.view", zipClasses, found); - - assertArrayEquals(new String[] { }, - found.keySet().toArray()); - - // a complex glob search. * is a search pattern that matches names, not dots - mAa.findGlobs("mock_android.*.*Group$*Layout*", zipClasses, found); - - assertArrayEquals(new String[] { - "mock_android.view.ViewGroup$LayoutParams", - "mock_android.view.ViewGroup$MarginLayoutParams" - }, - found.keySet().toArray()); - - // a complex glob search. ** is a search pattern that matches names including dots - mAa.findGlobs("mock_android.**Group*", zipClasses, found); - - assertArrayEquals(new String[] { - "mock_android.view.ViewGroup", - "mock_android.view.ViewGroup$LayoutParams", - "mock_android.view.ViewGroup$MarginLayoutParams" - }, - found.keySet().toArray()); - - // matches a single class - found.clear(); - mAa.findGlobs("mock_android.view.View", zipClasses, found); - - assertArrayEquals(new String[] { - "mock_android.view.View" - }, - found.keySet().toArray()); - - // matches everyting inside the given package but not sub-packages - found.clear(); - mAa.findGlobs("mock_android.view.*", zipClasses, found); - - assertArrayEquals(new String[] { - "mock_android.view.View", - "mock_android.view.ViewGroup", - "mock_android.view.ViewGroup$LayoutParams", - "mock_android.view.ViewGroup$MarginLayoutParams" - }, - found.keySet().toArray()); - - for (String key : found.keySet()) { - ClassReader value = found.get(key); - assertNotNull("No value for " + key, value); - assertEquals(key, AsmAnalyzer.classReaderToClassName(value)); - } - } - - @Test - public void testFindClassesDerivingFrom() throws LogAbortException, IOException { - Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); - TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); - - mAa.findClassesDerivingFrom("mock_android.view.View", zipClasses, found); - - assertArrayEquals(new String[] { - "mock_android.view.View", - "mock_android.view.ViewGroup", - "mock_android.widget.LinearLayout", - "mock_android.widget.TableLayout", - }, - found.keySet().toArray()); - - for (String key : found.keySet()) { - ClassReader value = found.get(key); - assertNotNull("No value for " + key, value); - assertEquals(key, AsmAnalyzer.classReaderToClassName(value)); - } - } - - @Test - public void testDependencyVisitor() throws IOException, LogAbortException { - Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); - TreeMap<String, ClassReader> keep = new TreeMap<String, ClassReader>(); - TreeMap<String, ClassReader> new_keep = new TreeMap<String, ClassReader>(); - TreeMap<String, ClassReader> in_deps = new TreeMap<String, ClassReader>(); - TreeMap<String, ClassReader> out_deps = new TreeMap<String, ClassReader>(); - - ClassReader cr = mAa.findClass("mock_android.widget.TableLayout", zipClasses, keep); - DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps); - - // get first level dependencies - cr.accept(visitor, 0 /* flags */); - - assertArrayEquals(new String[] { - "mock_android.view.ViewGroup", - "mock_android.widget.TableLayout$LayoutParams", - }, - out_deps.keySet().toArray()); - - in_deps.putAll(out_deps); - out_deps.clear(); - - // get second level dependencies - for (ClassReader cr2 : in_deps.values()) { - cr2.accept(visitor, 0 /* flags */); - } - - assertArrayEquals(new String[] { - "mock_android.view.View", - "mock_android.view.ViewGroup$LayoutParams", - "mock_android.view.ViewGroup$MarginLayoutParams", - }, - out_deps.keySet().toArray()); - - in_deps.putAll(out_deps); - out_deps.clear(); - - // get third level dependencies (there are none) - for (ClassReader cr2 : in_deps.values()) { - cr2.accept(visitor, 0 /* flags */); - } - - assertArrayEquals(new String[] { }, out_deps.keySet().toArray()); - } -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java deleted file mode 100644 index 7b76a5b..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - - -package com.android.tools.layoutlib.create; - - -import static org.junit.Assert.assertArrayEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Set; - -/** - * Unit tests for some methods of {@link AsmGenerator}. - */ -public class AsmGeneratorTest { - - private MockLog mLog; - private ArrayList<String> mOsJarPath; - private String mOsDestJar; - private File mTempFile; - - @Before - public void setUp() throws Exception { - mLog = new MockLog(); - URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar"); - - mOsJarPath = new ArrayList<String>(); - mOsJarPath.add(url.getFile()); - - mTempFile = File.createTempFile("mock", "jar"); - mOsDestJar = mTempFile.getAbsolutePath(); - mTempFile.deleteOnExit(); - } - - @After - public void tearDown() throws Exception { - if (mTempFile != null) { - mTempFile.delete(); - mTempFile = null; - } - } - - @Test - public void testClassRenaming() throws IOException, LogAbortException { - - ICreateInfo ci = new ICreateInfo() { - @Override - public Class<?>[] getInjectedClasses() { - // classes to inject in the final JAR - return new Class<?>[0]; - } - - @Override - public String[] getDelegateMethods() { - return new String[0]; - } - - @Override - public String[] getDelegateClassNatives() { - return new String[0]; - } - - @Override - public String[] getOverriddenMethods() { - // methods to force override - return new String[0]; - } - - @Override - public String[] getRenamedClasses() { - // classes to rename (so that we can replace them) - return new String[] { - "mock_android.view.View", "mock_android.view._Original_View", - "not.an.actual.ClassName", "anoter.fake.NewClassName", - }; - } - - @Override - public String[] getDeleteReturns() { - // methods deleted from their return type. - return new String[0]; - } - }; - - AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci); - - AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen, - null, // derived from - new String[] { // include classes - "**" - }); - aa.analyze(); - agen.generate(); - - Set<String> notRenamed = agen.getClassesNotRenamed(); - assertArrayEquals(new String[] { "not/an/actual/ClassName" }, notRenamed.toArray()); - } -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java deleted file mode 100644 index 0135c40..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create; - -import static org.junit.Assert.*; - -import org.junit.Test; -import org.objectweb.asm.ClassReader; - -import java.io.IOException; -import java.util.ArrayList; - - -/** - * Tests {@link ClassHasNativeVisitor}. - */ -public class ClassHasNativeVisitorTest { - - @Test - public void testHasNative() throws IOException { - MockClassHasNativeVisitor cv = new MockClassHasNativeVisitor(); - String className = - this.getClass().getCanonicalName() + "$" + ClassWithNative.class.getSimpleName(); - ClassReader cr = new ClassReader(className); - - cr.accept(cv, 0 /* flags */); - assertArrayEquals(new String[] { "native_method" }, cv.getMethodsFound()); - assertTrue(cv.hasNativeMethods()); - } - - @Test - public void testHasNoNative() throws IOException { - MockClassHasNativeVisitor cv = new MockClassHasNativeVisitor(); - String className = - this.getClass().getCanonicalName() + "$" + ClassWithoutNative.class.getSimpleName(); - ClassReader cr = new ClassReader(className); - - cr.accept(cv, 0 /* flags */); - assertArrayEquals(new String[0], cv.getMethodsFound()); - assertFalse(cv.hasNativeMethods()); - } - - //------- - - /** - * Overrides {@link ClassHasNativeVisitor} to collec the name of the native methods found. - */ - private static class MockClassHasNativeVisitor extends ClassHasNativeVisitor { - private ArrayList<String> mMethodsFound = new ArrayList<String>(); - - public String[] getMethodsFound() { - return mMethodsFound.toArray(new String[mMethodsFound.size()]); - } - - @Override - protected void setHasNativeMethods(boolean hasNativeMethods, String methodName) { - if (hasNativeMethods) { - mMethodsFound.add(methodName); - } - super.setHasNativeMethods(hasNativeMethods, methodName); - } - } - - /** - * Dummy test class with a native method. - */ - public static class ClassWithNative { - public ClassWithNative() { - } - - public void callTheNativeMethod() { - native_method(); - } - - private native void native_method(); - } - - /** - * Dummy test class with no native method. - */ - public static class ClassWithoutNative { - public ClassWithoutNative() { - } - - public void someMethod() { - } - } -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java deleted file mode 100644 index 6e120ce..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create; - - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.android.tools.layoutlib.create.dataclass.ClassWithNative; -import com.android.tools.layoutlib.create.dataclass.OuterClass; -import com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass; - -import org.junit.Before; -import org.junit.Test; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -public class DelegateClassAdapterTest { - - private MockLog mLog; - - private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getCanonicalName(); - private static final String OUTER_CLASS_NAME = OuterClass.class.getCanonicalName(); - private static final String INNER_CLASS_NAME = OuterClass.class.getCanonicalName() + "$" + - InnerClass.class.getSimpleName(); - - @Before - public void setUp() throws Exception { - mLog = new MockLog(); - mLog.setVerbose(true); // capture debug error too - } - - /** - * Tests that a class not being modified still works. - */ - @SuppressWarnings("unchecked") - @Test - public void testNoOp() throws Throwable { - // create an instance of the class that will be modified - // (load the class in a distinct class loader so that we can trash its definition later) - ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) { }; - Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME); - ClassWithNative instance1 = clazz1.newInstance(); - assertEquals(42, instance1.add(20, 22)); - try { - instance1.callNativeInstance(10, 3.1415, new Object[0] ); - fail("Test should have failed to invoke callTheNativeMethod [1]"); - } catch (UnsatisfiedLinkError e) { - // This is expected to fail since the native method is not implemented. - } - - // Now process it but tell the delegate to not modify any method - ClassWriter cw = new ClassWriter(0 /*flags*/); - - HashSet<String> delegateMethods = new HashSet<String>(); - String internalClassName = NATIVE_CLASS_NAME.replace('.', '/'); - DelegateClassAdapter cv = new DelegateClassAdapter( - mLog, cw, internalClassName, delegateMethods); - - ClassReader cr = new ClassReader(NATIVE_CLASS_NAME); - cr.accept(cv, 0 /* flags */); - - // Load the generated class in a different class loader and try it again - - ClassLoader2 cl2 = null; - try { - cl2 = new ClassLoader2() { - @Override - public void testModifiedInstance() throws Exception { - Class<?> clazz2 = loadClass(NATIVE_CLASS_NAME); - Object i2 = clazz2.newInstance(); - assertNotNull(i2); - assertEquals(42, callAdd(i2, 20, 22)); - - try { - callCallNativeInstance(i2, 10, 3.1415, new Object[0]); - fail("Test should have failed to invoke callTheNativeMethod [2]"); - } catch (InvocationTargetException e) { - // This is expected to fail since the native method has NOT been - // overridden here. - assertEquals(UnsatisfiedLinkError.class, e.getCause().getClass()); - } - - // Check that the native method does NOT have the new annotation - Method[] m = clazz2.getDeclaredMethods(); - assertEquals("native_instance", m[2].getName()); - assertTrue(Modifier.isNative(m[2].getModifiers())); - Annotation[] a = m[2].getAnnotations(); - assertEquals(0, a.length); - } - }; - cl2.add(NATIVE_CLASS_NAME, cw); - cl2.testModifiedInstance(); - } catch (Throwable t) { - throw dumpGeneratedClass(t, cl2); - } - } - - /** - * {@link DelegateMethodAdapter2} does not support overriding constructors yet, - * so this should fail with an {@link UnsupportedOperationException}. - * - * Although not tested here, the message of the exception should contain the - * constructor signature. - */ - @Test(expected=UnsupportedOperationException.class) - public void testConstructorsNotSupported() throws IOException { - ClassWriter cw = new ClassWriter(0 /*flags*/); - - String internalClassName = NATIVE_CLASS_NAME.replace('.', '/'); - - HashSet<String> delegateMethods = new HashSet<String>(); - delegateMethods.add("<init>"); - DelegateClassAdapter cv = new DelegateClassAdapter( - mLog, cw, internalClassName, delegateMethods); - - ClassReader cr = new ClassReader(NATIVE_CLASS_NAME); - cr.accept(cv, 0 /* flags */); - } - - @Test - public void testDelegateNative() throws Throwable { - ClassWriter cw = new ClassWriter(0 /*flags*/); - String internalClassName = NATIVE_CLASS_NAME.replace('.', '/'); - - HashSet<String> delegateMethods = new HashSet<String>(); - delegateMethods.add(DelegateClassAdapter.ALL_NATIVES); - DelegateClassAdapter cv = new DelegateClassAdapter( - mLog, cw, internalClassName, delegateMethods); - - ClassReader cr = new ClassReader(NATIVE_CLASS_NAME); - cr.accept(cv, 0 /* flags */); - - // Load the generated class in a different class loader and try it - ClassLoader2 cl2 = null; - try { - cl2 = new ClassLoader2() { - @Override - public void testModifiedInstance() throws Exception { - Class<?> clazz2 = loadClass(NATIVE_CLASS_NAME); - Object i2 = clazz2.newInstance(); - assertNotNull(i2); - - // Use reflection to access inner methods - assertEquals(42, callAdd(i2, 20, 22)); - - Object[] objResult = new Object[] { null }; - int result = callCallNativeInstance(i2, 10, 3.1415, objResult); - assertEquals((int)(10 + 3.1415), result); - assertSame(i2, objResult[0]); - - // Check that the native method now has the new annotation and is not native - Method[] m = clazz2.getDeclaredMethods(); - assertEquals("native_instance", m[2].getName()); - assertFalse(Modifier.isNative(m[2].getModifiers())); - Annotation[] a = m[2].getAnnotations(); - assertEquals("LayoutlibDelegate", a[0].annotationType().getSimpleName()); - } - }; - cl2.add(NATIVE_CLASS_NAME, cw); - cl2.testModifiedInstance(); - } catch (Throwable t) { - throw dumpGeneratedClass(t, cl2); - } - } - - @Test - public void testDelegateInner() throws Throwable { - // We'll delegate the "get" method of both the inner and outer class. - HashSet<String> delegateMethods = new HashSet<String>(); - delegateMethods.add("get"); - delegateMethods.add("privateMethod"); - - // Generate the delegate for the outer class. - ClassWriter cwOuter = new ClassWriter(0 /*flags*/); - String outerClassName = OUTER_CLASS_NAME.replace('.', '/'); - DelegateClassAdapter cvOuter = new DelegateClassAdapter( - mLog, cwOuter, outerClassName, delegateMethods); - ClassReader cr = new ClassReader(OUTER_CLASS_NAME); - cr.accept(cvOuter, 0 /* flags */); - - // Generate the delegate for the inner class. - ClassWriter cwInner = new ClassWriter(0 /*flags*/); - String innerClassName = INNER_CLASS_NAME.replace('.', '/'); - DelegateClassAdapter cvInner = new DelegateClassAdapter( - mLog, cwInner, innerClassName, delegateMethods); - cr = new ClassReader(INNER_CLASS_NAME); - cr.accept(cvInner, 0 /* flags */); - - // Load the generated classes in a different class loader and try them - ClassLoader2 cl2 = null; - try { - cl2 = new ClassLoader2() { - @Override - public void testModifiedInstance() throws Exception { - - // Check the outer class - Class<?> outerClazz2 = loadClass(OUTER_CLASS_NAME); - Object o2 = outerClazz2.newInstance(); - assertNotNull(o2); - - // The original Outer.get returns 1+10+20, - // but the delegate makes it return 4+10+20 - assertEquals(4+10+20, callGet(o2, 10, 20)); - assertEquals(1+10+20, callGet_Original(o2, 10, 20)); - - // The original Outer has a private method that is - // delegated. We should be able to call both the delegate - // and the original (which is now public). - assertEquals("outerPrivateMethod", - callMethod(o2, "privateMethod_Original", false /*makePublic*/)); - - // The original method is private, so by default we can't access it - boolean gotIllegalAccessException = false; - try { - callMethod(o2, "privateMethod", false /*makePublic*/); - } catch(IllegalAccessException e) { - gotIllegalAccessException = true; - } - assertTrue(gotIllegalAccessException); - // Try again, but now making it accessible - assertEquals("outerPrivate_Delegate", - callMethod(o2, "privateMethod", true /*makePublic*/)); - - // Check the inner class. Since it's not a static inner class, we need - // to use the hidden constructor that takes the outer class as first parameter. - Class<?> innerClazz2 = loadClass(INNER_CLASS_NAME); - Constructor<?> innerCons = innerClazz2.getConstructor( - new Class<?>[] { outerClazz2 }); - Object i2 = innerCons.newInstance(new Object[] { o2 }); - assertNotNull(i2); - - // The original Inner.get returns 3+10+20, - // but the delegate makes it return 6+10+20 - assertEquals(6+10+20, callGet(i2, 10, 20)); - assertEquals(3+10+20, callGet_Original(i2, 10, 20)); - } - }; - cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray()); - cl2.add(INNER_CLASS_NAME, cwInner.toByteArray()); - cl2.testModifiedInstance(); - } catch (Throwable t) { - throw dumpGeneratedClass(t, cl2); - } - } - - //------- - - /** - * A class loader than can define and instantiate our modified classes. - * <p/> - * The trick here is that this class loader will test our <em>modified</em> version - * of the classes, the one with the delegate calls. - * <p/> - * Trying to do so in the original class loader generates all sort of link issues because - * there are 2 different definitions of the same class name. This class loader will - * define and load the class when requested by name and provide helpers to access the - * instance methods via reflection. - */ - private abstract class ClassLoader2 extends ClassLoader { - - private final Map<String, byte[]> mClassDefs = new HashMap<String, byte[]>(); - - public ClassLoader2() { - super(null); - } - - public ClassLoader2 add(String className, byte[] definition) { - mClassDefs.put(className, definition); - return this; - } - - public ClassLoader2 add(String className, ClassWriter rewrittenClass) { - mClassDefs.put(className, rewrittenClass.toByteArray()); - return this; - } - - private Set<Entry<String, byte[]>> getByteCode() { - return mClassDefs.entrySet(); - } - - @SuppressWarnings("unused") - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - try { - return super.findClass(name); - } catch (ClassNotFoundException e) { - - byte[] def = mClassDefs.get(name); - if (def != null) { - // Load the modified ClassWithNative from its bytes representation. - return defineClass(name, def, 0, def.length); - } - - try { - // Load everything else from the original definition into the new class loader. - ClassReader cr = new ClassReader(name); - ClassWriter cw = new ClassWriter(0); - cr.accept(cw, 0); - byte[] bytes = cw.toByteArray(); - return defineClass(name, bytes, 0, bytes.length); - - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - } - - /** - * Accesses {@link OuterClass#get} or {@link InnerClass#get}via reflection. - */ - public int callGet(Object instance, int a, long b) throws Exception { - Method m = instance.getClass().getMethod("get", - new Class<?>[] { int.class, long.class } ); - - Object result = m.invoke(instance, new Object[] { a, b }); - return ((Integer) result).intValue(); - } - - /** - * Accesses the "_Original" methods for {@link OuterClass#get} - * or {@link InnerClass#get}via reflection. - */ - public int callGet_Original(Object instance, int a, long b) throws Exception { - Method m = instance.getClass().getMethod("get_Original", - new Class<?>[] { int.class, long.class } ); - - Object result = m.invoke(instance, new Object[] { a, b }); - return ((Integer) result).intValue(); - } - - /** - * Accesses the any declared method that takes no parameter via reflection. - */ - @SuppressWarnings("unchecked") - public <T> T callMethod(Object instance, String methodName, boolean makePublic) throws Exception { - Method m = instance.getClass().getDeclaredMethod(methodName, (Class<?>[])null); - - boolean wasAccessible = m.isAccessible(); - if (makePublic && !wasAccessible) { - m.setAccessible(true); - } - - Object result = m.invoke(instance, (Object[])null); - - if (makePublic && !wasAccessible) { - m.setAccessible(false); - } - - return (T) result; - } - - /** - * Accesses {@link ClassWithNative#add(int, int)} via reflection. - */ - public int callAdd(Object instance, int a, int b) throws Exception { - Method m = instance.getClass().getMethod("add", - new Class<?>[] { int.class, int.class }); - - Object result = m.invoke(instance, new Object[] { a, b }); - return ((Integer) result).intValue(); - } - - /** - * Accesses {@link ClassWithNative#callNativeInstance(int, double, Object[])} - * via reflection. - */ - public int callCallNativeInstance(Object instance, int a, double d, Object[] o) - throws Exception { - Method m = instance.getClass().getMethod("callNativeInstance", - new Class<?>[] { int.class, double.class, Object[].class }); - - Object result = m.invoke(instance, new Object[] { a, d, o }); - return ((Integer) result).intValue(); - } - - public abstract void testModifiedInstance() throws Exception; - } - - /** - * For debugging, it's useful to dump the content of the generated classes - * along with the exception that was generated. - * - * However to make it work you need to pull in the org.objectweb.asm.util.TraceClassVisitor - * class and associated utilities which are found in the ASM source jar. Since we don't - * want that dependency in the source code, we only put it manually for development and - * access the TraceClassVisitor via reflection if present. - * - * @param t The exception thrown by {@link ClassLoader2#testModifiedInstance()} - * @param cl2 The {@link ClassLoader2} instance with the generated bytecode. - * @return Either original {@code t} or a new wrapper {@link Throwable} - */ - private Throwable dumpGeneratedClass(Throwable t, ClassLoader2 cl2) { - try { - // For debugging, dump the bytecode of the class in case of unexpected error - // if we can find the TraceClassVisitor class. - Class<?> tcvClass = Class.forName("org.objectweb.asm.util.TraceClassVisitor"); - - StringBuilder sb = new StringBuilder(); - sb.append('\n').append(t.getClass().getCanonicalName()); - if (t.getMessage() != null) { - sb.append(": ").append(t.getMessage()); - } - - for (Entry<String, byte[]> entry : cl2.getByteCode()) { - String className = entry.getKey(); - byte[] bytes = entry.getValue(); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - // next 2 lines do: TraceClassVisitor tcv = new TraceClassVisitor(pw); - Constructor<?> cons = tcvClass.getConstructor(new Class<?>[] { pw.getClass() }); - Object tcv = cons.newInstance(new Object[] { pw }); - ClassReader cr2 = new ClassReader(bytes); - cr2.accept((ClassVisitor) tcv, 0 /* flags */); - - sb.append("\nBytecode dump: <").append(className).append(">:\n") - .append(sw.toString()); - } - - // Re-throw exception with new message - RuntimeException ex = new RuntimeException(sb.toString(), t); - return ex; - } catch (Throwable ignore) { - // In case of problem, just throw the original exception as-is. - return t; - } - } - -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/LogTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/LogTest.java deleted file mode 100644 index 1a5f653..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/LogTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -package com.android.tools.layoutlib.create; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class LogTest { - - private MockLog mLog; - - @Before - public void setUp() throws Exception { - mLog = new MockLog(); - } - - @After - public void tearDown() throws Exception { - // pass - } - - @Test - public void testDebug() { - assertEquals("", mLog.getOut()); - assertEquals("", mLog.getErr()); - - mLog.setVerbose(false); - mLog.debug("Test %d", 42); - assertEquals("", mLog.getOut()); - - mLog.setVerbose(true); - mLog.debug("Test %d", 42); - - assertEquals("Test 42\n", mLog.getOut()); - assertEquals("", mLog.getErr()); - } - - @Test - public void testInfo() { - assertEquals("", mLog.getOut()); - assertEquals("", mLog.getErr()); - - mLog.info("Test %d", 43); - - assertEquals("Test 43\n", mLog.getOut()); - assertEquals("", mLog.getErr()); - } - - @Test - public void testError() { - assertEquals("", mLog.getOut()); - assertEquals("", mLog.getErr()); - - mLog.error("Test %d", 44); - - assertEquals("", mLog.getOut()); - assertEquals("Test 44\n", mLog.getErr()); - } - - @Test - public void testException() { - assertEquals("", mLog.getOut()); - assertEquals("", mLog.getErr()); - - Exception e = new Exception("My Exception"); - mLog.exception(e, "Test %d", 44); - - assertEquals("", mLog.getOut()); - assertTrue(mLog.getErr().startsWith("Test 44\njava.lang.Exception: My Exception")); - } -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/MockLog.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/MockLog.java deleted file mode 100644 index de750a3..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/MockLog.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create; - - -public class MockLog extends Log { - StringBuilder mOut = new StringBuilder(); - StringBuilder mErr = new StringBuilder(); - - public String getOut() { - return mOut.toString(); - } - - public String getErr() { - return mErr.toString(); - } - - @Override - protected void outPrintln(String msg) { - mOut.append(msg); - mOut.append('\n'); - } - - @Override - protected void errPrintln(String msg) { - mErr.append(msg); - mErr.append('\n'); - } -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java deleted file mode 100644 index 90c6a9c..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - - -package com.android.tools.layoutlib.create; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * - */ -public class RenameClassAdapterTest { - - private RenameClassAdapter mOuter; - private RenameClassAdapter mInner; - - @Before - public void setUp() throws Exception { - mOuter = new RenameClassAdapter(null, // cv - "com.pack.Old", - "org.blah.New"); - - mInner = new RenameClassAdapter(null, // cv - "com.pack.Old$Inner", - "org.blah.New$Inner"); - } - - @After - public void tearDown() throws Exception { - } - - /** - * Renames a type, e.g. "Lcom.package.My;" - * If the type doesn't need to be renamed, returns the input string as-is. - */ - @Test - public void testRenameTypeDesc() { - - // primitive types are left untouched - assertEquals("I", mOuter.renameTypeDesc("I")); - assertEquals("D", mOuter.renameTypeDesc("D")); - assertEquals("V", mOuter.renameTypeDesc("V")); - - // object types that need no renaming are left untouched - assertEquals("Lcom.package.MyClass;", mOuter.renameTypeDesc("Lcom.package.MyClass;")); - assertEquals("Lcom.package.MyClass;", mInner.renameTypeDesc("Lcom.package.MyClass;")); - - // object types that match the requirements - assertEquals("Lorg.blah.New;", mOuter.renameTypeDesc("Lcom.pack.Old;")); - assertEquals("Lorg.blah.New$Inner;", mInner.renameTypeDesc("Lcom.pack.Old$Inner;")); - // inner classes match the base type which is being renamed - assertEquals("Lorg.blah.New$Other;", mOuter.renameTypeDesc("Lcom.pack.Old$Other;")); - assertEquals("Lorg.blah.New$Other;", mInner.renameTypeDesc("Lcom.pack.Old$Other;")); - - // arrays - assertEquals("[Lorg.blah.New;", mOuter.renameTypeDesc("[Lcom.pack.Old;")); - assertEquals("[[Lorg.blah.New;", mOuter.renameTypeDesc("[[Lcom.pack.Old;")); - - assertEquals("[Lorg.blah.New;", mInner.renameTypeDesc("[Lcom.pack.Old;")); - assertEquals("[[Lorg.blah.New;", mInner.renameTypeDesc("[[Lcom.pack.Old;")); - } - - /** - * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an - * object element, e.g. "[Lcom.package.MyClass;" - * If the type doesn't need to be renamed, returns the internal name of the input type. - */ - @Test - public void testRenameType() { - // Skip. This is actually tested by testRenameTypeDesc above. - } - - /** - * Renames an internal type name, e.g. "com.package.MyClass". - * If the type doesn't need to be renamed, returns the input string as-is. - */ - @Test - public void testRenameInternalType() { - // a descriptor is not left untouched - assertEquals("Lorg.blah.New;", mOuter.renameInternalType("Lcom.pack.Old;")); - assertEquals("Lorg.blah.New$Inner;", mOuter.renameInternalType("Lcom.pack.Old$Inner;")); - - // an actual FQCN - assertEquals("org.blah.New", mOuter.renameInternalType("com.pack.Old")); - assertEquals("org.blah.New$Inner", mOuter.renameInternalType("com.pack.Old$Inner")); - - assertEquals("org.blah.New$Other", mInner.renameInternalType("com.pack.Old$Other")); - assertEquals("org.blah.New$Other", mInner.renameInternalType("com.pack.Old$Other")); - } - - /** - * Renames a method descriptor, i.e. applies renameType to all arguments and to the - * return value. - */ - @Test - public void testRenameMethodDesc() { - assertEquals("(IDLorg.blah.New;[Lorg.blah.New$Inner;)Lorg.blah.New$Other;", - mOuter.renameMethodDesc("(IDLcom.pack.Old;[Lcom.pack.Old$Inner;)Lcom.pack.Old$Other;")); - } - - - -} diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative.java deleted file mode 100644 index c314853..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create.dataclass; - -import com.android.tools.layoutlib.create.DelegateClassAdapterTest; - -/** - * Dummy test class with a native method. - * The native method is not defined and any attempt to invoke it will - * throw an {@link UnsatisfiedLinkError}. - * - * Used by {@link DelegateClassAdapterTest}. - */ -public class ClassWithNative { - public ClassWithNative() { - } - - public int add(int a, int b) { - return a + b; - } - - // Note: it's good to have a long or double for testing parameters since they take - // 2 slots in the stack/locals maps. - - public int callNativeInstance(int a, double d, Object[] o) { - return native_instance(a, d, o); - } - - private native int native_instance(int a, double d, Object[] o); -} - diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative_Delegate.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative_Delegate.java deleted file mode 100644 index a3d4dc6..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package com.android.tools.layoutlib.create.dataclass; - -import com.android.tools.layoutlib.create.DelegateClassAdapterTest; - -/** - * The delegate that receives the call to {@link ClassWithNative_Delegate}'s overridden methods. - * - * Used by {@link DelegateClassAdapterTest}. - */ -public class ClassWithNative_Delegate { - public static int native_instance(ClassWithNative instance, int a, double d, Object[] o) { - if (o != null && o.length > 0) { - o[0] = instance; - } - return (int)(a + d); - } -} - diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java deleted file mode 100644 index f083e76..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.tools.layoutlib.create.dataclass; - -import com.android.tools.layoutlib.create.DelegateClassAdapterTest; - -/** - * Test class with an inner class. - * - * Used by {@link DelegateClassAdapterTest}. - */ -public class OuterClass { - private int mOuterValue = 1; - public OuterClass() { - } - - // Outer.get returns 1 + a + b - // Note: it's good to have a long or double for testing parameters since they take - // 2 slots in the stack/locals maps. - public int get(int a, long b) { - return mOuterValue + a + (int) b; - } - - public class InnerClass { - public InnerClass() { - } - - // Inner.get returns 2 + 1 + a + b - public int get(int a, long b) { - return 2 + mOuterValue + a + (int) b; - } - } - - @SuppressWarnings("unused") - private String privateMethod() { - return "outerPrivateMethod"; - } -} - diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java deleted file mode 100644 index 774be8e..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.tools.layoutlib.create.dataclass; - -import com.android.tools.layoutlib.create.DelegateClassAdapterTest; - -/** - * Used by {@link DelegateClassAdapterTest}. - */ -public class OuterClass_Delegate { - // The delegate override of Outer.get returns 4 + a + b - public static int get(OuterClass instance, int a, long b) { - return 4 + a + (int) b; - } - - public static String privateMethod(OuterClass instance) { - return "outerPrivate_Delegate"; - } -} - diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_InnerClass_Delegate.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_InnerClass_Delegate.java deleted file mode 100644 index b472220..0000000 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_InnerClass_Delegate.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -package com.android.tools.layoutlib.create.dataclass; - -import com.android.tools.layoutlib.create.DelegateClassAdapterTest; -import com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass; - -/** - * Used by {@link DelegateClassAdapterTest}. - */ -public class OuterClass_InnerClass_Delegate { - // The delegate override of Inner.get return 6 + a + b - public static int get(OuterClass outer, InnerClass inner, int a, long b) { - return 6 + a + (int) b; - } -} diff --git a/tools/layoutlib/create/tests/data/mock_android.jar b/tools/layoutlib/create/tests/data/mock_android.jar Binary files differdeleted file mode 100644 index a7ea74f..0000000 --- a/tools/layoutlib/create/tests/data/mock_android.jar +++ /dev/null diff --git a/tools/layoutlib/create/tests/data/mock_android.jardesc b/tools/layoutlib/create/tests/data/mock_android.jardesc deleted file mode 100644 index 95f7591..0000000 --- a/tools/layoutlib/create/tests/data/mock_android.jardesc +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?> -<jardesc> - <jar path="C:/ralf/google/src/raphael-lapdroid/device/tools/layoutlib/create/tests/data/mock_android.jar"/> - <options buildIfNeeded="true" compress="true" descriptionLocation="/layoutlib_create/tests/data/mock_android.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> - <storedRefactorings deprecationInfo="true" structuralOnly="false"/> - <selectedProjects/> - <manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true"> - <sealing sealJar="false"> - <packagesToSeal/> - <packagesToUnSeal/> - </sealing> - </manifest> - <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false"> - <javaElement handleIdentifier="=layoutlib_create/tests<mock_android.widget"/> - <javaElement handleIdentifier="=layoutlib_create/tests<mock_android.view"/> - <javaElement handleIdentifier="=layoutlib_create/tests<mock_android.dummy"/> - </selectedElements> -</jardesc> diff --git a/tools/layoutlib/create/tests/mock_android/dummy/InnerTest.java b/tools/layoutlib/create/tests/mock_android/dummy/InnerTest.java deleted file mode 100644 index e355ead..0000000 --- a/tools/layoutlib/create/tests/mock_android/dummy/InnerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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. - */ - -package mock_android.dummy; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; - -public class InnerTest { - - private int mSomeField; - private MyStaticInnerClass mInnerInstance; - private MyIntEnum mTheIntEnum; - private MyGenerics1<int[][], InnerTest, MyIntEnum, float[]> mGeneric1; - - public class NotStaticInner2 extends NotStaticInner1 { - - } - - public class NotStaticInner1 { - - public void someThing() { - mSomeField = 2; - mInnerInstance = null; - } - - } - - private static class MyStaticInnerClass { - - } - - private static class DerivingClass extends InnerTest { - - } - - // enums are a kind of inner static class - public enum MyIntEnum { - VALUE0(0), - VALUE1(1), - VALUE2(2); - - MyIntEnum(int myInt) { - this.myInt = myInt; - } - final int myInt; - } - - public static class MyGenerics1<T, U, V, W> { - public MyGenerics1() { - int a = 1; - } - } - - public <X> void genericMethod1(X a, X[] a) { - } - - public <X, Y> void genericMethod2(X a, List<Y> b) { - } - - public <X, Y> void genericMethod3(X a, List<Y extends InnerTest> b) { - } - - public <T extends InnerTest> void genericMethod4(T[] a, Collection<T> b, Collection<?> c) { - Iterator<T> i = b.iterator(); - } - - public void someMethod(InnerTest self) { - mSomeField = self.mSomeField; - MyStaticInnerClass m = new MyStaticInnerClass(); - mInnerInstance = m; - mTheIntEnum = null; - mGeneric1 = new MyGenerics1(); - genericMethod(new DerivingClass[0], new ArrayList<DerivingClass>(), new ArrayList<InnerTest>()); - } -} diff --git a/tools/layoutlib/create/tests/mock_android/view/View.java b/tools/layoutlib/create/tests/mock_android/view/View.java deleted file mode 100644 index a80a98d..0000000 --- a/tools/layoutlib/create/tests/mock_android/view/View.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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. - */ - -package mock_android.view; - -public class View { - -} diff --git a/tools/layoutlib/create/tests/mock_android/view/ViewGroup.java b/tools/layoutlib/create/tests/mock_android/view/ViewGroup.java deleted file mode 100644 index 466470f..0000000 --- a/tools/layoutlib/create/tests/mock_android/view/ViewGroup.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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. - */ - -package mock_android.view; - -public class ViewGroup extends View { - - public class MarginLayoutParams extends LayoutParams { - - } - - public class LayoutParams { - - } - -} diff --git a/tools/layoutlib/create/tests/mock_android/widget/LinearLayout.java b/tools/layoutlib/create/tests/mock_android/widget/LinearLayout.java deleted file mode 100644 index 3870a63..0000000 --- a/tools/layoutlib/create/tests/mock_android/widget/LinearLayout.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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. - */ - -package mock_android.widget; - -import mock_android.view.ViewGroup; - -public class LinearLayout extends ViewGroup { - - public class LayoutParams extends mock_android.view.ViewGroup.LayoutParams { - - } - -} diff --git a/tools/layoutlib/create/tests/mock_android/widget/TableLayout.java b/tools/layoutlib/create/tests/mock_android/widget/TableLayout.java deleted file mode 100644 index e455e7d..0000000 --- a/tools/layoutlib/create/tests/mock_android/widget/TableLayout.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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. - */ - -package mock_android.widget; - -import mock_android.view.ViewGroup; - -public class TableLayout extends ViewGroup { - - public class LayoutParams extends MarginLayoutParams { - - } - -} diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk deleted file mode 100644 index 9ff56d6..0000000 --- a/tools/obbtool/Android.mk +++ /dev/null @@ -1,48 +0,0 @@ -# -# 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_CFLAGS := -Wall -Werror - -#LOCAL_C_INCLUDES += - -LOCAL_STATIC_LIBRARIES := \ - libandroidfw \ - libutils \ - libcutils \ - liblog - -ifeq ($(HOST_OS),linux) -LOCAL_LDLIBS += -ldl -lpthread -endif - -LOCAL_MODULE := obbtool - -include $(BUILD_HOST_EXECUTABLE) - -##################################################### -include $(CLEAR_VARS) - -LOCAL_MODULE := pbkdf2gen -LOCAL_MODULE_TAGS := optional -LOCAL_CFLAGS := -Wall -Werror -LOCAL_SRC_FILES := pbkdf2gen.cpp -LOCAL_LDLIBS += -ldl -LOCAL_C_INCLUDES := external/openssl/include $(LOCAL_C_INCLUDES) -LOCAL_STATIC_LIBRARIES := libcrypto_static - -include $(BUILD_HOST_EXECUTABLE) - -####################################################### -endif # TARGET_BUILD_APPS diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp deleted file mode 100644 index b2152e8..0000000 --- a/tools/obbtool/Main.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * 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 <androidfw/ObbFile.h> -#include <utils/String8.h> - -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -using namespace android; - -static const char* gProgName = "obbtool"; -static const char* gProgVersion = "1.0"; - -static int wantUsage = 0; -static int wantVersion = 0; - -#define SALT_LEN 8 - -#define ADD_OPTS "n:v:os:" -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'}, - {"salt", required_argument, NULL, 's'}, - - {NULL, 0, NULL, '\0'} -}; - -class PackageInfo { -public: - PackageInfo() - : packageName(NULL) - , packageVersion(-1) - , overlay(false) - , salted(false) - { - memset(&salt, 0, sizeof(salt)); - } - - char* packageName; - int packageVersion; - bool overlay; - bool salted; - unsigned char salt[SALT_LEN]; -}; - -/* - * 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, - " Options:\n" - " -n <package name> sets the OBB package name (required)\n" - " -v <OBB version> sets the OBB version (required)\n" - " -o sets the OBB overlay flag\n" - " -s <8 byte hex salt> sets the crypto key salt (if encrypted)\n" - "\n"); - 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 PackageInfo* 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 (info->salted) { - obb->setSalt(info->salt, SALT_LEN); - } - - 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"); - printf(" Salt: "); - - size_t saltLen; - const unsigned char* salt = obb->getSalt(&saltLen); - if (salt != NULL) { - for (int i = 0; i < SALT_LEN; i++) { - printf("%02x", salt[i]); - } - printf("\n"); - } else { - printf("<empty>\n"); - } -} - -bool fromHex(char h, unsigned char *b) { - if (h >= '0' && h <= '9') { - *b = h - '0'; - return true; - } else if (h >= 'a' && h <= 'f') { - *b = h - 'a' + 10; - return true; - } else if (h >= 'A' && h <= 'F') { - *b = h - 'A' + 10; - return true; - } - return false; -} - -bool hexToByte(char h1, char h2, unsigned char* b) { - unsigned char first, second; - if (!fromHex(h1, &first)) return false; - if (!fromHex(h2, &second)) return false; - *b = (first << 4) | second; - return true; -} - -/* - * Parse args. - */ -int main(int argc, char* const argv[]) -{ - int opt; - int option_index = 0; - struct PackageInfo 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 's': - if (strlen(optarg) != SALT_LEN * 2) { - fprintf(stderr, "ERROR: salt must be 8 bytes in hex (e.g., ABCD65031337D00D)\n\n"); - wantUsage = 1; - goto bail; - } - - package_info.salted = true; - - unsigned char b; - for (int i = 0, j = 0; i < SALT_LEN; i++, j+=2) { - if (!hexToByte(optarg[j], optarg[j+1], &b)) { - fprintf(stderr, "ERROR: salt must be in hex (e.g., ABCD65031337D00D)\n"); - wantUsage = 1; - goto bail; - } - package_info.salt[i] = b; - } - 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; -} diff --git a/tools/obbtool/mkobb.sh b/tools/obbtool/mkobb.sh deleted file mode 100755 index 725250d..0000000 --- a/tools/obbtool/mkobb.sh +++ /dev/null @@ -1,281 +0,0 @@ -#!/bin/bash -# -# 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. -# - -# mkobb.sh - Creates OBB files on Linux machines - -# Directory where we should temporarily mount the OBB loopback to copy files -MOUNTDIR=/tmp - -# Presets. Changing these will probably break your OBB on the device -CRYPTO=twofish -FS=vfat -MKFS=mkfs.vfat -LOSETUP=losetup -BLOCK_SIZE=512 -SLOP=512 # Amount of filesystem slop in ${BLOCK_SIZE} blocks - -find_binaries() { - MKFSBIN=`which ${MKFS}` - LOSETUPBIN=`which ${LOSETUP}` - MOUNTBIN=`which mount` - UMOUNTBIN=`which umount` - DDBIN=`which dd` - RSYNCBIN=`which rsync` - PBKDF2GEN=`which pbkdf2gen` -} - -check_prereqs() { - if [ "`uname -s`x" != "Linuxx" ]; then \ - echo "ERROR: This script only works on Linux!" - exit 1 - fi - - if ! egrep -q "^cryptoloop " /proc/modules; then \ - echo "ERROR: Could not find cryptoloop in the kernel." - echo "Perhaps you need to: modprobe cryptoloop" - exit 1 - fi - - if ! egrep -q "name\s*:\s*${CRYPTO}$" /proc/crypto; then \ - echo "ERROR: Could not find crypto \`${CRYPTO}' in the kernel." - echo "Perhaps you need to: modprobe ${CRYPTO}" - exit 1 - fi - - if ! egrep -q "^\s*${FS}$" /proc/filesystems; then \ - echo "ERROR: Could not find filesystem \`${FS}' in the kernel." - echo "Perhaps you need to: modprobe ${FS}" - exit 1 - fi - - if [ "${MKFSBIN}x" = "x" ]; then \ - echo "ERROR: Could not find ${MKFS} in your path!" - exit 1 - elif [ ! -x "${MKFSBIN}" ]; then \ - echo "ERROR: ${MKFSBIN} is not executable!" - exit 1 - fi - - if [ "${LOSETUPBIN}x" = "x" ]; then \ - echo "ERROR: Could not find ${LOSETUP} in your path!" - exit 1 - elif [ ! -x "${LOSETUPBIN}" ]; then \ - echo "ERROR: ${LOSETUPBIN} is not executable!" - exit 1 - fi - - if [ "${PBKDF2GEN}x" = "x" ]; then \ - echo "ERROR: Could not find pbkdf2gen in your path!" - exit 1 - fi -} - -cleanup() { - if [ "${loopdev}x" != "x" ]; then \ - ${LOSETUPBIN} -d ${loopdev} - fi -} - -hidden_prompt() { - unset output - prompt="$1" - outvar="$2" - while read -s -n 1 -p "$prompt" c; do \ - if [ "x$c" = "x" ]; then \ - break - fi - prompt='*' - output="${output}${c}" - done - echo - eval $outvar="$output" - unset output -} - -read_key() { - hidden_prompt " Encryption key: " key - - if [ "${key}x" = "x" ]; then \ - echo "ERROR: An empty key is not allowed!" - exit 1 - fi - - hidden_prompt "Encryption key (again): " key2 - - if [ "${key}x" != "${key2}x" ]; then \ - echo "ERROR: Encryption keys do not match!" - exit 1 - fi -} - -onexit() { - if [ "x${temp_mount}" != "x" ]; then \ - ${UMOUNTBIN} ${temp_mount} - rmdir ${temp_mount} - fi - if [ "x${loop_dev}" != "x" ]; then \ - if [ ${use_crypto} -eq 1 ]; then \ - dmsetup remove -f ${loop_dev} - ${LOSETUPBIN} -d ${old_loop_dev} - else \ - ${LOSETUPBIN} -d ${loop_dev} - fi - fi - if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \ - rm -f ${tempfile} - fi - if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \ - rm -f ${keyfile} - fi - echo "Fatal error." - exit 1 -} - -usage() { - echo "mkobb.sh -- Create OBB files for use on Android" - echo "" - echo " -d <directory> Use <directory> as input for OBB files" - echo " -k <key> Use <key> to encrypt OBB file" - echo " -K Prompt for key to encrypt OBB file" - echo " -o <filename> Write OBB file out to <filename>" - echo " -v Verbose mode" - echo " -h Help; this usage screen" -} - -find_binaries -check_prereqs - -use_crypto=0 - -args=`getopt -o d:hk:Ko:v -- "$@"` -eval set -- "$args" - -while true; do \ - case "$1" in - -d) directory=$2; shift 2;; - -h) usage; exit 1;; - -k) key=$2; use_crypto=1; shift 2;; - -K) prompt_key=1; use_crypto=1; shift;; - -v) verbose=1; shift;; - -o) filename=$2; shift 2;; - --) shift; break;; - *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;; - esac -done - -if [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \ - echo "ERROR: Must specify valid input directory" - echo "" - usage - exit 1; -fi - -if [ "${filename}x" = "x" ]; then \ - echo "ERROR: Must specify filename" - echo "" - usage - exit 1; -fi - -if [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \ - echo "ERROR: Crypto desired, but no key supplied or requested to prompt for." - exit 1 -fi - -if [ 0${prompt_key} -eq 1 ]; then \ - read_key -fi - -outdir=`dirname ${filename}` -if [ ! -d "${outdir}" ]; then \ - echo "ERROR: Output directory does not exist: ${outdir}" - exit 1 -fi - -# Make sure we clean up any stuff we create from here on during error conditions -trap onexit ERR - -tempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 ) - -block_count=`du -s --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'` -if [ $? -ne 0 ]; then \ - echo "ERROR: Couldn't read size of input directory ${directory}" - exit 1 -fi - -echo "Creating temporary file..." -${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1 -if [ $? -ne 0 ]; then \ - echo "ERROR: creating temporary file: $?" -fi - -loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 ) - -${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 ) - -if [ ${use_crypto} -eq 1 ]; then \ - eval `${PBKDF2GEN} ${key}` - unique_dm_name=`basename ${tempfile}` - echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name} - old_loop_dev=${loop_dev} - loop_dev=/dev/mapper/${unique_dm_name} -fi - -# -# Create the filesystem -# -echo "" -${MKFSBIN} -I ${loop_dev} -echo "" - -# -# Make the temporary mount point and mount it -# -temp_mount="${MOUNTDIR}/${RANDOM}" -mkdir ${temp_mount} -${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount} - -# -# rsync the files! -# -echo "Copying files:" -${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/ -echo "" - -echo "Successfully created \`${filename}'" - -if [ ${use_crypto} -eq 1 ]; then \ - echo "salt for use with obbtool is:" - echo "${salt}" -fi - -# -# Undo all the temporaries -# -umount ${temp_mount} -rmdir ${temp_mount} -if [ ${use_crypto} -eq 1 ]; then \ - dmsetup remove -f ${loop_dev} - ${LOSETUPBIN} -d ${old_loop_dev} -else \ - ${LOSETUPBIN} -d ${loop_dev} -fi -mv ${tempfile} ${filename} - -trap - ERR - -exit 0 diff --git a/tools/obbtool/pbkdf2gen.cpp b/tools/obbtool/pbkdf2gen.cpp deleted file mode 100644 index 98d67c0..0000000 --- a/tools/obbtool/pbkdf2gen.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 <openssl/evp.h> - -#include <sys/types.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -/** - * Simple program to generate a key based on PBKDF2 with preset inputs. - * - * Will print out the salt and key in hex. - */ - -#define SALT_LEN 8 -#define ROUNDS 1024 -#define KEY_BITS 128 - -int main(int argc, char* argv[]) -{ - if (argc != 2) { - fprintf(stderr, "Usage: %s <password>\n", argv[0]); - exit(1); - } - - int fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Could not open /dev/urandom: %s\n", strerror(errno)); - close(fd); - exit(1); - } - - unsigned char salt[SALT_LEN]; - - if (read(fd, &salt, SALT_LEN) != SALT_LEN) { - fprintf(stderr, "Could not read salt from /dev/urandom: %s\n", strerror(errno)); - close(fd); - exit(1); - } - close(fd); - - unsigned char rawKey[KEY_BITS]; - - if (PKCS5_PBKDF2_HMAC_SHA1(argv[1], strlen(argv[1]), salt, SALT_LEN, - ROUNDS, KEY_BITS, rawKey) != 1) { - fprintf(stderr, "Could not generate PBKDF2 output: %s\n", strerror(errno)); - exit(1); - } - - printf("salt="); - for (int i = 0; i < SALT_LEN; i++) { - printf("%02x", salt[i]); - } - printf("\n"); - - printf("key="); - for (int i = 0; i < (KEY_BITS / 8); i++) { - printf("%02x", rawKey[i]); - } - printf("\n"); -} diff --git a/tools/orientationplot/README.txt b/tools/orientationplot/README.txt deleted file mode 100644 index d53f65e..0000000 --- a/tools/orientationplot/README.txt +++ /dev/null @@ -1,87 +0,0 @@ -This directory contains a simple python script for visualizing -the behavior of the WindowOrientationListener. - - -PREREQUISITES -------------- - -1. Python 2.6 -2. numpy -3. matplotlib - - -USAGE ------ - -The tool works by scaping the debug log output from WindowOrientationListener -for interesting data and then plotting it. - -1. Plug in the device. Ensure that it is the only device plugged in - since this script is of very little brain and will get confused otherwise. - -2. Enable the Window Orientation Listener debugging data log. - adb shell setprop debug.orientation.log true - adb shell stop - adb shell start - -3. Run "orientationplot.py". - - -WHAT IT ALL MEANS ------------------ - -The tool displays several time series graphs that plot the output of the -WindowOrientationListener. Here you can see the raw accelerometer data, -filtered accelerometer data, measured tilt and orientation angle, confidence -intervals for the proposed orientation and accelerometer latency. - -Things to look for: - -1. Ensure the filtering is not too aggressive. If the filter cut-off frequency is - less than about 1Hz, then the filtered accelorometer data becomes too smooth - and the latency for orientation detection goes up. One way to observe this - is by holding the device vertically in one orientation then sharply turning - it 90 degrees to a different orientation. Compared the rapid changes in the - raw accelerometer data with the smoothed out filtered data. If the filtering - is too aggressive, the filter response may lag by hundreds of milliseconds. - -2. Ensure that there is an appropriate gap between adjacent orientation angles - for hysteresis. Try holding the device in one orientation and slowly turning - it 90 degrees. Note that the confidence intervals will all drop to 0 at some - point in between the two orientations; that is the gap. The gap should be - observed between all adjacent pairs of orientations when turning the device - in either direction. - - Next try holding the device in one orientation and rapidly turning it end - over end to a midpoint about 45 degrees between two opposing orientations. - There should be no gap observed initially. The algorithm should pick one - of the orientations and settle into it (since it is obviously quite - different from the original orientation of the device). However, once it - settles, the confidence values should start trending to 0 again because - the measured orientation angle is now within the gap between the new - orientation and the adjacent orientation. - - In other words, the hysteresis gap applies only when the measured orientation - angle (say, 45 degrees) is between the current orientation's ideal angle - (say, 0 degrees) and an adjacent orientation's ideal angle (say, 90 degrees). - -3. Accelerometer jitter. The accelerometer latency graph displays the interval - between sensor events as reported by the SensorEvent.timestamp field. It - should be a fairly constant 60ms. If the latency jumps around wildly or - greatly exceeds 60ms then there is a problem with the accelerometer or the - sensor manager. - -4. The orientation angle is not measured when the tilt is too close to 90 or -90 - degrees (refer to MAX_TILT constant). Consequently, you should expect there - to be no data. Likewise, all dependent calculations are suppressed in this case - so there will be no orientation proposal either. - -5. Each orientation has its own bound on allowable tilt angles. It's a good idea to - verify that these limits are being enforced by gradually varying the tilt of - the device until it is inside/outside the limit for each orientation. - -6. Orientation changes should be significantly harder when the device is held - overhead. People reading on tablets in bed often have their head turned - a little to the side, or they hold the device loosely so its orientation - can be a bit unusual. The tilt is a good indicator of whether the device is - overhead. diff --git a/tools/orientationplot/orientationplot.py b/tools/orientationplot/orientationplot.py deleted file mode 100755 index 6fc3922..0000000 --- a/tools/orientationplot/orientationplot.py +++ /dev/null @@ -1,457 +0,0 @@ -#!/usr/bin/env python2.6 -# -# Copyright (C) 2011 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. -# - -# -# Plots debug log output from WindowOrientationListener. -# See README.txt for details. -# - -import numpy as np -import matplotlib.pyplot as plot -import subprocess -import re -import fcntl -import os -import errno -import bisect -from datetime import datetime, timedelta - -# Parameters. -timespan = 15 # seconds total span shown -scrolljump = 5 # seconds jump when scrolling -timeticks = 1 # seconds between each time tick - -# Non-blocking stream wrapper. -class NonBlockingStream: - def __init__(self, stream): - fcntl.fcntl(stream, fcntl.F_SETFL, os.O_NONBLOCK) - self.stream = stream - self.buffer = '' - self.pos = 0 - - def readline(self): - while True: - index = self.buffer.find('\n', self.pos) - if index != -1: - result = self.buffer[self.pos:index] - self.pos = index + 1 - return result - - self.buffer = self.buffer[self.pos:] - self.pos = 0 - try: - chunk = os.read(self.stream.fileno(), 4096) - except OSError, e: - if e.errno == errno.EAGAIN: - return None - raise e - if len(chunk) == 0: - if len(self.buffer) == 0: - raise(EOFError) - else: - result = self.buffer - self.buffer = '' - self.pos = 0 - return result - self.buffer += chunk - -# Plotter -class Plotter: - def __init__(self, adbout): - self.adbout = adbout - - self.fig = plot.figure(1) - self.fig.suptitle('Window Orientation Listener', fontsize=12) - self.fig.set_dpi(96) - self.fig.set_size_inches(16, 12, forward=True) - - self.raw_acceleration_x = self._make_timeseries() - self.raw_acceleration_y = self._make_timeseries() - self.raw_acceleration_z = self._make_timeseries() - self.raw_acceleration_magnitude = self._make_timeseries() - self.raw_acceleration_axes = self._add_timeseries_axes( - 1, 'Raw Acceleration', 'm/s^2', [-20, 20], - yticks=range(-15, 16, 5)) - self.raw_acceleration_line_x = self._add_timeseries_line( - self.raw_acceleration_axes, 'x', 'red') - self.raw_acceleration_line_y = self._add_timeseries_line( - self.raw_acceleration_axes, 'y', 'green') - self.raw_acceleration_line_z = self._add_timeseries_line( - self.raw_acceleration_axes, 'z', 'blue') - self.raw_acceleration_line_magnitude = self._add_timeseries_line( - self.raw_acceleration_axes, 'magnitude', 'orange', linewidth=2) - self._add_timeseries_legend(self.raw_acceleration_axes) - - shared_axis = self.raw_acceleration_axes - - self.filtered_acceleration_x = self._make_timeseries() - self.filtered_acceleration_y = self._make_timeseries() - self.filtered_acceleration_z = self._make_timeseries() - self.filtered_acceleration_magnitude = self._make_timeseries() - self.filtered_acceleration_axes = self._add_timeseries_axes( - 2, 'Filtered Acceleration', 'm/s^2', [-20, 20], - sharex=shared_axis, - yticks=range(-15, 16, 5)) - self.filtered_acceleration_line_x = self._add_timeseries_line( - self.filtered_acceleration_axes, 'x', 'red') - self.filtered_acceleration_line_y = self._add_timeseries_line( - self.filtered_acceleration_axes, 'y', 'green') - self.filtered_acceleration_line_z = self._add_timeseries_line( - self.filtered_acceleration_axes, 'z', 'blue') - self.filtered_acceleration_line_magnitude = self._add_timeseries_line( - self.filtered_acceleration_axes, 'magnitude', 'orange', linewidth=2) - self._add_timeseries_legend(self.filtered_acceleration_axes) - - self.tilt_angle = self._make_timeseries() - self.tilt_angle_axes = self._add_timeseries_axes( - 3, 'Tilt Angle', 'degrees', [-105, 105], - sharex=shared_axis, - yticks=range(-90, 91, 30)) - self.tilt_angle_line = self._add_timeseries_line( - self.tilt_angle_axes, 'tilt', 'black') - self._add_timeseries_legend(self.tilt_angle_axes) - - self.orientation_angle = self._make_timeseries() - self.orientation_angle_axes = self._add_timeseries_axes( - 4, 'Orientation Angle', 'degrees', [-25, 375], - sharex=shared_axis, - yticks=range(0, 361, 45)) - self.orientation_angle_line = self._add_timeseries_line( - self.orientation_angle_axes, 'orientation', 'black') - self._add_timeseries_legend(self.orientation_angle_axes) - - self.current_rotation = self._make_timeseries() - self.proposed_rotation = self._make_timeseries() - self.predicted_rotation = self._make_timeseries() - self.orientation_axes = self._add_timeseries_axes( - 5, 'Current / Proposed Orientation', 'rotation', [-1, 4], - sharex=shared_axis, - yticks=range(0, 4)) - self.current_rotation_line = self._add_timeseries_line( - self.orientation_axes, 'current', 'black', linewidth=2) - self.predicted_rotation_line = self._add_timeseries_line( - self.orientation_axes, 'predicted', 'purple', linewidth=3) - self.proposed_rotation_line = self._add_timeseries_line( - self.orientation_axes, 'proposed', 'green', linewidth=3) - self._add_timeseries_legend(self.orientation_axes) - - self.time_until_settled = self._make_timeseries() - self.time_until_flat_delay_expired = self._make_timeseries() - self.time_until_swing_delay_expired = self._make_timeseries() - self.time_until_acceleration_delay_expired = self._make_timeseries() - self.stability_axes = self._add_timeseries_axes( - 6, 'Proposal Stability', 'ms', [-10, 600], - sharex=shared_axis, - yticks=range(0, 600, 100)) - self.time_until_settled_line = self._add_timeseries_line( - self.stability_axes, 'time until settled', 'black', linewidth=2) - self.time_until_flat_delay_expired_line = self._add_timeseries_line( - self.stability_axes, 'time until flat delay expired', 'green') - self.time_until_swing_delay_expired_line = self._add_timeseries_line( - self.stability_axes, 'time until swing delay expired', 'blue') - self.time_until_acceleration_delay_expired_line = self._add_timeseries_line( - self.stability_axes, 'time until acceleration delay expired', 'red') - self._add_timeseries_legend(self.stability_axes) - - self.sample_latency = self._make_timeseries() - self.sample_latency_axes = self._add_timeseries_axes( - 7, 'Accelerometer Sampling Latency', 'ms', [-10, 500], - sharex=shared_axis, - yticks=range(0, 500, 100)) - self.sample_latency_line = self._add_timeseries_line( - self.sample_latency_axes, 'latency', 'black') - self._add_timeseries_legend(self.sample_latency_axes) - - self.fig.canvas.mpl_connect('button_press_event', self._on_click) - self.paused = False - - self.timer = self.fig.canvas.new_timer(interval=100) - self.timer.add_callback(lambda: self.update()) - self.timer.start() - - self.timebase = None - self._reset_parse_state() - - # Handle a click event to pause or restart the timer. - def _on_click(self, ev): - if not self.paused: - self.paused = True - self.timer.stop() - else: - self.paused = False - self.timer.start() - - # Initialize a time series. - def _make_timeseries(self): - return [[], []] - - # Add a subplot to the figure for a time series. - def _add_timeseries_axes(self, index, title, ylabel, ylim, yticks, sharex=None): - num_graphs = 7 - height = 0.9 / num_graphs - top = 0.95 - height * index - axes = self.fig.add_axes([0.1, top, 0.8, height], - xscale='linear', - xlim=[0, timespan], - ylabel=ylabel, - yscale='linear', - ylim=ylim, - sharex=sharex) - axes.text(0.02, 0.02, title, transform=axes.transAxes, fontsize=10, fontweight='bold') - axes.set_xlabel('time (s)', fontsize=10, fontweight='bold') - axes.set_ylabel(ylabel, fontsize=10, fontweight='bold') - axes.set_xticks(range(0, timespan + 1, timeticks)) - axes.set_yticks(yticks) - axes.grid(True) - - for label in axes.get_xticklabels(): - label.set_fontsize(9) - for label in axes.get_yticklabels(): - label.set_fontsize(9) - - return axes - - # Add a line to the axes for a time series. - def _add_timeseries_line(self, axes, label, color, linewidth=1): - return axes.plot([], label=label, color=color, linewidth=linewidth)[0] - - # Add a legend to a time series. - def _add_timeseries_legend(self, axes): - axes.legend( - loc='upper left', - bbox_to_anchor=(1.01, 1), - borderpad=0.1, - borderaxespad=0.1, - prop={'size': 10}) - - # Resets the parse state. - def _reset_parse_state(self): - self.parse_raw_acceleration_x = None - self.parse_raw_acceleration_y = None - self.parse_raw_acceleration_z = None - self.parse_raw_acceleration_magnitude = None - self.parse_filtered_acceleration_x = None - self.parse_filtered_acceleration_y = None - self.parse_filtered_acceleration_z = None - self.parse_filtered_acceleration_magnitude = None - self.parse_tilt_angle = None - self.parse_orientation_angle = None - self.parse_current_rotation = None - self.parse_proposed_rotation = None - self.parse_predicted_rotation = None - self.parse_time_until_settled = None - self.parse_time_until_flat_delay_expired = None - self.parse_time_until_swing_delay_expired = None - self.parse_time_until_acceleration_delay_expired = None - self.parse_sample_latency = None - - # Update samples. - def update(self): - timeindex = 0 - while True: - try: - line = self.adbout.readline() - except EOFError: - plot.close() - return - if line is None: - break - print line - - try: - timestamp = self._parse_timestamp(line) - except ValueError, e: - continue - if self.timebase is None: - self.timebase = timestamp - delta = timestamp - self.timebase - timeindex = delta.seconds + delta.microseconds * 0.000001 - - if line.find('Raw acceleration vector:') != -1: - self.parse_raw_acceleration_x = self._get_following_number(line, 'x=') - self.parse_raw_acceleration_y = self._get_following_number(line, 'y=') - self.parse_raw_acceleration_z = self._get_following_number(line, 'z=') - self.parse_raw_acceleration_magnitude = self._get_following_number(line, 'magnitude=') - - if line.find('Filtered acceleration vector:') != -1: - self.parse_filtered_acceleration_x = self._get_following_number(line, 'x=') - self.parse_filtered_acceleration_y = self._get_following_number(line, 'y=') - self.parse_filtered_acceleration_z = self._get_following_number(line, 'z=') - self.parse_filtered_acceleration_magnitude = self._get_following_number(line, 'magnitude=') - - if line.find('tiltAngle=') != -1: - self.parse_tilt_angle = self._get_following_number(line, 'tiltAngle=') - - if line.find('orientationAngle=') != -1: - self.parse_orientation_angle = self._get_following_number(line, 'orientationAngle=') - - if line.find('Result:') != -1: - self.parse_current_rotation = self._get_following_number(line, 'currentRotation=') - self.parse_proposed_rotation = self._get_following_number(line, 'proposedRotation=') - self.parse_predicted_rotation = self._get_following_number(line, 'predictedRotation=') - self.parse_sample_latency = self._get_following_number(line, 'timeDeltaMS=') - self.parse_time_until_settled = self._get_following_number(line, 'timeUntilSettledMS=') - self.parse_time_until_flat_delay_expired = self._get_following_number(line, 'timeUntilFlatDelayExpiredMS=') - self.parse_time_until_swing_delay_expired = self._get_following_number(line, 'timeUntilSwingDelayExpiredMS=') - self.parse_time_until_acceleration_delay_expired = self._get_following_number(line, 'timeUntilAccelerationDelayExpiredMS=') - - self._append(self.raw_acceleration_x, timeindex, self.parse_raw_acceleration_x) - self._append(self.raw_acceleration_y, timeindex, self.parse_raw_acceleration_y) - self._append(self.raw_acceleration_z, timeindex, self.parse_raw_acceleration_z) - self._append(self.raw_acceleration_magnitude, timeindex, self.parse_raw_acceleration_magnitude) - self._append(self.filtered_acceleration_x, timeindex, self.parse_filtered_acceleration_x) - self._append(self.filtered_acceleration_y, timeindex, self.parse_filtered_acceleration_y) - self._append(self.filtered_acceleration_z, timeindex, self.parse_filtered_acceleration_z) - self._append(self.filtered_acceleration_magnitude, timeindex, self.parse_filtered_acceleration_magnitude) - self._append(self.tilt_angle, timeindex, self.parse_tilt_angle) - self._append(self.orientation_angle, timeindex, self.parse_orientation_angle) - self._append(self.current_rotation, timeindex, self.parse_current_rotation) - if self.parse_proposed_rotation >= 0: - self._append(self.proposed_rotation, timeindex, self.parse_proposed_rotation) - else: - self._append(self.proposed_rotation, timeindex, None) - if self.parse_predicted_rotation >= 0: - self._append(self.predicted_rotation, timeindex, self.parse_predicted_rotation) - else: - self._append(self.predicted_rotation, timeindex, None) - self._append(self.time_until_settled, timeindex, self.parse_time_until_settled) - self._append(self.time_until_flat_delay_expired, timeindex, self.parse_time_until_flat_delay_expired) - self._append(self.time_until_swing_delay_expired, timeindex, self.parse_time_until_swing_delay_expired) - self._append(self.time_until_acceleration_delay_expired, timeindex, self.parse_time_until_acceleration_delay_expired) - self._append(self.sample_latency, timeindex, self.parse_sample_latency) - self._reset_parse_state() - - # Scroll the plots. - if timeindex > timespan: - bottom = int(timeindex) - timespan + scrolljump - self.timebase += timedelta(seconds=bottom) - self._scroll(self.raw_acceleration_x, bottom) - self._scroll(self.raw_acceleration_y, bottom) - self._scroll(self.raw_acceleration_z, bottom) - self._scroll(self.raw_acceleration_magnitude, bottom) - self._scroll(self.filtered_acceleration_x, bottom) - self._scroll(self.filtered_acceleration_y, bottom) - self._scroll(self.filtered_acceleration_z, bottom) - self._scroll(self.filtered_acceleration_magnitude, bottom) - self._scroll(self.tilt_angle, bottom) - self._scroll(self.orientation_angle, bottom) - self._scroll(self.current_rotation, bottom) - self._scroll(self.proposed_rotation, bottom) - self._scroll(self.predicted_rotation, bottom) - self._scroll(self.time_until_settled, bottom) - self._scroll(self.time_until_flat_delay_expired, bottom) - self._scroll(self.time_until_swing_delay_expired, bottom) - self._scroll(self.time_until_acceleration_delay_expired, bottom) - self._scroll(self.sample_latency, bottom) - - # Redraw the plots. - self.raw_acceleration_line_x.set_data(self.raw_acceleration_x) - self.raw_acceleration_line_y.set_data(self.raw_acceleration_y) - self.raw_acceleration_line_z.set_data(self.raw_acceleration_z) - self.raw_acceleration_line_magnitude.set_data(self.raw_acceleration_magnitude) - self.filtered_acceleration_line_x.set_data(self.filtered_acceleration_x) - self.filtered_acceleration_line_y.set_data(self.filtered_acceleration_y) - self.filtered_acceleration_line_z.set_data(self.filtered_acceleration_z) - self.filtered_acceleration_line_magnitude.set_data(self.filtered_acceleration_magnitude) - self.tilt_angle_line.set_data(self.tilt_angle) - self.orientation_angle_line.set_data(self.orientation_angle) - self.current_rotation_line.set_data(self.current_rotation) - self.proposed_rotation_line.set_data(self.proposed_rotation) - self.predicted_rotation_line.set_data(self.predicted_rotation) - self.time_until_settled_line.set_data(self.time_until_settled) - self.time_until_flat_delay_expired_line.set_data(self.time_until_flat_delay_expired) - self.time_until_swing_delay_expired_line.set_data(self.time_until_swing_delay_expired) - self.time_until_acceleration_delay_expired_line.set_data(self.time_until_acceleration_delay_expired) - self.sample_latency_line.set_data(self.sample_latency) - - self.fig.canvas.draw_idle() - - # Scroll a time series. - def _scroll(self, timeseries, bottom): - bottom_index = bisect.bisect_left(timeseries[0], bottom) - del timeseries[0][:bottom_index] - del timeseries[1][:bottom_index] - for i, timeindex in enumerate(timeseries[0]): - timeseries[0][i] = timeindex - bottom - - # Extract a word following the specified prefix. - def _get_following_word(self, line, prefix): - prefix_index = line.find(prefix) - if prefix_index == -1: - return None - start_index = prefix_index + len(prefix) - delim_index = line.find(',', start_index) - if delim_index == -1: - return line[start_index:] - else: - return line[start_index:delim_index] - - # Extract a number following the specified prefix. - def _get_following_number(self, line, prefix): - word = self._get_following_word(line, prefix) - if word is None: - return None - return float(word) - - # Extract an array of numbers following the specified prefix. - def _get_following_array_of_numbers(self, line, prefix): - prefix_index = line.find(prefix + '[') - if prefix_index == -1: - return None - start_index = prefix_index + len(prefix) + 1 - delim_index = line.find(']', start_index) - if delim_index == -1: - return None - - result = [] - while start_index < delim_index: - comma_index = line.find(', ', start_index, delim_index) - if comma_index == -1: - result.append(float(line[start_index:delim_index])) - break; - result.append(float(line[start_index:comma_index])) - start_index = comma_index + 2 - return result - - # Add a value to a time series. - def _append(self, timeseries, timeindex, number): - timeseries[0].append(timeindex) - timeseries[1].append(number) - - # Parse the logcat timestamp. - # Timestamp has the form '01-21 20:42:42.930' - def _parse_timestamp(self, line): - return datetime.strptime(line[0:18], '%m-%d %H:%M:%S.%f') - -# Notice -print "Window Orientation Listener plotting tool" -print "-----------------------------------------\n" -print "Please turn on the Window Orientation Listener logging in Development Settings." - -# Start adb. -print "Starting adb logcat.\n" - -adb = subprocess.Popen(['adb', 'logcat', '-s', '-v', 'time', 'WindowOrientationListener:V'], - stdout=subprocess.PIPE) -adbout = NonBlockingStream(adb.stdout) - -# Prepare plotter. -plotter = Plotter(adbout) -plotter.update() - -# Main loop. -plot.show() diff --git a/tools/preload/20080522.compiled b/tools/preload/20080522.compiled Binary files differdeleted file mode 100644 index a2af422..0000000 --- a/tools/preload/20080522.compiled +++ /dev/null diff --git a/tools/preload/20090811.compiled b/tools/preload/20090811.compiled Binary files differdeleted file mode 100644 index 6dbeca0..0000000 --- a/tools/preload/20090811.compiled +++ /dev/null diff --git a/tools/preload/20100223.compiled b/tools/preload/20100223.compiled Binary files differdeleted file mode 100644 index 3056388..0000000 --- a/tools/preload/20100223.compiled +++ /dev/null diff --git a/tools/preload/Android.mk b/tools/preload/Android.mk deleted file mode 100644 index f325870..0000000 --- a/tools/preload/Android.mk +++ /dev/null @@ -1,23 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - Compile.java \ - LoadedClass.java \ - MemoryUsage.java \ - Operation.java \ - Policy.java \ - PrintCsv.java \ - PrintHtmlDiff.java \ - PrintPsTree.java \ - Proc.java \ - Record.java \ - Root.java \ - WritePreloadedClassFile.java - -LOCAL_MODULE:= preload - -include $(BUILD_HOST_JAVA_LIBRARY) - -include $(call all-subdir-makefiles) diff --git a/tools/preload/Compile.java b/tools/preload/Compile.java deleted file mode 100644 index 67258ef..0000000 --- a/tools/preload/Compile.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -/** - * Parses and analyzes a log, pulling our PRELOAD information. If you have - * an emulator or device running in the background, this class will use it - * to measure and record the memory usage of each class. - * - * TODO: Should analyze lines and select substring dynamically (instead of hardcoded 19) - */ -public class Compile { - - public static void main(String[] args) throws IOException { - if (args.length != 2) { - System.err.println("Usage: Compile [log file] [output file]"); - System.exit(0); - } - - Root root = new Root(); - - List<Record> records = new ArrayList<Record>(); - - BufferedReader in = new BufferedReader(new InputStreamReader( - new FileInputStream(args[0]))); - - String line; - int lineNumber = 0; - while ((line = in.readLine()) != null) { - lineNumber++; - if (line.startsWith("I/PRELOAD")) { - try { - String clipped = line.substring(19); - records.add(new Record(clipped, lineNumber)); - } catch (RuntimeException e) { - throw new RuntimeException( - "Exception while recording line " + lineNumber + ": " + line, e); - } - } - } - - for (Record record : records) { - root.indexProcess(record); - } - - for (Record record : records) { - root.indexClassOperation(record); - } - - in.close(); - - root.toFile(args[1]); - } -} diff --git a/tools/preload/LoadedClass.java b/tools/preload/LoadedClass.java deleted file mode 100644 index 86e5dfc..0000000 --- a/tools/preload/LoadedClass.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.Serializable; -import java.util.*; - -/** - * A loaded class. - */ -class LoadedClass implements Serializable, Comparable<LoadedClass> { - - private static final long serialVersionUID = 0; - - /** Class name. */ - final String name; - - /** Load operations. */ - final List<Operation> loads = new ArrayList<Operation>(); - - /** Static initialization operations. */ - final List<Operation> initializations = new ArrayList<Operation>(); - - /** Memory usage gathered by loading only this class in its own VM. */ - MemoryUsage memoryUsage = MemoryUsage.NOT_AVAILABLE; - - /** - * Whether or not this class was loaded in the system class loader. - */ - final boolean systemClass; - - /** Whether or not this class will be preloaded. */ - boolean preloaded; - - /** Constructs a new class. */ - LoadedClass(String name, boolean systemClass) { - this.name = name; - this.systemClass = systemClass; - } - - void measureMemoryUsage() { - this.memoryUsage = MemoryUsage.forClass(name); - } - - int mlt = -1; - - /** Median time to load this class. */ - int medianLoadTimeMicros() { - if (mlt != -1) { - return mlt; - } - - return mlt = calculateMedian(loads); - } - - int mit = -1; - - /** Median time to initialize this class. */ - int medianInitTimeMicros() { - if (mit != -1) { - return mit; - } - - return mit = calculateMedian(initializations); - } - - int medianTimeMicros() { - return medianInitTimeMicros() + medianLoadTimeMicros(); - } - - /** Calculates the median duration for a list of operations. */ - private static int calculateMedian(List<Operation> operations) { - int size = operations.size(); - if (size == 0) { - return 0; - } - - int[] times = new int[size]; - for (int i = 0; i < size; i++) { - times[i] = operations.get(i).exclusiveTimeMicros(); - } - - Arrays.sort(times); - int middle = size / 2; - if (size % 2 == 1) { - // Odd - return times[middle]; - } else { - // Even -- average the two. - return (times[middle - 1] + times[middle]) / 2; - } - } - - /** Returns names of processes that loaded this class. */ - Set<String> processNames() { - Set<String> names = new HashSet<String>(); - addProcessNames(loads, names); - addProcessNames(initializations, names); - return names; - } - - private void addProcessNames(List<Operation> ops, Set<String> names) { - for (Operation operation : ops) { - if (operation.process.fromZygote()) { - names.add(operation.process.name); - } - } - } - - public int compareTo(LoadedClass o) { - return name.compareTo(o.name); - } - - @Override - public String toString() { - return name; - } -} diff --git a/tools/preload/MemoryUsage.java b/tools/preload/MemoryUsage.java deleted file mode 100644 index d8f95f4..0000000 --- a/tools/preload/MemoryUsage.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.Serializable; -import java.io.IOException; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Memory usage information. - */ -class MemoryUsage implements Serializable { - - private static final long serialVersionUID = 0; - - static final MemoryUsage NOT_AVAILABLE = new MemoryUsage(); - - static int errorCount = 0; - - // These values are in 1kB increments (not 4kB like you'd expect). - final int nativeSharedPages; - final int javaSharedPages; - final int otherSharedPages; - final int nativePrivatePages; - final int javaPrivatePages; - final int otherPrivatePages; - - final int allocCount; - final int allocSize; - final int freedCount; - final int freedSize; - final long nativeHeapSize; - - public MemoryUsage(String line) { - String[] parsed = line.split(","); - - nativeSharedPages = Integer.parseInt(parsed[1]); - javaSharedPages = Integer.parseInt(parsed[2]); - otherSharedPages = Integer.parseInt(parsed[3]); - nativePrivatePages = Integer.parseInt(parsed[4]); - javaPrivatePages = Integer.parseInt(parsed[5]); - otherPrivatePages = Integer.parseInt(parsed[6]); - allocCount = Integer.parseInt(parsed[7]); - allocSize = Integer.parseInt(parsed[8]); - freedCount = Integer.parseInt(parsed[9]); - freedSize = Integer.parseInt(parsed[10]); - nativeHeapSize = Long.parseLong(parsed[11]); - } - - MemoryUsage() { - nativeSharedPages = -1; - javaSharedPages = -1; - otherSharedPages = -1; - nativePrivatePages = -1; - javaPrivatePages = -1; - otherPrivatePages = -1; - - allocCount = -1; - allocSize = -1; - freedCount = -1; - freedSize = -1; - nativeHeapSize = -1; - } - - MemoryUsage(int nativeSharedPages, - int javaSharedPages, - int otherSharedPages, - int nativePrivatePages, - int javaPrivatePages, - int otherPrivatePages, - int allocCount, - int allocSize, - int freedCount, - int freedSize, - long nativeHeapSize) { - this.nativeSharedPages = nativeSharedPages; - this.javaSharedPages = javaSharedPages; - this.otherSharedPages = otherSharedPages; - this.nativePrivatePages = nativePrivatePages; - this.javaPrivatePages = javaPrivatePages; - this.otherPrivatePages = otherPrivatePages; - this.allocCount = allocCount; - this.allocSize = allocSize; - this.freedCount = freedCount; - this.freedSize = freedSize; - this.nativeHeapSize = nativeHeapSize; - } - - MemoryUsage subtract(MemoryUsage baseline) { - return new MemoryUsage( - nativeSharedPages - baseline.nativeSharedPages, - javaSharedPages - baseline.javaSharedPages, - otherSharedPages - baseline.otherSharedPages, - nativePrivatePages - baseline.nativePrivatePages, - javaPrivatePages - baseline.javaPrivatePages, - otherPrivatePages - baseline.otherPrivatePages, - allocCount - baseline.allocCount, - allocSize - baseline.allocSize, - freedCount - baseline.freedCount, - freedSize - baseline.freedSize, - nativeHeapSize - baseline.nativeHeapSize); - } - - int javaHeapSize() { - return allocSize - freedSize; - } - - int totalHeap() { - return javaHeapSize() + (int) nativeHeapSize; - } - - int javaPagesInK() { - return javaSharedPages + javaPrivatePages; - } - - int nativePagesInK() { - return nativeSharedPages + nativePrivatePages; - } - int otherPagesInK() { - return otherSharedPages + otherPrivatePages; - } - - int totalPages() { - return javaSharedPages + javaPrivatePages + nativeSharedPages + - nativePrivatePages + otherSharedPages + otherPrivatePages; - } - - /** - * Was this information available? - */ - boolean isAvailable() { - return nativeSharedPages != -1; - } - - /** - * Measures baseline memory usage. - */ - static MemoryUsage baseline() { - return forClass(null); - } - - private static final String CLASS_PATH = "-Xbootclasspath" - + ":/system/framework/core.jar" - + ":/system/framework/ext.jar" - + ":/system/framework/framework.jar" - + ":/system/framework/framework-tests.jar" - + ":/system/framework/services.jar" - + ":/system/framework/loadclass.jar"; - - private static final String[] GET_DIRTY_PAGES = { - "adb", "shell", "dalvikvm", CLASS_PATH, "LoadClass" }; - - /** - * Measures memory usage for the given class. - */ - static MemoryUsage forClass(String className) { - MeasureWithTimeout measurer = new MeasureWithTimeout(className); - - new Thread(measurer).start(); - - synchronized (measurer) { - if (measurer.memoryUsage == null) { - // Wait up to 10s. - try { - measurer.wait(30000); - } catch (InterruptedException e) { - System.err.println("Interrupted waiting for measurement."); - e.printStackTrace(); - return NOT_AVAILABLE; - } - - // If it's still null. - if (measurer.memoryUsage == null) { - System.err.println("Timed out while measuring " - + className + "."); - return NOT_AVAILABLE; - } - } - - System.err.println("Got memory usage for " + className + "."); - return measurer.memoryUsage; - } - } - - static class MeasureWithTimeout implements Runnable { - - final String className; - MemoryUsage memoryUsage = null; - - MeasureWithTimeout(String className) { - this.className = className; - } - - public void run() { - MemoryUsage measured = measure(); - - synchronized (this) { - memoryUsage = measured; - notifyAll(); - } - } - - private MemoryUsage measure() { - String[] commands = GET_DIRTY_PAGES; - if (className != null) { - List<String> commandList = new ArrayList<String>( - GET_DIRTY_PAGES.length + 1); - commandList.addAll(Arrays.asList(commands)); - commandList.add(className); - commands = commandList.toArray(new String[commandList.size()]); - } - - try { - final Process process = Runtime.getRuntime().exec(commands); - - final InputStream err = process.getErrorStream(); - - // Send error output to stderr. - Thread errThread = new Thread() { - @Override - public void run() { - copy(err, System.err); - } - }; - errThread.setDaemon(true); - errThread.start(); - - BufferedReader in = new BufferedReader( - new InputStreamReader(process.getInputStream())); - String line = in.readLine(); - if (line == null || !line.startsWith("DECAFBAD,")) { - System.err.println("Got bad response for " + className - + ": " + line + "; command was " + Arrays.toString(commands)); - errorCount += 1; - return NOT_AVAILABLE; - } - - in.close(); - err.close(); - process.destroy(); - - return new MemoryUsage(line); - } catch (IOException e) { - System.err.println("Error getting stats for " - + className + "."); - e.printStackTrace(); - return NOT_AVAILABLE; - } - } - - } - - /** - * Copies from one stream to another. - */ - private static void copy(InputStream in, OutputStream out) { - byte[] buffer = new byte[1024]; - int read; - try { - while ((read = in.read(buffer)) > -1) { - out.write(buffer, 0, read); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** Measures memory usage information and stores it in the model. */ - public static void main(String[] args) throws IOException, - ClassNotFoundException { - Root root = Root.fromFile(args[0]); - root.baseline = baseline(); - for (LoadedClass loadedClass : root.loadedClasses.values()) { - if (loadedClass.systemClass) { - loadedClass.measureMemoryUsage(); - } - } - root.toFile(args[0]); - } -} diff --git a/tools/preload/Operation.java b/tools/preload/Operation.java deleted file mode 100644 index 4f1938e..0000000 --- a/tools/preload/Operation.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.util.List; -import java.util.ArrayList; -import java.io.Serializable; - -/** - * An operation with a duration. Could represent a class load or initialization. - */ -class Operation implements Serializable { - - private static final long serialVersionUID = 0; - - /** - * Type of operation. - */ - enum Type { - LOAD, INIT - } - - /** Process this operation occurred in. */ - final Proc process; - - /** Start time for this operation. */ - final long startTimeNanos; - - /** Index of this operation relative to its process. */ - final int index; - - /** Type of operation. */ - final Type type; - - /** End time for this operation. */ - long endTimeNanos = -1; - - /** The class that this operation loaded or initialized. */ - final LoadedClass loadedClass; - - /** Other operations that occurred during this one. */ - final List<Operation> subops = new ArrayList<Operation>(); - - /** Constructs a new operation. */ - Operation(Proc process, LoadedClass loadedClass, long startTimeNanos, - int index, Type type) { - this.process = process; - this.loadedClass = loadedClass; - this.startTimeNanos = startTimeNanos; - this.index = index; - this.type = type; - } - - /** - * Returns how long this class initialization and all the nested class - * initializations took. - */ - private long inclusiveTimeNanos() { - if (endTimeNanos == -1) { - throw new IllegalStateException("End time hasn't been set yet: " - + loadedClass.name); - } - - return endTimeNanos - startTimeNanos; - } - - /** - * Returns how long this class initialization took. - */ - int exclusiveTimeMicros() { - long exclusive = inclusiveTimeNanos(); - - for (Operation child : subops) { - exclusive -= child.inclusiveTimeNanos(); - } - - if (exclusive < 0) { - throw new AssertionError(loadedClass.name); - } - - return nanosToMicros(exclusive); - } - - /** Gets the median time that this operation took across all processes. */ - int medianExclusiveTimeMicros() { - switch (type) { - case LOAD: return loadedClass.medianLoadTimeMicros(); - case INIT: return loadedClass.medianInitTimeMicros(); - default: throw new AssertionError(); - } - } - - /** - * Converts nanoseconds to microseconds. - * - * @throws RuntimeException if overflow occurs - */ - private static int nanosToMicros(long nanos) { - long micros = nanos / 1000; - int microsInt = (int) micros; - if (microsInt != micros) { - throw new RuntimeException("Integer overflow: " + nanos); - } - return microsInt; - } - - /** - * Primarily for debugger support - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(type.toString()); - sb.append(' '); - sb.append(loadedClass.toString()); - if (subops.size() > 0) { - sb.append(" ("); - sb.append(subops.size()); - sb.append(" sub ops)"); - } - return sb.toString(); - } - -} diff --git a/tools/preload/Policy.java b/tools/preload/Policy.java deleted file mode 100644 index af46820..0000000 --- a/tools/preload/Policy.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * Policy that governs which classes are preloaded. - */ -public class Policy { - - /** - * No constructor - use static methods only - */ - private Policy() {} - - /** - * This location (in the build system) of the preloaded-classes file. - */ - static final String PRELOADED_CLASS_FILE - = "frameworks/base/preloaded-classes"; - - /** - * Long running services. These are restricted in their contribution to the - * preloader because their launch time is less critical. - */ - // TODO: Generate this automatically from package manager. - private static final Set<String> SERVICES = new HashSet<String>(Arrays.asList( - "system_server", - "com.google.process.content", - "android.process.media", - "com.android.bluetooth", - "com.android.calendar", - "com.android.inputmethod.latin", - "com.android.phone", - "com.google.android.apps.maps.FriendService", // pre froyo - "com.google.android.apps.maps:FriendService", // froyo - "com.google.android.apps.maps.LocationFriendService", - "com.google.android.deskclock", - "com.google.process.gapps", - "android.tts" - )); - - /** - * Classes which we shouldn't load from the Zygote. - */ - private static final Set<String> EXCLUDED_CLASSES - = new HashSet<String>(Arrays.asList( - // Binders - "android.app.AlarmManager", - "android.app.SearchManager", - "android.os.FileObserver", - "com.android.server.PackageManagerService$AppDirObserver", - - // Threads - "android.os.AsyncTask", - "android.pim.ContactsAsyncHelper", - "android.webkit.WebViewClassic$1", - "java.lang.ProcessManager" - )); - - /** - * Returns true if the given process name is a "long running" process or - * service. - */ - public static boolean isService(String processName) { - return SERVICES.contains(processName); - } - - /** Reports if the given class should be preloaded. */ - public static boolean isPreloadable(LoadedClass clazz) { - return clazz.systemClass && !EXCLUDED_CLASSES.contains(clazz.name) - && !clazz.name.endsWith("$NoPreloadHolder"); - } -} diff --git a/tools/preload/PrintCsv.java b/tools/preload/PrintCsv.java deleted file mode 100644 index 1820830..0000000 --- a/tools/preload/PrintCsv.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.IOException; -import java.io.FileInputStream; -import java.io.ObjectInputStream; -import java.io.BufferedInputStream; -import java.io.Writer; -import java.io.PrintStream; -import java.util.Set; -import java.util.HashSet; -import java.util.TreeSet; -import java.util.Iterator; - -/** - * Prints raw information in CSV format. - */ -public class PrintCsv { - - public static void main(String[] args) - throws IOException, ClassNotFoundException { - if (args.length != 1) { - System.err.println("Usage: PrintCsv [compiled log file]"); - System.exit(0); - } - - Root root = Root.fromFile(args[0]); - - printHeaders(System.out); - - MemoryUsage baseline = MemoryUsage.baseline(); - - for (LoadedClass loadedClass : root.loadedClasses.values()) { - if (!loadedClass.systemClass) { - continue; - } - - printRow(System.out, baseline, loadedClass); - } - } - - static void printHeaders(PrintStream out) { - out.println("Name" - + ",Preloaded" - + ",Median Load Time (us)" - + ",Median Init Time (us)" - + ",Process Names" - + ",Load Count" - + ",Init Count" - + ",Managed Heap (B)" - + ",Native Heap (B)" - + ",Managed Pages (kB)" - + ",Native Pages (kB)" - + ",Other Pages (kB)"); - } - - static void printRow(PrintStream out, MemoryUsage baseline, - LoadedClass loadedClass) { - out.print(loadedClass.name); - out.print(','); - out.print(loadedClass.preloaded); - out.print(','); - out.print(loadedClass.medianLoadTimeMicros()); - out.print(','); - out.print(loadedClass.medianInitTimeMicros()); - out.print(','); - out.print('"'); - - Set<String> procNames = new TreeSet<String>(); - for (Operation op : loadedClass.loads) - procNames.add(op.process.name); - for (Operation op : loadedClass.initializations) - procNames.add(op.process.name); - - if (procNames.size() <= 3) { - for (String name : procNames) { - out.print(name + "\n"); - } - } else { - Iterator<String> i = procNames.iterator(); - out.print(i.next() + "\n"); - out.print(i.next() + "\n"); - out.print("...and " + (procNames.size() - 2) - + " others."); - } - - out.print('"'); - out.print(','); - out.print(loadedClass.loads.size()); - out.print(','); - out.print(loadedClass.initializations.size()); - - if (loadedClass.memoryUsage.isAvailable()) { - MemoryUsage subtracted - = loadedClass.memoryUsage.subtract(baseline); - - out.print(','); - out.print(subtracted.javaHeapSize()); - out.print(','); - out.print(subtracted.nativeHeapSize); - out.print(','); - out.print(subtracted.javaPagesInK()); - out.print(','); - out.print(subtracted.nativePagesInK()); - out.print(','); - out.print(subtracted.otherPagesInK()); - - } else { - out.print(",n/a,n/a,n/a,n/a,n/a"); - } - - out.println(); - } -} diff --git a/tools/preload/PrintHtmlDiff.java b/tools/preload/PrintHtmlDiff.java deleted file mode 100644 index b101c85..0000000 --- a/tools/preload/PrintHtmlDiff.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -import java.io.IOException; -import java.io.FileReader; -import java.io.BufferedReader; -import java.io.PrintStream; -import java.util.Set; -import java.util.TreeSet; -import java.util.HashSet; -import java.util.Iterator; - -/** - * Prints HTML containing removed and added files. - */ -public class PrintHtmlDiff { - - private static final String OLD_PRELOADED_CLASSES - = "old-preloaded-classes"; - - public static void main(String[] args) throws IOException, - ClassNotFoundException { - Root root = Root.fromFile(args[0]); - - BufferedReader oldClasses = new BufferedReader( - new FileReader(OLD_PRELOADED_CLASSES)); - - // Classes loaded implicitly by the zygote. - Set<LoadedClass> zygote = new HashSet<LoadedClass>(); - for (Proc proc : root.processes.values()) { - if (proc.name.equals("zygote")) { - for (Operation op : proc.operations) { - zygote.add(op.loadedClass); - } - break; - } - } - - Set<LoadedClass> removed = new TreeSet<LoadedClass>(); - Set<LoadedClass> added = new TreeSet<LoadedClass>(); - - for (LoadedClass loadedClass : root.loadedClasses.values()) { - if (loadedClass.preloaded && !zygote.contains(loadedClass)) { - added.add(loadedClass); - } - } - - String line; - while ((line = oldClasses.readLine()) != null) { - line = line.trim(); - LoadedClass clazz = root.loadedClasses.get(line); - if (clazz != null) { - added.remove(clazz); - if (!clazz.preloaded) removed.add(clazz); - } - } - - PrintStream out = System.out; - - out.println("<html><body>"); - out.println("<style>"); - out.println("a, th, td, h2 { font-family: arial }"); - out.println("th, td { font-size: small }"); - out.println("</style>"); - out.println("<script src=\"sorttable.js\"></script>"); - out.println("<p><a href=\"#removed\">Removed</a>"); - out.println("<a name=\"added\"/><h2>Added</h2>"); - printTable(out, root.baseline, added); - out.println("<a name=\"removed\"/><h2>Removed</h2>"); - printTable(out, root.baseline, removed); - out.println("</body></html>"); - } - - static void printTable(PrintStream out, MemoryUsage baseline, - Iterable<LoadedClass> classes) { - out.println("<table border=\"1\" cellpadding=\"5\"" - + " class=\"sortable\">"); - - out.println("<thead><tr>"); - out.println("<th>Name</th>"); - out.println("<th>Load Time (us)</th>"); - out.println("<th>Loaded By</th>"); - out.println("<th>Heap (B)</th>"); - out.println("<th>Pages</th>"); - out.println("</tr></thead>"); - - for (LoadedClass clazz : classes) { - out.println("<tr>"); - out.println("<td>" + clazz.name + "</td>"); - out.println("<td>" + clazz.medianTimeMicros() + "</td>"); - - out.println("<td>"); - Set<String> procNames = new TreeSet<String>(); - for (Operation op : clazz.loads) procNames.add(op.process.name); - for (Operation op : clazz.initializations) { - procNames.add(op.process.name); - } - if (procNames.size() <= 3) { - for (String name : procNames) { - out.print(name + "<br/>"); - } - } else { - Iterator<String> i = procNames.iterator(); - out.print(i.next() + "<br/>"); - out.print(i.next() + "<br/>"); - out.print("...and " + (procNames.size() - 2) - + " others."); - } - out.println("</td>"); - - if (clazz.memoryUsage.isAvailable()) { - MemoryUsage subtracted - = clazz.memoryUsage.subtract(baseline); - - out.println("<td>" + (subtracted.javaHeapSize() - + subtracted.nativeHeapSize) + "</td>"); - out.println("<td>" + subtracted.totalPages() + "</td>"); - } else { - for (int i = 0; i < 2; i++) { - out.println("<td>n/a</td>"); - } - } - - out.println("</tr>"); - } - - out.println("</table>"); - } -} diff --git a/tools/preload/PrintPsTree.java b/tools/preload/PrintPsTree.java deleted file mode 100644 index 22701fa..0000000 --- a/tools/preload/PrintPsTree.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.IOException; -import java.io.FileInputStream; -import java.io.ObjectInputStream; -import java.io.BufferedInputStream; - -/** - * Prints raw information in CSV format. - */ -public class PrintPsTree { - - public static void main(String[] args) - throws IOException, ClassNotFoundException { - if (args.length != 1) { - System.err.println("Usage: PrintCsv [compiled log file]"); - System.exit(0); - } - - FileInputStream fin = new FileInputStream(args[0]); - ObjectInputStream oin = new ObjectInputStream( - new BufferedInputStream(fin)); - - Root root = (Root) oin.readObject(); - - for (Proc proc : root.processes.values()) { - if (proc.parent == null) { - proc.print(); - } - } - } -} diff --git a/tools/preload/Proc.java b/tools/preload/Proc.java deleted file mode 100644 index 2105021..0000000 --- a/tools/preload/Proc.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.util.List; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Map; -import java.util.HashMap; -import java.io.Serializable; - -/** - * A Dalvik process. - */ -class Proc implements Serializable { - - private static final long serialVersionUID = 0; - - /** Parent process. */ - final Proc parent; - - /** Process ID. */ - final int id; - - /** - * Name of this process. We may not have the correct name at first, i.e. - * some classes could have been loaded before the process name was set. - */ - String name; - - /** Child processes. */ - final List<Proc> children = new ArrayList<Proc>(); - - /** Maps thread ID to operation stack. */ - transient final Map<Integer, LinkedList<Operation>> stacks - = new HashMap<Integer, LinkedList<Operation>>(); - - /** Number of operations. */ - int operationCount; - - /** Sequential list of operations that happened in this process. */ - final List<Operation> operations = new ArrayList<Operation>(); - - /** List of past process names. */ - final List<String> nameHistory = new ArrayList<String>(); - - /** Constructs a new process. */ - Proc(Proc parent, int id) { - this.parent = parent; - this.id = id; - } - - /** Sets name of this process. */ - void setName(String name) { - if (!name.equals(this.name)) { - if (this.name != null) { - nameHistory.add(this.name); - } - this.name = name; - } - } - - /** - * Returns true if this process comes from the zygote. - */ - public boolean fromZygote() { - return parent != null && parent.name.equals("zygote") - && !name.equals("com.android.development"); - } - - /** - * Starts an operation. - * - * @param threadId thread the operation started in - * @param loadedClass class operation happened to - * @param time the operation started - */ - void startOperation(int threadId, LoadedClass loadedClass, long time, - Operation.Type type) { - Operation o = new Operation( - this, loadedClass, time, operationCount++, type); - operations.add(o); - - LinkedList<Operation> stack = stacks.get(threadId); - if (stack == null) { - stack = new LinkedList<Operation>(); - stacks.put(threadId, stack); - } - - if (!stack.isEmpty()) { - stack.getLast().subops.add(o); - } - - stack.add(o); - } - - /** - * Ends an operation. - * - * @param threadId thread the operation ended in - * @param loadedClass class operation happened to - * @param time the operation ended - */ - Operation endOperation(int threadId, String className, - LoadedClass loadedClass, long time) { - LinkedList<Operation> stack = stacks.get(threadId); - - if (stack == null || stack.isEmpty()) { - didNotStart(className); - return null; - } - - Operation o = stack.getLast(); - if (loadedClass != o.loadedClass) { - didNotStart(className); - return null; - } - - stack.removeLast(); - - o.endTimeNanos = time; - return o; - } - - /** - * Prints an error indicating that we saw the end of an operation but not - * the start. A bug in the logging framework which results in dropped logs - * causes this. - */ - private static void didNotStart(String name) { - System.err.println("Warning: An operation ended on " + name - + " but it never started!"); - } - - /** - * Prints this process tree to stdout. - */ - void print() { - print(""); - } - - /** - * Prints a child proc to standard out. - */ - private void print(String prefix) { - System.out.println(prefix + "id=" + id + ", name=" + name); - for (Proc child : children) { - child.print(prefix + " "); - } - } - - @Override - public String toString() { - return this.name; - } -} diff --git a/tools/preload/Record.java b/tools/preload/Record.java deleted file mode 100644 index d0a2af4..0000000 --- a/tools/preload/Record.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -/** - * One line from the loaded-classes file. - */ -class Record { - - /** - * The delimiter character we use, {@code :}, conflicts with some other - * names. In that case, manually replace the delimiter with something else. - */ - private static final String[] REPLACE_CLASSES = { - "com.google.android.apps.maps:FriendService", - "com.google.android.apps.maps\\u003AFriendService", - "com.google.android.apps.maps:driveabout", - "com.google.android.apps.maps\\u003Adriveabout", - "com.google.android.apps.maps:GoogleLocationService", - "com.google.android.apps.maps\\u003AGoogleLocationService", - "com.google.android.apps.maps:LocationFriendService", - "com.google.android.apps.maps\\u003ALocationFriendService", - "com.google.android.apps.maps:MapsBackgroundService", - "com.google.android.apps.maps\\u003AMapsBackgroundService", - "com.google.android.apps.maps:NetworkLocationService", - "com.google.android.apps.maps\\u003ANetworkLocationService", - "com.android.chrome:sandboxed_process", - "com.android.chrome\\u003Asandboxed_process", - "com.android.fakeoemfeatures:background", - "com.android.fakeoemfeatures\\u003Abackground", - "com.android.fakeoemfeatures:core", - "com.android.fakeoemfeatures\\u003Acore", - "com.android.launcher:wallpaper_chooser", - "com.android.launcher\\u003Awallpaper_chooser", - "com.android.nfc:handover", - "com.android.nfc\\u003Ahandover", - "com.google.android.music:main", - "com.google.android.music\\u003Amain", - "com.google.android.music:ui", - "com.google.android.music\\u003Aui", - "com.google.android.setupwarlock:broker", - "com.google.android.setupwarlock\\u003Abroker", - "mobi.mgeek.TunnyBrowser:DolphinNotification", - "mobi.mgeek.TunnyBrowser\\u003ADolphinNotification", - "com.qo.android.sp.oem:Quickword", - "com.qo.android.sp.oem\\u003AQuickword", - "android:ui", - "android\\u003Aui", - "system:ui", - "system\\u003Aui", - }; - - enum Type { - /** Start of initialization. */ - START_LOAD, - - /** End of initialization. */ - END_LOAD, - - /** Start of initialization. */ - START_INIT, - - /** End of initialization. */ - END_INIT - } - - /** Parent process ID. */ - final int ppid; - - /** Process ID. */ - final int pid; - - /** Thread ID. */ - final int tid; - - /** Process name. */ - final String processName; - - /** Class loader pointer. */ - final int classLoader; - - /** Type of record. */ - final Type type; - - /** Name of loaded class. */ - final String className; - - /** Record time (ns). */ - final long time; - - /** Source file line# */ - int sourceLineNumber; - - /** - * Parses a line from the loaded-classes file. - */ - Record(String line, int lineNum) { - char typeChar = line.charAt(0); - switch (typeChar) { - case '>': type = Type.START_LOAD; break; - case '<': type = Type.END_LOAD; break; - case '+': type = Type.START_INIT; break; - case '-': type = Type.END_INIT; break; - default: throw new AssertionError("Bad line: " + line); - } - - sourceLineNumber = lineNum; - - for (int i = 0; i < REPLACE_CLASSES.length; i+= 2) { - line = line.replace(REPLACE_CLASSES[i], REPLACE_CLASSES[i+1]); - } - - line = line.substring(1); - String[] parts = line.split(":"); - - ppid = Integer.parseInt(parts[0]); - pid = Integer.parseInt(parts[1]); - tid = Integer.parseInt(parts[2]); - - processName = decode(parts[3]).intern(); - - classLoader = Integer.parseInt(parts[4]); - className = vmTypeToLanguage(decode(parts[5])).intern(); - - time = Long.parseLong(parts[6]); - } - - /** - * Decode any escaping that may have been written to the log line. - * - * Supports unicode-style escaping: \\uXXXX = character in hex - * - * @param rawField the field as it was written into the log - * @result the same field with any escaped characters replaced - */ - String decode(String rawField) { - String result = rawField; - int offset = result.indexOf("\\u"); - while (offset >= 0) { - String before = result.substring(0, offset); - String escaped = result.substring(offset+2, offset+6); - String after = result.substring(offset+6); - - result = String.format("%s%c%s", before, Integer.parseInt(escaped, 16), after); - - // find another but don't recurse - offset = result.indexOf("\\u", offset + 1); - } - return result; - } - - /** - * Converts a VM-style name to a language-style name. - */ - String vmTypeToLanguage(String typeName) { - // if the typename is (null), just return it as-is. This is probably in dexopt and - // will be discarded anyway. NOTE: This corresponds to the case in dalvik/vm/oo/Class.c - // where dvmLinkClass() returns false and we clean up and exit. - if ("(null)".equals(typeName)) { - return typeName; - } - - if (!typeName.startsWith("L") || !typeName.endsWith(";") ) { - throw new AssertionError("Bad name: " + typeName + " in line " + sourceLineNumber); - } - - typeName = typeName.substring(1, typeName.length() - 1); - return typeName.replace("/", "."); - } -} diff --git a/tools/preload/Root.java b/tools/preload/Root.java deleted file mode 100644 index 0bc29bf..0000000 --- a/tools/preload/Root.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.Serializable; -import java.io.IOException; -import java.io.Writer; -import java.io.BufferedWriter; -import java.io.OutputStreamWriter; -import java.io.FileOutputStream; -import java.io.FileInputStream; -import java.io.ObjectInputStream; -import java.io.BufferedInputStream; -import java.io.ObjectOutputStream; -import java.io.BufferedOutputStream; -import java.util.Map; -import java.util.HashMap; -import java.util.Set; -import java.util.TreeSet; -import java.util.Arrays; -import java.nio.charset.Charset; - -/** - * Root of our data model. - */ -public class Root implements Serializable { - - private static final long serialVersionUID = 0; - - /** pid -> Proc */ - final Map<Integer, Proc> processes = new HashMap<Integer, Proc>(); - - /** Class name -> LoadedClass */ - final Map<String, LoadedClass> loadedClasses - = new HashMap<String, LoadedClass>(); - - MemoryUsage baseline = MemoryUsage.baseline(); - - /** - * Records class loads and initializations. - */ - void indexClassOperation(Record record) { - Proc process = processes.get(record.pid); - - // Ignore dexopt output. It loads applications classes through the - // system class loader and messes us up. - if (record.processName.equals("dexopt")) { - return; - } - - String name = record.className; - LoadedClass loadedClass = loadedClasses.get(name); - Operation o = null; - - switch (record.type) { - case START_LOAD: - case START_INIT: - if (loadedClass == null) { - loadedClass = new LoadedClass( - name, record.classLoader == 0); - if (loadedClass.systemClass) { - // Only measure memory for classes in the boot - // classpath. - loadedClass.measureMemoryUsage(); - } - loadedClasses.put(name, loadedClass); - } - break; - - case END_LOAD: - case END_INIT: - o = process.endOperation(record.tid, record.className, - loadedClass, record.time); - if (o == null) { - return; - } - } - - switch (record.type) { - case START_LOAD: - process.startOperation(record.tid, loadedClass, record.time, - Operation.Type.LOAD); - break; - - case START_INIT: - process.startOperation(record.tid, loadedClass, record.time, - Operation.Type.INIT); - break; - - case END_LOAD: - loadedClass.loads.add(o); - break; - - case END_INIT: - loadedClass.initializations.add(o); - break; - } - } - - /** - * Indexes information about the process from the given record. - */ - void indexProcess(Record record) { - Proc proc = processes.get(record.pid); - - if (proc == null) { - // Create a new process object. - Proc parent = processes.get(record.ppid); - proc = new Proc(parent, record.pid); - processes.put(proc.id, proc); - if (parent != null) { - parent.children.add(proc); - } - } - - proc.setName(record.processName); - } - - /** - * Writes this graph to a file. - */ - void toFile(String fileName) throws IOException { - FileOutputStream out = new FileOutputStream(fileName); - ObjectOutputStream oout = new ObjectOutputStream( - new BufferedOutputStream(out)); - - System.err.println("Writing object model..."); - - oout.writeObject(this); - - oout.close(); - - System.err.println("Done!"); - } - - /** - * Reads Root from a file. - */ - static Root fromFile(String fileName) - throws IOException, ClassNotFoundException { - FileInputStream fin = new FileInputStream(fileName); - ObjectInputStream oin = new ObjectInputStream( - new BufferedInputStream(fin)); - - Root root = (Root) oin.readObject(); - - oin.close(); - - return root; - } -} diff --git a/tools/preload/WritePreloadedClassFile.java b/tools/preload/WritePreloadedClassFile.java deleted file mode 100644 index b067bc2..0000000 --- a/tools/preload/WritePreloadedClassFile.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import java.io.BufferedWriter; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.nio.charset.Charset; -import java.util.Set; -import java.util.TreeSet; - -/** - * Writes /frameworks/base/preloaded-classes. Also updates - * {@link LoadedClass#preloaded} fields and writes over compiled log file. - */ -public class WritePreloadedClassFile { - - /** - * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us. - */ - static final int MIN_LOAD_TIME_MICROS = 1250; - - /** - * Preload any class that was loaded by at least MIN_PROCESSES processes. - */ - static final int MIN_PROCESSES = 10; - - public static void main(String[] args) throws IOException, - ClassNotFoundException { - if (args.length != 1) { - System.err.println("Usage: WritePreloadedClassFile [compiled log]"); - System.exit(-1); - } - String rootFile = args[0]; - Root root = Root.fromFile(rootFile); - - // No classes are preloaded to start. - for (LoadedClass loadedClass : root.loadedClasses.values()) { - loadedClass.preloaded = false; - } - - // Open preloaded-classes file for output. - Writer out = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(Policy.PRELOADED_CLASS_FILE), - Charset.forName("US-ASCII"))); - - out.write("# Classes which are preloaded by" - + " com.android.internal.os.ZygoteInit.\n"); - out.write("# Automatically generated by frameworks/base/tools/preload/" - + WritePreloadedClassFile.class.getSimpleName() + ".java.\n"); - out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n"); - out.write("# MIN_PROCESSES=" + MIN_PROCESSES + "\n"); - - /* - * The set of classes to preload. We preload a class if: - * - * a) it's loaded in the bootclasspath (i.e., is a system class) - * b) it takes > MIN_LOAD_TIME_MICROS us to load, and - * c) it's loaded by more than one process, or it's loaded by an - * application (i.e., not a long running service) - */ - Set<LoadedClass> toPreload = new TreeSet<LoadedClass>(); - - // Preload classes that were loaded by at least 2 processes. Hopefully, - // the memory associated with these classes will be shared. - for (LoadedClass loadedClass : root.loadedClasses.values()) { - Set<String> names = loadedClass.processNames(); - if (!Policy.isPreloadable(loadedClass)) { - continue; - } - - if (names.size() >= MIN_PROCESSES || - (loadedClass.medianTimeMicros() > MIN_LOAD_TIME_MICROS && names.size() > 1)) { - toPreload.add(loadedClass); - } - } - - int initialSize = toPreload.size(); - System.out.println(initialSize - + " classses were loaded by more than one app."); - - // Preload eligable classes from applications (not long-running - // services). - for (Proc proc : root.processes.values()) { - if (proc.fromZygote() && !Policy.isService(proc.name)) { - for (Operation operation : proc.operations) { - LoadedClass loadedClass = operation.loadedClass; - if (shouldPreload(loadedClass)) { - toPreload.add(loadedClass); - } - } - } - } - - System.out.println("Added " + (toPreload.size() - initialSize) - + " more to speed up applications."); - - System.out.println(toPreload.size() - + " total classes will be preloaded."); - - // Make classes that were implicitly loaded by the zygote explicit. - // This adds minimal overhead but avoid confusion about classes not - // appearing in the list. - addAllClassesFrom("zygote", root, toPreload); - - for (LoadedClass loadedClass : toPreload) { - out.write(loadedClass.name + "\n"); - } - - out.close(); - - // Update data to reflect LoadedClass.preloaded changes. - for (LoadedClass loadedClass : toPreload) { - loadedClass.preloaded = true; - } - root.toFile(rootFile); - } - - private static void addAllClassesFrom(String processName, Root root, - Set<LoadedClass> toPreload) { - for (Proc proc : root.processes.values()) { - if (proc.name.equals(processName)) { - for (Operation operation : proc.operations) { - boolean preloadable - = Policy.isPreloadable(operation.loadedClass); - if (preloadable) { - toPreload.add(operation.loadedClass); - } - } - } - } - } - - /** - * Returns true if the class should be preloaded. - */ - private static boolean shouldPreload(LoadedClass clazz) { - return Policy.isPreloadable(clazz) - && clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS; - } -} diff --git a/tools/preload/loadclass/Android.mk b/tools/preload/loadclass/Android.mk deleted file mode 100644 index 65828be..0000000 --- a/tools/preload/loadclass/Android.mk +++ /dev/null @@ -1,9 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_MODULE_TAGS := tests - -LOCAL_MODULE := loadclass - -include $(BUILD_JAVA_LIBRARY) diff --git a/tools/preload/loadclass/LoadClass.java b/tools/preload/loadclass/LoadClass.java deleted file mode 100644 index a71b6a8..0000000 --- a/tools/preload/loadclass/LoadClass.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -import android.util.Log; -import android.os.Debug; - -/** - * Loads a class, runs the garbage collector, and prints showmap output. - * - * <p>Usage: dalvikvm LoadClass [class name] - */ -class LoadClass { - - public static void main(String[] args) { - System.loadLibrary("android_runtime"); - - if (registerNatives() < 0) { - throw new RuntimeException("Error registering natives."); - } - - Debug.startAllocCounting(); - - if (args.length > 0) { - try { - long start = System.currentTimeMillis(); - Class.forName(args[0]); - long elapsed = System.currentTimeMillis() - start; - Log.i("LoadClass", "Loaded " + args[0] + " in " + elapsed - + "ms."); - } catch (ClassNotFoundException e) { - Log.w("LoadClass", e); - return; - } - } - - System.gc(); - - int allocCount = Debug.getGlobalAllocCount(); - int allocSize = Debug.getGlobalAllocSize(); - int freedCount = Debug.getGlobalFreedCount(); - int freedSize = Debug.getGlobalFreedSize(); - long nativeHeapSize = Debug.getNativeHeapSize(); - - Debug.stopAllocCounting(); - - StringBuilder response = new StringBuilder("DECAFBAD"); - - int[] pages = new int[6]; - Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); - Debug.getMemoryInfo(memoryInfo); - response.append(',').append(memoryInfo.nativeSharedDirty); - response.append(',').append(memoryInfo.dalvikSharedDirty); - response.append(',').append(memoryInfo.otherSharedDirty); - response.append(',').append(memoryInfo.nativePrivateDirty); - response.append(',').append(memoryInfo.dalvikPrivateDirty); - response.append(',').append(memoryInfo.otherPrivateDirty); - - response.append(',').append(allocCount); - response.append(',').append(allocSize); - response.append(',').append(freedCount); - response.append(',').append(freedSize); - response.append(',').append(nativeHeapSize); - - System.out.println(response.toString()); - } - - /** - * Registers native functions. See AndroidRuntime.cpp. - */ - static native int registerNatives(); -} diff --git a/tools/preload/preload.iml b/tools/preload/preload.iml deleted file mode 100644 index 2d87c55..0000000 --- a/tools/preload/preload.iml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module relativePaths="true" type="JAVA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="false"> - <output url="file:///tmp/preload" /> - <output-test url="file:///tmp/preload" /> - <exclude-output /> - <content url="file://$MODULE_DIR$"> - <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> - diff --git a/tools/preload/preload.ipr b/tools/preload/preload.ipr deleted file mode 100644 index 0c9621c..0000000 --- a/tools/preload/preload.ipr +++ /dev/null @@ -1,495 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project relativePaths="false" version="4"> - <component name="AntConfiguration"> - <defaultAnt bundledAnt="true" /> - </component> - <component name="BuildJarProjectSettings"> - <option name="BUILD_JARS_ON_MAKE" value="false" /> - </component> - <component name="ChangeBrowserSettings"> - <option name="MAIN_SPLITTER_PROPORTION" value="0.3" /> - <option name="MESSAGES_SPLITTER_PROPORTION" value="0.8" /> - <option name="USE_DATE_BEFORE_FILTER" value="false" /> - <option name="USE_DATE_AFTER_FILTER" value="false" /> - <option name="USE_CHANGE_BEFORE_FILTER" value="false" /> - <option name="USE_CHANGE_AFTER_FILTER" value="false" /> - <option name="DATE_BEFORE" value="" /> - <option name="DATE_AFTER" value="" /> - <option name="CHANGE_BEFORE" value="" /> - <option name="CHANGE_AFTER" value="" /> - <option name="USE_USER_FILTER" value="false" /> - <option name="USER" value="" /> - </component> - <component name="CodeStyleProjectProfileManger"> - <option name="PROJECT_PROFILE" /> - <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" /> - </component> - <component name="CodeStyleSettingsManager"> - <option name="PER_PROJECT_SETTINGS"> - <value> - <ADDITIONAL_INDENT_OPTIONS fileType="java"> - <option name="INDENT_SIZE" value="4" /> - <option name="CONTINUATION_INDENT_SIZE" value="8" /> - <option name="TAB_SIZE" value="4" /> - <option name="USE_TAB_CHARACTER" value="false" /> - <option name="SMART_TABS" value="false" /> - <option name="LABEL_INDENT_SIZE" value="0" /> - <option name="LABEL_INDENT_ABSOLUTE" value="false" /> - </ADDITIONAL_INDENT_OPTIONS> - <ADDITIONAL_INDENT_OPTIONS fileType="xml"> - <option name="INDENT_SIZE" value="4" /> - <option name="CONTINUATION_INDENT_SIZE" value="8" /> - <option name="TAB_SIZE" value="4" /> - <option name="USE_TAB_CHARACTER" value="false" /> - <option name="SMART_TABS" value="false" /> - <option name="LABEL_INDENT_SIZE" value="0" /> - <option name="LABEL_INDENT_ABSOLUTE" value="false" /> - </ADDITIONAL_INDENT_OPTIONS> - </value> - </option> - <option name="USE_PER_PROJECT_SETTINGS" value="false" /> - </component> - <component name="CompilerConfiguration"> - <option name="DEFAULT_COMPILER" value="Javac" /> - <option name="DEPLOY_AFTER_MAKE" value="0" /> - <resourceExtensions> - <entry name=".+\.(properties|xml|html|dtd|tld)" /> - <entry name=".+\.(gif|png|jpeg|jpg)" /> - </resourceExtensions> - <wildcardResourcePatterns> - <entry name="?*.properties" /> - <entry name="?*.xml" /> - <entry name="?*.gif" /> - <entry name="?*.png" /> - <entry name="?*.jpeg" /> - <entry name="?*.jpg" /> - <entry name="?*.html" /> - <entry name="?*.dtd" /> - <entry name="?*.tld" /> - </wildcardResourcePatterns> - </component> - <component name="Cvs2Configuration"> - <option name="PRUNE_EMPTY_DIRECTORIES" value="true" /> - <option name="MERGING_MODE" value="0" /> - <option name="MERGE_WITH_BRANCH1_NAME" value="HEAD" /> - <option name="MERGE_WITH_BRANCH2_NAME" value="HEAD" /> - <option name="RESET_STICKY" value="false" /> - <option name="CREATE_NEW_DIRECTORIES" value="true" /> - <option name="DEFAULT_TEXT_FILE_SUBSTITUTION" value="kv" /> - <option name="PROCESS_UNKNOWN_FILES" value="false" /> - <option name="PROCESS_DELETED_FILES" value="false" /> - <option name="PROCESS_IGNORED_FILES" value="false" /> - <option name="RESERVED_EDIT" value="false" /> - <option name="CHECKOUT_DATE_OR_REVISION_SETTINGS"> - <value> - <option name="BRANCH" value="" /> - <option name="DATE" value="" /> - <option name="USE_BRANCH" value="false" /> - <option name="USE_DATE" value="false" /> - </value> - </option> - <option name="UPDATE_DATE_OR_REVISION_SETTINGS"> - <value> - <option name="BRANCH" value="" /> - <option name="DATE" value="" /> - <option name="USE_BRANCH" value="false" /> - <option name="USE_DATE" value="false" /> - </value> - </option> - <option name="SHOW_CHANGES_REVISION_SETTINGS"> - <value> - <option name="BRANCH" value="" /> - <option name="DATE" value="" /> - <option name="USE_BRANCH" value="false" /> - <option name="USE_DATE" value="false" /> - </value> - </option> - <option name="SHOW_OUTPUT" value="false" /> - <option name="ADD_WATCH_INDEX" value="0" /> - <option name="REMOVE_WATCH_INDEX" value="0" /> - <option name="UPDATE_KEYWORD_SUBSTITUTION" /> - <option name="MAKE_NEW_FILES_READONLY" value="false" /> - <option name="SHOW_CORRUPTED_PROJECT_FILES" value="0" /> - <option name="TAG_AFTER_PROJECT_COMMIT" value="false" /> - <option name="OVERRIDE_EXISTING_TAG_FOR_PROJECT" value="true" /> - <option name="TAG_AFTER_PROJECT_COMMIT_NAME" value="" /> - <option name="CLEAN_COPY" value="false" /> - </component> - <component name="DependenciesAnalyzeManager"> - <option name="myForwardDirection" value="false" /> - </component> - <component name="DependencyValidationManager"> - <option name="SKIP_IMPORT_STATEMENTS" value="false" /> - </component> - <component name="EclipseCompilerSettings"> - <option name="DEBUGGING_INFO" value="true" /> - <option name="GENERATE_NO_WARNINGS" value="true" /> - <option name="DEPRECATION" value="false" /> - <option name="ADDITIONAL_OPTIONS_STRING" value="" /> - <option name="MAXIMUM_HEAP_SIZE" value="128" /> - </component> - <component name="EclipseEmbeddedCompilerSettings"> - <option name="DEBUGGING_INFO" value="true" /> - <option name="GENERATE_NO_WARNINGS" value="true" /> - <option name="DEPRECATION" value="false" /> - <option name="ADDITIONAL_OPTIONS_STRING" value="" /> - <option name="MAXIMUM_HEAP_SIZE" value="128" /> - </component> - <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> - <component name="EntryPointsManager"> - <entry_points version="2.0" /> - </component> - <component name="ExportToHTMLSettings"> - <option name="PRINT_LINE_NUMBERS" value="false" /> - <option name="OPEN_IN_BROWSER" value="false" /> - <option name="OUTPUT_DIRECTORY" /> - </component> - <component name="IdProvider" IDEtalkID="D171F99B9178C1675593DC9A76A5CC7E" /> - <component name="InspectionProjectProfileManager"> - <option name="PROJECT_PROFILE" value="Project Default" /> - <option name="USE_PROJECT_PROFILE" value="true" /> - <version value="1.0" /> - <profiles> - <profile version="1.0" is_locked="false"> - <option name="myName" value="Project Default" /> - <option name="myLocal" value="false" /> - <inspection_tool class="JavaDoc" enabled="false" level="WARNING" enabled_by_default="false"> - <option name="TOP_LEVEL_CLASS_OPTIONS"> - <value> - <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> - <option name="REQUIRED_TAGS" value="" /> - </value> - </option> - <option name="INNER_CLASS_OPTIONS"> - <value> - <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> - <option name="REQUIRED_TAGS" value="" /> - </value> - </option> - <option name="METHOD_OPTIONS"> - <value> - <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> - <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" /> - </value> - </option> - <option name="FIELD_OPTIONS"> - <value> - <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> - <option name="REQUIRED_TAGS" value="" /> - </value> - </option> - <option name="IGNORE_DEPRECATED" value="false" /> - <option name="IGNORE_JAVADOC_PERIOD" value="true" /> - <option name="myAdditionalJavadocTags" value="" /> - </inspection_tool> - <inspection_tool class="JavaLangImport" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="OnDemandImport" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="RedundantImport" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="SamePackageImport" enabled="true" level="WARNING" enabled_by_default="true" /> - <inspection_tool class="UnusedImport" enabled="true" level="WARNING" enabled_by_default="true" /> - </profile> - </profiles> - <list size="4"> - <item index="0" class="java.lang.String" itemvalue="WARNING" /> - <item index="1" class="java.lang.String" itemvalue="SERVER PROBLEM" /> - <item index="2" class="java.lang.String" itemvalue="INFO" /> - <item index="3" class="java.lang.String" itemvalue="ERROR" /> - </list> - </component> - <component name="JavacSettings"> - <option name="DEBUGGING_INFO" value="true" /> - <option name="GENERATE_NO_WARNINGS" value="false" /> - <option name="DEPRECATION" value="true" /> - <option name="ADDITIONAL_OPTIONS_STRING" value="" /> - <option name="MAXIMUM_HEAP_SIZE" value="128" /> - </component> - <component name="JavadocGenerationManager"> - <option name="OUTPUT_DIRECTORY" /> - <option name="OPTION_SCOPE" value="protected" /> - <option name="OPTION_HIERARCHY" value="true" /> - <option name="OPTION_NAVIGATOR" value="true" /> - <option name="OPTION_INDEX" value="true" /> - <option name="OPTION_SEPARATE_INDEX" value="true" /> - <option name="OPTION_DOCUMENT_TAG_USE" value="false" /> - <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" /> - <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" /> - <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" /> - <option name="OPTION_DEPRECATED_LIST" value="true" /> - <option name="OTHER_OPTIONS" value="" /> - <option name="HEAP_SIZE" /> - <option name="LOCALE" /> - <option name="OPEN_IN_BROWSER" value="true" /> - </component> - <component name="JikesSettings"> - <option name="JIKES_PATH" value="" /> - <option name="DEBUGGING_INFO" value="true" /> - <option name="DEPRECATION" value="true" /> - <option name="GENERATE_NO_WARNINGS" value="false" /> - <option name="IS_EMACS_ERRORS_MODE" value="true" /> - <option name="ADDITIONAL_OPTIONS_STRING" value="" /> - </component> - <component name="LogConsolePreferences"> - <option name="FILTER_ERRORS" value="false" /> - <option name="FILTER_WARNINGS" value="false" /> - <option name="FILTER_INFO" value="true" /> - <option name="CUSTOM_FILTER" /> - </component> - <component name="Palette2"> - <group name="Swing"> - <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" /> - </item> - <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" /> - </item> - <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" /> - </item> - <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true"> - <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" /> - </item> - <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" /> - <initial-values> - <property name="text" value="Button" /> - </initial-values> - </item> - <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> - <initial-values> - <property name="text" value="RadioButton" /> - </initial-values> - </item> - <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> - <initial-values> - <property name="text" value="CheckBox" /> - </initial-values> - </item> - <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" /> - <initial-values> - <property name="text" value="Label" /> - </initial-values> - </item> - <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> - <preferred-size width="150" height="-1" /> - </default-constraints> - </item> - <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> - <preferred-size width="150" height="-1" /> - </default-constraints> - </item> - <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> - <preferred-size width="150" height="-1" /> - </default-constraints> - </item> - <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" /> - </item> - <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> - <preferred-size width="150" height="50" /> - </default-constraints> - </item> - <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> - <preferred-size width="200" height="200" /> - </default-constraints> - </item> - <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> - <preferred-size width="200" height="200" /> - </default-constraints> - </item> - <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> - </item> - <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> - </item> - <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" /> - </item> - <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" /> - </item> - <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1"> - <preferred-size width="-1" height="20" /> - </default-constraints> - </item> - <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false"> - <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" /> - </item> - <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> - <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" /> - </item> - </group> - </component> - <component name="PerforceChangeBrowserSettings"> - <option name="USE_CLIENT_FILTER" value="true" /> - <option name="CLIENT" value="" /> - </component> - <component name="ProjectDetails"> - <option name="projectName" value="preload" /> - </component> - <component name="ProjectFileVersion" converted="true" /> - <component name="ProjectKey"> - <option name="state" value="project:///Volumes/Android/donut/frameworks/base/tools/preload/preload.ipr" /> - </component> - <component name="ProjectModuleManager"> - <modules> - <module fileurl="file://$PROJECT_DIR$/preload.iml" filepath="$PROJECT_DIR$/preload.iml" /> - </modules> - </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK"> - <output url="file:///tmp/preload" /> - </component> - <component name="RmicSettings"> - <option name="IS_EANABLED" value="false" /> - <option name="DEBUGGING_INFO" value="true" /> - <option name="GENERATE_NO_WARNINGS" value="false" /> - <option name="GENERATE_IIOP_STUBS" value="false" /> - <option name="ADDITIONAL_OPTIONS_STRING" value="" /> - </component> - <component name="StarteamConfiguration"> - <option name="SERVER" value="" /> - <option name="PORT" value="49201" /> - <option name="USER" value="" /> - <option name="PASSWORD" value="" /> - <option name="PROJECT" value="" /> - <option name="VIEW" value="" /> - <option name="ALTERNATIVE_WORKING_PATH" value="" /> - <option name="LOCK_ON_CHECKOUT" value="false" /> - <option name="UNLOCK_ON_CHECKIN" value="false" /> - </component> - <component name="Struts Assistant"> - <option name="showInputs" value="true" /> - <option name="resources"> - <value> - <option name="strutsPath" /> - <option name="strutsHelp" /> - </value> - </option> - <option name="selectedTaglibs" /> - <option name="selectedTaglibs" /> - <option name="myStrutsValidationEnabled" value="true" /> - <option name="myTilesValidationEnabled" value="true" /> - <option name="myValidatorValidationEnabled" value="true" /> - <option name="myReportErrorsAsWarnings" value="true" /> - </component> - <component name="SvnBranchConfigurationManager"> - <option name="mySupportsUserInfoFilter" value="true" /> - </component> - <component name="SvnChangesBrowserSettings"> - <option name="USE_AUTHOR_FIELD" value="true" /> - <option name="AUTHOR" value="" /> - <option name="LOCATION" value="" /> - <option name="USE_PROJECT_SETTINGS" value="true" /> - <option name="USE_ALTERNATE_LOCATION" value="false" /> - </component> - <component name="VCS.FileViewConfiguration"> - <option name="SELECTED_STATUSES" value="DEFAULT" /> - <option name="SELECTED_COLUMNS" value="DEFAULT" /> - <option name="SHOW_FILTERS" value="true" /> - <option name="CUSTOMIZE_VIEW" value="true" /> - <option name="SHOW_FILE_HISTORY_AS_TREE" value="true" /> - </component> - <component name="VcsDirectoryMappings"> - <mapping directory="" vcs="Perforce" /> - <mapping directory="/Volumes/Android/donut/frameworks/base" vcs="Git" /> - </component> - <component name="VssConfiguration"> - <option name="CLIENT_PATH" value="" /> - <option name="SRCSAFEINI_PATH" value="" /> - <option name="USER_NAME" value="" /> - <option name="PWD" value="" /> - <option name="VSS_IS_INITIALIZED" value="false" /> - <CheckoutOptions> - <option name="COMMENT" value="" /> - <option name="DO_NOT_GET_LATEST_VERSION" value="false" /> - <option name="REPLACE_WRITABLE" value="false" /> - <option name="RECURSIVE" value="false" /> - </CheckoutOptions> - <CheckinOptions> - <option name="COMMENT" value="" /> - <option name="KEEP_CHECKED_OUT" value="false" /> - <option name="RECURSIVE" value="false" /> - </CheckinOptions> - <AddOptions> - <option name="STORE_ONLY_LATEST_VERSION" value="false" /> - <option name="CHECK_OUT_IMMEDIATELY" value="false" /> - <option name="FILE_TYPE" value="0" /> - </AddOptions> - <UndocheckoutOptions> - <option name="MAKE_WRITABLE" value="false" /> - <option name="REPLACE_LOCAL_COPY" value="0" /> - <option name="RECURSIVE" value="false" /> - </UndocheckoutOptions> - <GetOptions> - <option name="REPLACE_WRITABLE" value="0" /> - <option name="MAKE_WRITABLE" value="false" /> - <option name="ANSWER_NEGATIVELY" value="false" /> - <option name="ANSWER_POSITIVELY" value="false" /> - <option name="RECURSIVE" value="false" /> - <option name="VERSION" /> - </GetOptions> - <VssConfigurableExcludedFilesTag /> - </component> - <component name="antWorkspaceConfiguration"> - <option name="IS_AUTOSCROLL_TO_SOURCE" value="false" /> - <option name="FILTER_TARGETS" value="false" /> - </component> - <component name="com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable" proportions="" version="1"> - <option name="myLastEditedConfigurable" /> - </component> - <component name="com.intellij.jsf.UserDefinedFacesConfigs"> - <option name="USER_DEFINED_CONFIGS"> - <value> - <list size="0" /> - </value> - </option> - </component> - <component name="com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectRootMasterDetailsConfigurable" proportions="" version="1"> - <option name="myPlainMode" value="false" /> - <option name="myLastEditedConfigurable" /> - </component> - <component name="com.intellij.profile.ui.ErrorOptionsConfigurable" proportions="" version="1"> - <option name="myLastEditedConfigurable" /> - </component> - <component name="uidesigner-configuration"> - <option name="INSTRUMENT_CLASSES" value="true" /> - <option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" /> - <option name="DEFAULT_LAYOUT_MANAGER" value="GridLayoutManager" /> - </component> -</project> - diff --git a/tools/preload/sorttable.js b/tools/preload/sorttable.js deleted file mode 100644 index 25bccb2..0000000 --- a/tools/preload/sorttable.js +++ /dev/null @@ -1,493 +0,0 @@ -/* - SortTable - version 2 - 7th April 2007 - Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ - - Instructions: - Download this file - Add <script src="sorttable.js"></script> to your HTML - Add class="sortable" to any table you'd like to make sortable - Click on the headers to sort - - Thanks to many, many people for contributions and suggestions. - Licenced as X11: http://www.kryogenix.org/code/browser/licence.html - This basically means: do what you want with it. -*/ - - -var stIsIE = /*@cc_on!@*/false; - -sorttable = { - init: function() { - // quit if this function has already been called - if (arguments.callee.done) return; - // flag this function so we don't do the same thing twice - arguments.callee.done = true; - // kill the timer - if (_timer) clearInterval(_timer); - - if (!document.createElement || !document.getElementsByTagName) return; - - sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; - - forEach(document.getElementsByTagName('table'), function(table) { - if (table.className.search(/\bsortable\b/) != -1) { - sorttable.makeSortable(table); - } - }); - - }, - - makeSortable: function(table) { - if (table.getElementsByTagName('thead').length == 0) { - // table doesn't have a tHead. Since it should have, create one and - // put the first table row in it. - the = document.createElement('thead'); - the.appendChild(table.rows[0]); - table.insertBefore(the,table.firstChild); - } - // Safari doesn't support table.tHead, sigh - if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; - - if (table.tHead.rows.length != 1) return; // can't cope with two header rows - - // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as - // "total" rows, for example). This is B&R, since what you're supposed - // to do is put them in a tfoot. So, if there are sortbottom rows, - // for backwards compatibility, move them to tfoot (creating it if needed). - sortbottomrows = []; - for (var i=0; i<table.rows.length; i++) { - if (table.rows[i].className.search(/\bsortbottom\b/) != -1) { - sortbottomrows[sortbottomrows.length] = table.rows[i]; - } - } - if (sortbottomrows) { - if (table.tFoot == null) { - // table doesn't have a tfoot. Create one. - tfo = document.createElement('tfoot'); - table.appendChild(tfo); - } - for (var i=0; i<sortbottomrows.length; i++) { - tfo.appendChild(sortbottomrows[i]); - } - delete sortbottomrows; - } - - // work through each column and calculate its type - headrow = table.tHead.rows[0].cells; - for (var i=0; i<headrow.length; i++) { - // manually override the type with a sorttable_type attribute - if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col - mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/); - if (mtch) { override = mtch[1]; } - if (mtch && typeof sorttable["sort_"+override] == 'function') { - headrow[i].sorttable_sortfunction = sorttable["sort_"+override]; - } else { - headrow[i].sorttable_sortfunction = sorttable.guessType(table,i); - } - // make it clickable to sort - headrow[i].sorttable_columnindex = i; - headrow[i].sorttable_tbody = table.tBodies[0]; - dean_addEvent(headrow[i],"click", function(e) { - - if (this.className.search(/\bsorttable_sorted\b/) != -1) { - // if we're already sorted by this column, just - // reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted', - 'sorttable_sorted_reverse'); - this.removeChild(document.getElementById('sorttable_sortfwdind')); - sortrevind = document.createElement('span'); - sortrevind.id = "sorttable_sortrevind"; - sortrevind.innerHTML = stIsIE ? ' <font face="webdings">5</font>' : ' ▴'; - this.appendChild(sortrevind); - return; - } - if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { - // if we're already sorted by this column in reverse, just - // re-reverse the table, which is quicker - sorttable.reverse(this.sorttable_tbody); - this.className = this.className.replace('sorttable_sorted_reverse', - 'sorttable_sorted'); - this.removeChild(document.getElementById('sorttable_sortrevind')); - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; - this.appendChild(sortfwdind); - return; - } - - // remove sorttable_sorted classes - theadrow = this.parentNode; - forEach(theadrow.childNodes, function(cell) { - if (cell.nodeType == 1) { // an element - cell.className = cell.className.replace('sorttable_sorted_reverse',''); - cell.className = cell.className.replace('sorttable_sorted',''); - } - }); - sortfwdind = document.getElementById('sorttable_sortfwdind'); - if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } - sortrevind = document.getElementById('sorttable_sortrevind'); - if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } - - this.className += ' sorttable_sorted'; - sortfwdind = document.createElement('span'); - sortfwdind.id = "sorttable_sortfwdind"; - sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾'; - this.appendChild(sortfwdind); - - // build an array to sort. This is a Schwartzian transform thing, - // i.e., we "decorate" each row with the actual sort key, - // sort based on the sort keys, and then put the rows back in order - // which is a lot faster because you only do getInnerText once per row - row_array = []; - col = this.sorttable_columnindex; - rows = this.sorttable_tbody.rows; - for (var j=0; j<rows.length; j++) { - row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]]; - } - /* If you want a stable sort, uncomment the following line */ - //sorttable.shaker_sort(row_array, this.sorttable_sortfunction); - /* and comment out this one */ - row_array.sort(this.sorttable_sortfunction); - - tb = this.sorttable_tbody; - for (var j=0; j<row_array.length; j++) { - tb.appendChild(row_array[j][1]); - } - - delete row_array; - }); - } - } - }, - - guessType: function(table, column) { - // guess the type of a column based on its first non-blank row - sortfn = sorttable.sort_alpha; - for (var i=0; i<table.tBodies[0].rows.length; i++) { - text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]); - if (text != '') { - if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) { - return sorttable.sort_numeric; - } - // check for a date: dd/mm/yyyy or dd/mm/yy - // can have / or . or - as separator - // can be mm/dd as well - possdate = text.match(sorttable.DATE_RE) - if (possdate) { - // looks like a date - first = parseInt(possdate[1]); - second = parseInt(possdate[2]); - if (first > 12) { - // definitely dd/mm - return sorttable.sort_ddmm; - } else if (second > 12) { - return sorttable.sort_mmdd; - } else { - // looks like a date, but we can't tell which, so assume - // that it's dd/mm (English imperialism!) and keep looking - sortfn = sorttable.sort_ddmm; - } - } - } - } - return sortfn; - }, - - getInnerText: function(node) { - // gets the text we want to use for sorting for a cell. - // strips leading and trailing whitespace. - // this is *not* a generic getInnerText function; it's special to sorttable. - // for example, you can override the cell text with a customkey attribute. - // it also gets .value for <input> fields. - - hasInputs = (typeof node.getElementsByTagName == 'function') && - node.getElementsByTagName('input').length; - - if (node.getAttribute("sorttable_customkey") != null) { - return node.getAttribute("sorttable_customkey"); - } - else if (typeof node.textContent != 'undefined' && !hasInputs) { - return node.textContent.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.innerText != 'undefined' && !hasInputs) { - return node.innerText.replace(/^\s+|\s+$/g, ''); - } - else if (typeof node.text != 'undefined' && !hasInputs) { - return node.text.replace(/^\s+|\s+$/g, ''); - } - else { - switch (node.nodeType) { - case 3: - if (node.nodeName.toLowerCase() == 'input') { - return node.value.replace(/^\s+|\s+$/g, ''); - } - case 4: - return node.nodeValue.replace(/^\s+|\s+$/g, ''); - break; - case 1: - case 11: - var innerText = ''; - for (var i = 0; i < node.childNodes.length; i++) { - innerText += sorttable.getInnerText(node.childNodes[i]); - } - return innerText.replace(/^\s+|\s+$/g, ''); - break; - default: - return ''; - } - } - }, - - reverse: function(tbody) { - // reverse the rows in a tbody - newrows = []; - for (var i=0; i<tbody.rows.length; i++) { - newrows[newrows.length] = tbody.rows[i]; - } - for (var i=newrows.length-1; i>=0; i--) { - tbody.appendChild(newrows[i]); - } - delete newrows; - }, - - /* sort functions - each sort function takes two parameters, a and b - you are comparing a[0] and b[0] */ - sort_numeric: function(a,b) { - aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); - if (isNaN(aa)) aa = 0; - bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); - if (isNaN(bb)) bb = 0; - return aa-bb; - }, - sort_alpha: function(a,b) { - if (a[0]==b[0]) return 0; - if (a[0]<b[0]) return -1; - return 1; - }, - sort_ddmm: function(a,b) { - mtch = a[0].match(sorttable.DATE_RE); - y = mtch[3]; m = mtch[2]; d = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt1 = y+m+d; - mtch = b[0].match(sorttable.DATE_RE); - y = mtch[3]; m = mtch[2]; d = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt2 = y+m+d; - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; - }, - sort_mmdd: function(a,b) { - mtch = a[0].match(sorttable.DATE_RE); - y = mtch[3]; d = mtch[2]; m = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt1 = y+m+d; - mtch = b[0].match(sorttable.DATE_RE); - y = mtch[3]; d = mtch[2]; m = mtch[1]; - if (m.length == 1) m = '0'+m; - if (d.length == 1) d = '0'+d; - dt2 = y+m+d; - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; - }, - - shaker_sort: function(list, comp_func) { - // A stable sort function to allow multi-level sorting of data - // see: http://en.wikipedia.org/wiki/Cocktail_sort - // thanks to Joseph Nahmias - var b = 0; - var t = list.length - 1; - var swap = true; - - while(swap) { - swap = false; - for(var i = b; i < t; ++i) { - if ( comp_func(list[i], list[i+1]) > 0 ) { - var q = list[i]; list[i] = list[i+1]; list[i+1] = q; - swap = true; - } - } // for - t--; - - if (!swap) break; - - for(var i = t; i > b; --i) { - if ( comp_func(list[i], list[i-1]) < 0 ) { - var q = list[i]; list[i] = list[i-1]; list[i-1] = q; - swap = true; - } - } // for - b++; - - } // while(swap) - } -} - -/* ****************************************************************** - Supporting functions: bundled here to avoid depending on a library - ****************************************************************** */ - -// Dean Edwards/Matthias Miller/John Resig - -/* for Mozilla/Opera9 */ -if (document.addEventListener) { - document.addEventListener("DOMContentLoaded", sorttable.init, false); -} - -/* for Internet Explorer */ -/*@cc_on @*/ -/*@if (@_win32) - document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>"); - var script = document.getElementById("__ie_onload"); - script.onreadystatechange = function() { - if (this.readyState == "complete") { - sorttable.init(); // call the onload handler - } - }; -/*@end @*/ - -/* for Safari */ -if (/WebKit/i.test(navigator.userAgent)) { // sniff - var _timer = setInterval(function() { - if (/loaded|complete/.test(document.readyState)) { - sorttable.init(); // call the onload handler - } - }, 10); -} - -/* for other browsers */ -window.onload = sorttable.init; - -// written by Dean Edwards, 2005 -// with input from Tino Zijdel, Matthias Miller, Diego Perini - -// http://dean.edwards.name/weblog/2005/10/add-event/ - -function dean_addEvent(element, type, handler) { - if (element.addEventListener) { - element.addEventListener(type, handler, false); - } else { - // assign each event handler a unique ID - if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++; - // create a hash table of event types for the element - if (!element.events) element.events = {}; - // create a hash table of event handlers for each element/event pair - var handlers = element.events[type]; - if (!handlers) { - handlers = element.events[type] = {}; - // store the existing event handler (if there is one) - if (element["on" + type]) { - handlers[0] = element["on" + type]; - } - } - // store the event handler in the hash table - handlers[handler.$$guid] = handler; - // assign a global event handler to do all the work - element["on" + type] = handleEvent; - } -}; -// a counter used to create unique IDs -dean_addEvent.guid = 1; - -function removeEvent(element, type, handler) { - if (element.removeEventListener) { - element.removeEventListener(type, handler, false); - } else { - // delete the event handler from the hash table - if (element.events && element.events[type]) { - delete element.events[type][handler.$$guid]; - } - } -}; - -function handleEvent(event) { - var returnValue = true; - // grab the event object (IE uses a global event object) - event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); - // get a reference to the hash table of event handlers - var handlers = this.events[event.type]; - // execute each event handler - for (var i in handlers) { - this.$$handleEvent = handlers[i]; - if (this.$$handleEvent(event) === false) { - returnValue = false; - } - } - return returnValue; -}; - -function fixEvent(event) { - // add W3C standard event methods - event.preventDefault = fixEvent.preventDefault; - event.stopPropagation = fixEvent.stopPropagation; - return event; -}; -fixEvent.preventDefault = function() { - this.returnValue = false; -}; -fixEvent.stopPropagation = function() { - this.cancelBubble = true; -} - -// Dean's forEach: http://dean.edwards.name/base/forEach.js -/* - forEach, version 1.0 - Copyright 2006, Dean Edwards - License: http://www.opensource.org/licenses/mit-license.php -*/ - -// array-like enumeration -if (!Array.forEach) { // mozilla already supports this - Array.forEach = function(array, block, context) { - for (var i = 0; i < array.length; i++) { - block.call(context, array[i], i, array); - } - }; -} - -// generic enumeration -Function.prototype.forEach = function(object, block, context) { - for (var key in object) { - if (typeof this.prototype[key] == "undefined") { - block.call(context, object[key], key, object); - } - } -}; - -// character enumeration -String.forEach = function(string, block, context) { - Array.forEach(string.split(""), function(chr, index) { - block.call(context, chr, index, string); - }); -}; - -// globally resolve forEach enumeration -var forEach = function(object, block, context) { - if (object) { - var resolve = Object; // default - if (object instanceof Function) { - // functions have a "length" property - resolve = Function; - } else if (object.forEach instanceof Function) { - // the object implements a custom forEach method so use that - object.forEach(block, context); - return; - } else if (typeof object == "string") { - // the object is a string - resolve = String; - } else if (typeof object.length == "number") { - // the object is array-like - resolve = Array; - } - resolve.forEach(object, block, context); - } -}; - diff --git a/tools/validatekeymaps/Android.mk b/tools/validatekeymaps/Android.mk deleted file mode 100644 index 9af721d..0000000 --- a/tools/validatekeymaps/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2010 The Android Open Source Project -# -# Keymap validation 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_CFLAGS := -Wall -Werror - -LOCAL_STATIC_LIBRARIES := \ - libinput \ - libutils \ - libcutils \ - liblog - -ifeq ($(HOST_OS),linux) -LOCAL_LDLIBS += -ldl -lpthread -endif - -LOCAL_MODULE := validatekeymaps -LOCAL_MODULE_TAGS := optional - -include $(BUILD_HOST_EXECUTABLE) - -endif # TARGET_BUILD_APPS diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp deleted file mode 100644 index 5b45c55..0000000 --- a/tools/validatekeymaps/Main.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 <input/KeyCharacterMap.h> -#include <input/KeyLayoutMap.h> -#include <input/VirtualKeyMap.h> -#include <utils/PropertyMap.h> -#include <utils/String8.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -using namespace android; - -static const char* gProgName = "validatekeymaps"; - -enum FileType { - FILETYPE_UNKNOWN, - FILETYPE_KEYLAYOUT, - FILETYPE_KEYCHARACTERMAP, - FILETYPE_VIRTUALKEYDEFINITION, - FILETYPE_INPUTDEVICECONFIGURATION, -}; - - -static void usage() { - fprintf(stderr, "Keymap Validation Tool\n\n"); - fprintf(stderr, "Usage:\n"); - fprintf(stderr, - " %s [*.kl] [*.kcm] [*.idc] [virtualkeys.*] [...]\n" - " Validates the specified key layouts, key character maps, \n" - " input device configurations, or virtual key definitions.\n\n", - gProgName); -} - -static FileType getFileType(const char* filename) { - const char *extension = strrchr(filename, '.'); - if (extension) { - if (strcmp(extension, ".kl") == 0) { - return FILETYPE_KEYLAYOUT; - } - if (strcmp(extension, ".kcm") == 0) { - return FILETYPE_KEYCHARACTERMAP; - } - if (strcmp(extension, ".idc") == 0) { - return FILETYPE_INPUTDEVICECONFIGURATION; - } - } - - if (strstr(filename, "virtualkeys.")) { - return FILETYPE_VIRTUALKEYDEFINITION; - } - - return FILETYPE_UNKNOWN; -} - -static bool validateFile(const char* filename) { - fprintf(stdout, "Validating file '%s'...\n", filename); - - FileType fileType = getFileType(filename); - switch (fileType) { - case FILETYPE_UNKNOWN: - fprintf(stderr, "Supported file types: *.kl, *.kcm, virtualkeys.*\n\n"); - return false; - - case FILETYPE_KEYLAYOUT: { - sp<KeyLayoutMap> map; - status_t status = KeyLayoutMap::load(String8(filename), &map); - if (status) { - fprintf(stderr, "Error %d parsing key layout file.\n\n", status); - return false; - } - break; - } - - case FILETYPE_KEYCHARACTERMAP: { - sp<KeyCharacterMap> map; - status_t status = KeyCharacterMap::load(String8(filename), - KeyCharacterMap::FORMAT_ANY, &map); - if (status) { - fprintf(stderr, "Error %d parsing key character map file.\n\n", status); - return false; - } - break; - } - - case FILETYPE_INPUTDEVICECONFIGURATION: { - PropertyMap* map; - status_t status = PropertyMap::load(String8(filename), &map); - if (status) { - fprintf(stderr, "Error %d parsing input device configuration file.\n\n", status); - return false; - } - delete map; - break; - } - - case FILETYPE_VIRTUALKEYDEFINITION: { - VirtualKeyMap* map; - status_t status = VirtualKeyMap::load(String8(filename), &map); - if (status) { - fprintf(stderr, "Error %d parsing virtual key definition file.\n\n", status); - return false; - } - delete map; - break; - } - } - - fputs("No errors.\n\n", stdout); - return true; -} - -int main(int argc, const char** argv) { - if (argc < 2) { - usage(); - return 1; - } - - int result = 0; - for (int i = 1; i < argc; i++) { - if (!validateFile(argv[i])) { - result = 1; - } - } - - if (result) { - fputs("Failed!\n", stderr); - } else { - fputs("Success.\n", stdout); - } - return result; -} diff --git a/tools/velocityplot/velocityplot.py b/tools/velocityplot/velocityplot.py deleted file mode 100755 index 421bed4..0000000 --- a/tools/velocityplot/velocityplot.py +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/env python2.6 -# -# Copyright (C) 2011 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. -# - -# -# Plots debug log output from VelocityTracker. -# Enable DEBUG_VELOCITY to print the output. -# -# This code supports side-by-side comparison of two algorithms. -# The old algorithm should be modified to emit debug log messages containing -# the word "OLD". -# - -import numpy as np -import matplotlib.pyplot as plot -import subprocess -import re -import fcntl -import os -import errno -import bisect -from datetime import datetime, timedelta - -# Parameters. -timespan = 15 # seconds total span shown -scrolljump = 5 # seconds jump when scrolling -timeticks = 1 # seconds between each time tick - -# Non-blocking stream wrapper. -class NonBlockingStream: - def __init__(self, stream): - fcntl.fcntl(stream, fcntl.F_SETFL, os.O_NONBLOCK) - self.stream = stream - self.buffer = '' - self.pos = 0 - - def readline(self): - while True: - index = self.buffer.find('\n', self.pos) - if index != -1: - result = self.buffer[self.pos:index] - self.pos = index + 1 - return result - - self.buffer = self.buffer[self.pos:] - self.pos = 0 - try: - chunk = os.read(self.stream.fileno(), 4096) - except OSError, e: - if e.errno == errno.EAGAIN: - return None - raise e - if len(chunk) == 0: - if len(self.buffer) == 0: - raise(EOFError) - else: - result = self.buffer - self.buffer = '' - self.pos = 0 - return result - self.buffer += chunk - -# Plotter -class Plotter: - def __init__(self, adbout): - self.adbout = adbout - - self.fig = plot.figure(1) - self.fig.suptitle('Velocity Tracker', fontsize=12) - self.fig.set_dpi(96) - self.fig.set_size_inches(16, 12, forward=True) - - self.velocity_x = self._make_timeseries() - self.velocity_y = self._make_timeseries() - self.velocity_magnitude = self._make_timeseries() - self.velocity_axes = self._add_timeseries_axes( - 1, 'Velocity', 'px/s', [-5000, 5000], - yticks=range(-5000, 5000, 1000)) - self.velocity_line_x = self._add_timeseries_line( - self.velocity_axes, 'vx', 'red') - self.velocity_line_y = self._add_timeseries_line( - self.velocity_axes, 'vy', 'green') - self.velocity_line_magnitude = self._add_timeseries_line( - self.velocity_axes, 'magnitude', 'blue') - self._add_timeseries_legend(self.velocity_axes) - - shared_axis = self.velocity_axes - - self.old_velocity_x = self._make_timeseries() - self.old_velocity_y = self._make_timeseries() - self.old_velocity_magnitude = self._make_timeseries() - self.old_velocity_axes = self._add_timeseries_axes( - 2, 'Old Algorithm Velocity', 'px/s', [-5000, 5000], - sharex=shared_axis, - yticks=range(-5000, 5000, 1000)) - self.old_velocity_line_x = self._add_timeseries_line( - self.old_velocity_axes, 'vx', 'red') - self.old_velocity_line_y = self._add_timeseries_line( - self.old_velocity_axes, 'vy', 'green') - self.old_velocity_line_magnitude = self._add_timeseries_line( - self.old_velocity_axes, 'magnitude', 'blue') - self._add_timeseries_legend(self.old_velocity_axes) - - self.timer = self.fig.canvas.new_timer(interval=100) - self.timer.add_callback(lambda: self.update()) - self.timer.start() - - self.timebase = None - self._reset_parse_state() - - # Initialize a time series. - def _make_timeseries(self): - return [[], []] - - # Add a subplot to the figure for a time series. - def _add_timeseries_axes(self, index, title, ylabel, ylim, yticks, sharex=None): - num_graphs = 2 - height = 0.9 / num_graphs - top = 0.95 - height * index - axes = self.fig.add_axes([0.1, top, 0.8, height], - xscale='linear', - xlim=[0, timespan], - ylabel=ylabel, - yscale='linear', - ylim=ylim, - sharex=sharex) - axes.text(0.02, 0.02, title, transform=axes.transAxes, fontsize=10, fontweight='bold') - axes.set_xlabel('time (s)', fontsize=10, fontweight='bold') - axes.set_ylabel(ylabel, fontsize=10, fontweight='bold') - axes.set_xticks(range(0, timespan + 1, timeticks)) - axes.set_yticks(yticks) - axes.grid(True) - - for label in axes.get_xticklabels(): - label.set_fontsize(9) - for label in axes.get_yticklabels(): - label.set_fontsize(9) - - return axes - - # Add a line to the axes for a time series. - def _add_timeseries_line(self, axes, label, color, linewidth=1): - return axes.plot([], label=label, color=color, linewidth=linewidth)[0] - - # Add a legend to a time series. - def _add_timeseries_legend(self, axes): - axes.legend( - loc='upper left', - bbox_to_anchor=(1.01, 1), - borderpad=0.1, - borderaxespad=0.1, - prop={'size': 10}) - - # Resets the parse state. - def _reset_parse_state(self): - self.parse_velocity_x = None - self.parse_velocity_y = None - self.parse_velocity_magnitude = None - self.parse_old_velocity_x = None - self.parse_old_velocity_y = None - self.parse_old_velocity_magnitude = None - - # Update samples. - def update(self): - timeindex = 0 - while True: - try: - line = self.adbout.readline() - except EOFError: - plot.close() - return - if line is None: - break - print line - - try: - timestamp = self._parse_timestamp(line) - except ValueError, e: - continue - if self.timebase is None: - self.timebase = timestamp - delta = timestamp - self.timebase - timeindex = delta.seconds + delta.microseconds * 0.000001 - - if line.find(': position') != -1: - self.parse_velocity_x = self._get_following_number(line, 'vx=') - self.parse_velocity_y = self._get_following_number(line, 'vy=') - self.parse_velocity_magnitude = self._get_following_number(line, 'speed=') - self._append(self.velocity_x, timeindex, self.parse_velocity_x) - self._append(self.velocity_y, timeindex, self.parse_velocity_y) - self._append(self.velocity_magnitude, timeindex, self.parse_velocity_magnitude) - - if line.find(': OLD') != -1: - self.parse_old_velocity_x = self._get_following_number(line, 'vx=') - self.parse_old_velocity_y = self._get_following_number(line, 'vy=') - self.parse_old_velocity_magnitude = self._get_following_number(line, 'speed=') - self._append(self.old_velocity_x, timeindex, self.parse_old_velocity_x) - self._append(self.old_velocity_y, timeindex, self.parse_old_velocity_y) - self._append(self.old_velocity_magnitude, timeindex, self.parse_old_velocity_magnitude) - - # Scroll the plots. - if timeindex > timespan: - bottom = int(timeindex) - timespan + scrolljump - self.timebase += timedelta(seconds=bottom) - self._scroll(self.velocity_x, bottom) - self._scroll(self.velocity_y, bottom) - self._scroll(self.velocity_magnitude, bottom) - self._scroll(self.old_velocity_x, bottom) - self._scroll(self.old_velocity_y, bottom) - self._scroll(self.old_velocity_magnitude, bottom) - - # Redraw the plots. - self.velocity_line_x.set_data(self.velocity_x) - self.velocity_line_y.set_data(self.velocity_y) - self.velocity_line_magnitude.set_data(self.velocity_magnitude) - self.old_velocity_line_x.set_data(self.old_velocity_x) - self.old_velocity_line_y.set_data(self.old_velocity_y) - self.old_velocity_line_magnitude.set_data(self.old_velocity_magnitude) - - self.fig.canvas.draw_idle() - - # Scroll a time series. - def _scroll(self, timeseries, bottom): - bottom_index = bisect.bisect_left(timeseries[0], bottom) - del timeseries[0][:bottom_index] - del timeseries[1][:bottom_index] - for i, timeindex in enumerate(timeseries[0]): - timeseries[0][i] = timeindex - bottom - - # Extract a word following the specified prefix. - def _get_following_word(self, line, prefix): - prefix_index = line.find(prefix) - if prefix_index == -1: - return None - start_index = prefix_index + len(prefix) - delim_index = line.find(',', start_index) - if delim_index == -1: - return line[start_index:] - else: - return line[start_index:delim_index] - - # Extract a number following the specified prefix. - def _get_following_number(self, line, prefix): - word = self._get_following_word(line, prefix) - if word is None: - return None - return float(word) - - # Add a value to a time series. - def _append(self, timeseries, timeindex, number): - timeseries[0].append(timeindex) - timeseries[1].append(number) - - # Parse the logcat timestamp. - # Timestamp has the form '01-21 20:42:42.930' - def _parse_timestamp(self, line): - return datetime.strptime(line[0:18], '%m-%d %H:%M:%S.%f') - -# Notice -print "Velocity Tracker plotting tool" -print "-----------------------------------------\n" -print "Please enable debug logging and recompile the code." - -# Start adb. -print "Starting adb logcat.\n" - -adb = subprocess.Popen(['adb', 'logcat', '-s', '-v', 'time', 'Input:*', 'VelocityTracker:*'], - stdout=subprocess.PIPE) -adbout = NonBlockingStream(adb.stdout) - -# Prepare plotter. -plotter = Plotter(adbout) -plotter.update() - -# Main loop. -plot.show() |