diff options
| author | Dianne Hackborn <hackbod@google.com> | 2009-07-06 11:07:40 -0700 | 
|---|---|---|
| committer | Dianne Hackborn <hackbod@google.com> | 2009-07-06 11:12:37 -0700 | 
| commit | 78c405178c57bb45e40f1e2839d6a18d91f7f02c (patch) | |
| tree | 6e7137f628b8fff1f72c59e5e42f3f4878e0bb39 /libs/utils | |
| parent | ef1f21b34f5624adb7436d3da927660ed16c97c7 (diff) | |
| download | frameworks_base-78c405178c57bb45e40f1e2839d6a18d91f7f02c.zip frameworks_base-78c405178c57bb45e40f1e2839d6a18d91f7f02c.tar.gz frameworks_base-78c405178c57bb45e40f1e2839d6a18d91f7f02c.tar.bz2 | |
Don't re-parse the framework resources all the time.
A small optimization to the resource code, to not re-parse the framework
resources every time we build a new AssetManager.  Instead, you can now
construct a ResTable from a previously created one...  of course, like the
existing code for using the data in-place, you can't delete the original
ResTable until you have deleted the one that has been constructed from it.
Diffstat (limited to 'libs/utils')
| -rw-r--r-- | libs/utils/Asset.cpp | 5 | ||||
| -rw-r--r-- | libs/utils/AssetManager.cpp | 97 | ||||
| -rw-r--r-- | libs/utils/ResourceTypes.cpp | 96 | 
3 files changed, 158 insertions, 40 deletions
| diff --git a/libs/utils/Asset.cpp b/libs/utils/Asset.cpp index 91203dd..23cb72d 100644 --- a/libs/utils/Asset.cpp +++ b/libs/utils/Asset.cpp @@ -582,11 +582,14 @@ const void* _FileAsset::ensureAlignment(FileMap* map)      if ((((size_t)data)&0x3) == 0) {          // We can return this directly if it is aligned on a word          // boundary. +        LOGV("Returning aligned FileAsset %p (%s).", this, +                getAssetSource());          return data;      }      // If not aligned on a word boundary, then we need to copy it into      // our own buffer. -    LOGV("Copying FileAsset %p to buffer size %d to make it aligned.", this, (int)mLength); +    LOGV("Copying FileAsset %p (%s) to buffer size %d to make it aligned.", this, +            getAssetSource(), (int)mLength);      unsigned char* buf = new unsigned char[mLength];      if (buf == NULL) {          LOGE("alloc of %ld bytes failed\n", (long) mLength); diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp index 4126bfb..5a05e6a 100644 --- a/libs/utils/AssetManager.cpp +++ b/libs/utils/AssetManager.cpp @@ -395,21 +395,41 @@ const ResTable* AssetManager::getResTable(bool required) const      const size_t N = mAssetPaths.size();      for (size_t i=0; i<N; i++) {          Asset* ass = NULL; +        ResTable* sharedRes = NULL;          bool shared = true;          const asset_path& ap = mAssetPaths.itemAt(i);          LOGV("Looking for resource asset in '%s'\n", ap.path.string());          if (ap.type != kFileTypeDirectory) { -            ass = const_cast<AssetManager*>(this)-> -                mZipSet.getZipResourceTable(ap.path); -            if (ass == NULL) { -                LOGV("loading resource table %s\n", ap.path.string()); +            if (i == 0) { +                // The first item is typically the framework resources, +                // which we want to avoid parsing every time. +                sharedRes = const_cast<AssetManager*>(this)-> +                    mZipSet.getZipResourceTable(ap.path); +            } +            if (sharedRes == NULL) {                  ass = const_cast<AssetManager*>(this)-> -                    openNonAssetInPathLocked("resources.arsc", -                                             Asset::ACCESS_BUFFER, -                                             ap); -                if (ass != NULL && ass != kExcludedAsset) { +                    mZipSet.getZipResourceTableAsset(ap.path); +                if (ass == NULL) { +                    LOGV("loading resource table %s\n", ap.path.string());                      ass = const_cast<AssetManager*>(this)-> -                        mZipSet.setZipResourceTable(ap.path, ass); +                        openNonAssetInPathLocked("resources.arsc", +                                                 Asset::ACCESS_BUFFER, +                                                 ap); +                    if (ass != NULL && ass != kExcludedAsset) { +                        ass = const_cast<AssetManager*>(this)-> +                            mZipSet.setZipResourceTableAsset(ap.path, ass); +                    } +                } +                 +                if (i == 0 && ass != NULL) { +                    // If this is the first resource table in the asset +                    // manager, then we are going to cache it so that we +                    // can quickly copy it out for others. +                    LOGV("Creating shared resources for %s", ap.path.string()); +                    sharedRes = new ResTable(); +                    sharedRes->add(ass, (void*)(i+1), false); +                    sharedRes = const_cast<AssetManager*>(this)-> +                        mZipSet.setZipResourceTable(ap.path, sharedRes);                  }              }          } else { @@ -420,13 +440,19 @@ const ResTable* AssetManager::getResTable(bool required) const                                           ap);              shared = false;          } -        if (ass != NULL && ass != kExcludedAsset) { +        if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) {              if (rt == NULL) {                  mResources = rt = new ResTable();                  updateResourceParamsLocked();              }              LOGV("Installing resource asset %p in to table %p\n", ass, mResources); -            rt->add(ass, (void*)(i+1), !shared); +            if (sharedRes != NULL) { +                LOGV("Copying existing resources for %s", ap.path.string()); +                rt->add(sharedRes); +            } else { +                LOGV("Parsing resources for %s", ap.path.string()); +                rt->add(ass, (void*)(i+1), !shared); +            }              if (!shared) {                  delete ass; @@ -1510,7 +1536,8 @@ Mutex AssetManager::SharedZip::gLock;  DefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen;  AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) -    : mPath(path), mZipFile(NULL), mModWhen(modWhen), mResourceTableAsset(NULL) +    : mPath(path), mZipFile(NULL), mModWhen(modWhen), +      mResourceTableAsset(NULL), mResourceTable(NULL)  {      //LOGI("Creating SharedZip %p %s\n", this, (const char*)mPath);      mZipFile = new ZipFileRO; @@ -1563,6 +1590,25 @@ Asset* AssetManager::SharedZip::setResourceTableAsset(Asset* asset)      return mResourceTableAsset;  } +ResTable* AssetManager::SharedZip::getResourceTable() +{ +    LOGV("Getting from SharedZip %p resource table %p\n", this, mResourceTable); +    return mResourceTable; +} + +ResTable* AssetManager::SharedZip::setResourceTable(ResTable* res) +{ +    { +        AutoMutex _l(gLock); +        if (mResourceTable == NULL) { +            mResourceTable = res; +            return res; +        } +    } +    delete res; +    return mResourceTable; +} +  bool AssetManager::SharedZip::isUpToDate()  {      time_t modWhen = getFileModDate(mPath.string()); @@ -1572,6 +1618,9 @@ bool AssetManager::SharedZip::isUpToDate()  AssetManager::SharedZip::~SharedZip()  {      //LOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath); +    if (mResourceTable != NULL) { +        delete mResourceTable; +    }      if (mResourceTableAsset != NULL) {          delete mResourceTableAsset;      } @@ -1627,7 +1676,7 @@ ZipFileRO* AssetManager::ZipSet::getZip(const String8& path)      return zip->getZip();  } -Asset* AssetManager::ZipSet::getZipResourceTable(const String8& path) +Asset* AssetManager::ZipSet::getZipResourceTableAsset(const String8& path)  {      int idx = getIndex(path);      sp<SharedZip> zip = mZipFile[idx]; @@ -1638,7 +1687,7 @@ Asset* AssetManager::ZipSet::getZipResourceTable(const String8& path)      return zip->getResourceTableAsset();  } -Asset* AssetManager::ZipSet::setZipResourceTable(const String8& path, +Asset* AssetManager::ZipSet::setZipResourceTableAsset(const String8& path,                                                   Asset* asset)  {      int idx = getIndex(path); @@ -1647,6 +1696,26 @@ Asset* AssetManager::ZipSet::setZipResourceTable(const String8& path,      return zip->setResourceTableAsset(asset);  } +ResTable* AssetManager::ZipSet::getZipResourceTable(const String8& path) +{ +    int idx = getIndex(path); +    sp<SharedZip> zip = mZipFile[idx]; +    if (zip == NULL) { +        zip = SharedZip::get(path); +        mZipFile.editItemAt(idx) = zip; +    } +    return zip->getResourceTable(); +} + +ResTable* AssetManager::ZipSet::setZipResourceTable(const String8& path, +                                                    ResTable* res) +{ +    int idx = getIndex(path); +    sp<SharedZip> zip = mZipFile[idx]; +    // doesn't make sense to call before previously accessing. +    return zip->setResourceTable(res); +} +  /*   * Generate the partial pathname for the specified archive.  The caller   * gets to prepend the asset root directory. diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 4a5063a..109f28d 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -1136,8 +1136,9 @@ status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const  struct ResTable::Header  { -    Header() : ownedData(NULL), header(NULL) { } +    Header(ResTable* _owner) : owner(_owner), ownedData(NULL), header(NULL) { } +    ResTable* const                 owner;      void*                           ownedData;      const ResTable_header*          header;      size_t                          size; @@ -1163,8 +1164,8 @@ struct ResTable::Type  struct ResTable::Package  { -    Package(const Header* _header, const ResTable_package* _package) -        : header(_header), package(_package) { } +    Package(ResTable* _owner, const Header* _header, const ResTable_package* _package) +        : owner(_owner), header(_header), package(_package) { }      ~Package()      {          size_t i = types.size(); @@ -1174,10 +1175,14 @@ struct ResTable::Package          }      } +    ResTable* const                 owner;      const Header* const             header;      const ResTable_package* const   package;      Vector<Type*>                   types; +    ResStringPool                   typeStrings; +    ResStringPool                   keyStrings; +          const Type* getType(size_t idx) const {          return idx < types.size() ? types[idx] : NULL;      } @@ -1188,13 +1193,16 @@ struct ResTable::Package  // table that defined the package); the ones after are skins on top of it.  struct ResTable::PackageGroup  { -    PackageGroup(const String16& _name, uint32_t _id) -        : name(_name), id(_id), typeCount(0), bags(NULL) { } +    PackageGroup(ResTable* _owner, const String16& _name, uint32_t _id) +        : owner(_owner), name(_name), id(_id), typeCount(0), bags(NULL) { }      ~PackageGroup() {          clearBagCache();          const size_t N = packages.size();          for (size_t i=0; i<N; i++) { -            delete packages[i]; +            Package* pkg = packages[i]; +            if (pkg->owner == owner) { +                delete pkg; +            }          }      } @@ -1225,15 +1233,17 @@ struct ResTable::PackageGroup          }      } +    ResTable* const                 owner;      String16 const                  name;      uint32_t const                  id;      Vector<Package*>                packages; +     +    // This is for finding typeStrings and other common package stuff. +    Package*                        basePackage; -    // Taken from the root package. -    ResStringPool                   typeStrings; -    ResStringPool                   keyStrings; +    // For quick access.      size_t                          typeCount; - +          // Computed attribute bags, first indexed by the type and second      // by the entry in that type.      bag_set***                      bags; @@ -1560,11 +1570,36 @@ status_t ResTable::add(Asset* asset, void* cookie, bool copyData)      return add(data, size, cookie, asset, copyData);  } +status_t ResTable::add(ResTable* src) +{ +    mError = src->mError; +    mParams = src->mParams; +     +    for (size_t i=0; i<src->mHeaders.size(); i++) { +        mHeaders.add(src->mHeaders[i]); +    } +     +    for (size_t i=0; i<src->mPackageGroups.size(); i++) { +        PackageGroup* srcPg = src->mPackageGroups[i]; +        PackageGroup* pg = new PackageGroup(this, srcPg->name, srcPg->id); +        for (size_t j=0; j<srcPg->packages.size(); j++) { +            pg->packages.add(srcPg->packages[j]); +        } +        pg->basePackage = srcPg->basePackage; +        pg->typeCount = srcPg->typeCount; +        mPackageGroups.add(pg); +    } +     +    memcpy(mPackageMap, src->mPackageMap, sizeof(mPackageMap)); +     +    return mError; +} +  status_t ResTable::add(const void* data, size_t size, void* cookie,                         Asset* asset, bool copyData)  {      if (!data) return NO_ERROR; -    Header* header = new Header; +    Header* header = new Header(this);      header->index = mHeaders.size();      header->cookie = cookie;      mHeaders.add(header); @@ -1682,10 +1717,12 @@ void ResTable::uninit()      N = mHeaders.size();      for (size_t i=0; i<N; i++) {          Header* header = mHeaders[i]; -        if (header->ownedData) { -            free(header->ownedData); +        if (header->owner == this) { +            if (header->ownedData) { +                free(header->ownedData); +            } +            delete header;          } -        delete header;      }      mPackageGroups.clear(); @@ -1728,8 +1765,8 @@ bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const          outName->package = grp->name.string();          outName->packageLen = grp->name.size(); -        outName->type = grp->typeStrings.stringAt(t, &outName->typeLen); -        outName->name = grp->keyStrings.stringAt( +        outName->type = grp->basePackage->typeStrings.stringAt(t, &outName->typeLen); +        outName->name = grp->basePackage->keyStrings.stringAt(              dtohl(entry->key.index), &outName->nameLen);          return true;      } @@ -2331,13 +2368,13 @@ nope:              continue;          } -        const ssize_t ti = group->typeStrings.indexOfString(type, typeLen); +        const ssize_t ti = group->basePackage->typeStrings.indexOfString(type, typeLen);          if (ti < 0) {              TABLE_NOISY(printf("Type not found in package %s\n", String8(group->name).string()));              continue;          } -        const ssize_t ei = group->keyStrings.indexOfString(name, nameLen); +        const ssize_t ei = group->basePackage->keyStrings.indexOfString(name, nameLen);          if (ei < 0) {              TABLE_NOISY(printf("Name not found in package %s\n", String8(group->name).string()));              continue; @@ -3630,25 +3667,36 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,      PackageGroup* group = NULL;      uint32_t id = dtohl(pkg->id);      if (id != 0 && id < 256) { +     +        package = new Package(this, header, pkg); +        if (package == NULL) { +            return (mError=NO_MEMORY); +        } +                  size_t idx = mPackageMap[id];          if (idx == 0) {              idx = mPackageGroups.size()+1;              char16_t tmpName[sizeof(pkg->name)/sizeof(char16_t)];              strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(char16_t)); -            group = new PackageGroup(String16(tmpName), id); +            group = new PackageGroup(this, String16(tmpName), id);              if (group == NULL) { +                delete package;                  return (mError=NO_MEMORY);              } -            err = group->typeStrings.setTo(base+dtohl(pkg->typeStrings), +            err = package->typeStrings.setTo(base+dtohl(pkg->typeStrings),                                             header->dataEnd-(base+dtohl(pkg->typeStrings)));              if (err != NO_ERROR) { +                delete group; +                delete package;                  return (mError=err);              } -            err = group->keyStrings.setTo(base+dtohl(pkg->keyStrings), +            err = package->keyStrings.setTo(base+dtohl(pkg->keyStrings),                                            header->dataEnd-(base+dtohl(pkg->keyStrings)));              if (err != NO_ERROR) { +                delete group; +                delete package;                  return (mError=err);              } @@ -3657,6 +3705,8 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,              if (err < NO_ERROR) {                  return (mError=err);              } +            group->basePackage = package; +                          mPackageMap[id] = (uint8_t)idx;          } else {              group = mPackageGroups.itemAt(idx-1); @@ -3664,10 +3714,6 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,                  return (mError=UNKNOWN_ERROR);              }          } -        package = new Package(header, pkg); -        if (package == NULL) { -            return (mError=NO_MEMORY); -        }          err = group->packages.add(package);          if (err < NO_ERROR) {              return (mError=err); | 
