2 // Copyright 2006 The Android Open Source Project 
   4 // Build resource files from raw assets. 
   7 #include "AaptAssets.h" 
   8 #include "StringPool.h" 
  10 #include "ResourceTable.h" 
  15 // ========================================================================== 
  16 // ========================================================================== 
  17 // ========================================================================== 
  29     status_t 
parsePackage(const sp
<AaptGroup
>& grp
); 
  32 // ========================================================================== 
  33 // ========================================================================== 
  34 // ========================================================================== 
  36 static String8 
parseResourceName(const String8
& leaf
) 
  38     const char* firstDot 
= strchr(leaf
.string(), '.'); 
  39     const char* str 
= leaf
.string(); 
  42         return String8(str
, firstDot
-str
); 
  48 class ResourceTypeSet 
: public RefBase
, 
  49                         public KeyedVector
<String8
,sp
<AaptGroup
> > 
  55 ResourceTypeSet::ResourceTypeSet() 
  57      KeyedVector
<String8
,sp
<AaptGroup
> >() 
  61 class ResourceDirIterator
 
  64     ResourceDirIterator(const sp
<ResourceTypeSet
>& set
, const String8
& resType
) 
  65         : mResType(resType
), mSet(set
), mSetPos(0), mGroupPos(0) 
  69     inline const sp
<AaptGroup
>& getGroup() const { return mGroup
; } 
  70     inline const sp
<AaptFile
>& getFile() const { return mFile
; } 
  72     inline const String8
& getBaseName() const { return mBaseName
; } 
  73     inline const String8
& getLeafName() const { return mLeafName
; } 
  74     inline String8 
getPath() const { return mPath
; } 
  75     inline const ResTable_config
& getParams() const { return mParams
; } 
  87             // Try to get next file in this current group. 
  88             if (mGroup 
!= NULL 
&& mGroupPos 
< mGroup
->getFiles().size()) { 
  90                 file 
= group
->getFiles().valueAt(mGroupPos
++); 
  92             // Try to get the next group/file in this directory 
  93             } else if (mSetPos 
< mSet
->size()) { 
  94                 mGroup 
= group 
= mSet
->valueAt(mSetPos
++); 
  95                 if (group
->getFiles().size() < 1) { 
  98                 file 
= group
->getFiles().valueAt(0); 
 108             String8 
leaf(group
->getLeaf()); 
 109             mLeafName 
= String8(leaf
); 
 110             mParams 
= file
->getGroupEntry().toParams(); 
 111             NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d density=%d touch=%d key=%d inp=%d nav=%d\n", 
 112                    group
->getPath().string(), mParams
.mcc
, mParams
.mnc
, 
 113                    mParams
.language
[0] ? mParams
.language
[0] : '-', 
 114                    mParams
.language
[1] ? mParams
.language
[1] : '-', 
 115                    mParams
.country
[0] ? mParams
.country
[0] : '-', 
 116                    mParams
.country
[1] ? mParams
.country
[1] : '-', 
 118                    mParams
.density
, mParams
.touchscreen
, mParams
.keyboard
, 
 119                    mParams
.inputFlags
, mParams
.navigation
)); 
 121             mPath
.appendPath(file
->getGroupEntry().toDirName(mResType
)); 
 122             mPath
.appendPath(leaf
); 
 123             mBaseName 
= parseResourceName(leaf
); 
 124             if (mBaseName 
== "") { 
 125                 fprintf(stderr
, "Error: malformed resource filename %s\n", 
 126                         file
->getPrintableSource().string()); 
 127                 return UNKNOWN_ERROR
; 
 130             NOISY(printf("file name=%s\n", mBaseName
.string())); 
 139     const sp
<ResourceTypeSet
> mSet
; 
 142     sp
<AaptGroup
> mGroup
; 
 149     ResTable_config mParams
; 
 152 // ========================================================================== 
 153 // ========================================================================== 
 154 // ========================================================================== 
 156 bool isValidResourceType(const String8
& type
) 
 158     return type 
== "anim" || type 
== "drawable" || type 
== "layout" 
 159         || type 
== "values" || type 
== "xml" || type 
== "raw" 
 160         || type 
== "color" || type 
== "menu"; 
 163 static sp
<AaptFile
> getResourceFile(const sp
<AaptAssets
>& assets
, bool makeIfNecessary
=true) 
 165     sp
<AaptGroup
> group 
= assets
->getFiles().valueFor(String8("resources.arsc")); 
 168         file 
= group
->getFiles().valueFor(AaptGroupEntry()); 
 174     if (!makeIfNecessary
) { 
 177     return assets
->addFile(String8("resources.arsc"), AaptGroupEntry(), String8(), 
 181 static status_t 
parsePackage(const sp
<AaptAssets
>& assets
, const sp
<AaptGroup
>& grp
) 
 183     if (grp
->getFiles().size() != 1) { 
 184         fprintf(stderr
, "WARNING: Multiple AndroidManifest.xml files found, using %s\n", 
 185                 grp
->getFiles().valueAt(0)->getPrintableSource().string()); 
 188     sp
<AaptFile
> file 
= grp
->getFiles().valueAt(0); 
 191     status_t err 
= parseXMLResource(file
, &block
); 
 192     if (err 
!= NO_ERROR
) { 
 195     //printXMLBlock(&block); 
 197     ResXMLTree::event_code_t code
; 
 198     while ((code
=block
.next()) != ResXMLTree::START_TAG
 
 199            && code 
!= ResXMLTree::END_DOCUMENT
 
 200            && code 
!= ResXMLTree::BAD_DOCUMENT
) { 
 204     if (code 
!= ResXMLTree::START_TAG
) { 
 205         fprintf(stderr
, "%s:%d: No start tag found\n", 
 206                 file
->getPrintableSource().string(), block
.getLineNumber()); 
 207         return UNKNOWN_ERROR
; 
 209     if (strcmp16(block
.getElementName(&len
), String16("manifest").string()) != 0) { 
 210         fprintf(stderr
, "%s:%d: Invalid start tag %s, expected <manifest>\n", 
 211                 file
->getPrintableSource().string(), block
.getLineNumber(), 
 212                 String8(block
.getElementName(&len
)).string()); 
 213         return UNKNOWN_ERROR
; 
 216     ssize_t nameIndex 
= block
.indexOfAttribute(NULL
, "package"); 
 218         fprintf(stderr
, "%s:%d: <manifest> does not have package attribute.\n", 
 219                 file
->getPrintableSource().string(), block
.getLineNumber()); 
 220         return UNKNOWN_ERROR
; 
 223     assets
->setPackage(String8(block
.getAttributeStringValue(nameIndex
, &len
))); 
 228 // ========================================================================== 
 229 // ========================================================================== 
 230 // ========================================================================== 
 232 static status_t 
makeFileResources(Bundle
* bundle
, const sp
<AaptAssets
>& assets
, 
 233                                   ResourceTable
* table
, 
 234                                   const sp
<ResourceTypeSet
>& set
, 
 237     String8 
type8(resType
); 
 238     String16 
type16(resType
); 
 240     bool hasErrors 
= false; 
 242     ResourceDirIterator 
it(set
, String8(resType
)); 
 244     while ((res
=it
.next()) == NO_ERROR
) { 
 245         if (bundle
->getVerbose()) { 
 246             printf("    (new resource id %s from %s)\n", 
 247                    it
.getBaseName().string(), it
.getFile()->getPrintableSource().string()); 
 249         String16 
baseName(it
.getBaseName()); 
 250         const char16_t* str 
= baseName
.string(); 
 251         const char16_t* const end 
= str 
+ baseName
.size(); 
 253             if (!((*str 
>= 'a' && *str 
<= 'z') 
 254                     || (*str 
>= '0' && *str 
<= '9') 
 255                     || *str 
== '_' || *str 
== '.')) { 
 256                 fprintf(stderr
, "%s: Invalid file name: must contain only [a-z0-9_.]\n", 
 257                         it
.getPath().string()); 
 262         String8 resPath 
= it
.getPath(); 
 263         resPath
.convertToResPath(); 
 264         table
->addEntry(SourcePos(it
.getPath(), 0), String16(assets
->getPackage()), 
 270         assets
->addResource(it
.getLeafName(), resPath
, it
.getFile(), type8
); 
 273     return hasErrors 
? UNKNOWN_ERROR 
: NO_ERROR
; 
 276 static status_t 
preProcessImages(Bundle
* bundle
, const sp
<AaptAssets
>& assets
, 
 277                           const sp
<ResourceTypeSet
>& set
) 
 279     ResourceDirIterator 
it(set
, String8("drawable")); 
 280     Vector
<sp
<AaptFile
> > newNameFiles
; 
 281     Vector
<String8
> newNamePaths
; 
 283     while ((res
=it
.next()) == NO_ERROR
) { 
 284         res 
= preProcessImage(bundle
, assets
, it
.getFile(), NULL
); 
 285         if (res 
!= NO_ERROR
) { 
 293 status_t 
postProcessImages(const sp
<AaptAssets
>& assets
, 
 294                            ResourceTable
* table
, 
 295                            const sp
<ResourceTypeSet
>& set
) 
 297     ResourceDirIterator 
it(set
, String8("drawable")); 
 299     while ((res
=it
.next()) == NO_ERROR
) { 
 300         res 
= postProcessImage(assets
, table
, it
.getFile()); 
 301         if (res 
!= NO_ERROR
) { 
 306     return res 
< NO_ERROR 
? res 
: (status_t
)NO_ERROR
; 
 309 static void collect_files(const sp
<AaptDir
>& dir
, 
 310         KeyedVector
<String8
, sp
<ResourceTypeSet
> >* resources
) 
 312     const DefaultKeyedVector
<String8
, sp
<AaptGroup
> >& groups 
= dir
->getFiles(); 
 313     int N 
= groups
.size(); 
 314     for (int i
=0; i
<N
; i
++) { 
 315         String8 leafName 
= groups
.keyAt(i
); 
 316         const sp
<AaptGroup
>& group 
= groups
.valueAt(i
); 
 318         const DefaultKeyedVector
<AaptGroupEntry
, sp
<AaptFile
> >& files
 
 321         if (files
.size() == 0) { 
 325         String8 resType 
= files
.valueAt(0)->getResourceType(); 
 327         ssize_t index 
= resources
->indexOfKey(resType
); 
 330             sp
<ResourceTypeSet
> set 
= new ResourceTypeSet(); 
 331             set
->add(leafName
, group
); 
 332             resources
->add(resType
, set
); 
 334             sp
<ResourceTypeSet
> set 
= resources
->valueAt(index
); 
 335             index 
= set
->indexOfKey(leafName
); 
 337                 set
->add(leafName
, group
); 
 339                 sp
<AaptGroup
> existingGroup 
= set
->valueAt(index
); 
 340                 int M 
= files
.size(); 
 341                 for (int j
=0; j
<M
; j
++) { 
 342                     existingGroup
->addFile(files
.valueAt(j
)); 
 349 static void collect_files(const sp
<AaptAssets
>& ass
, 
 350         KeyedVector
<String8
, sp
<ResourceTypeSet
> >* resources
) 
 352     const Vector
<sp
<AaptDir
> >& dirs 
= ass
->resDirs(); 
 355     for (int i
=0; i
<N
; i
++) { 
 356         sp
<AaptDir
> d 
= dirs
.itemAt(i
); 
 357         collect_files(d
, resources
); 
 359         // don't try to include the res dir 
 360         ass
->removeDir(d
->getLeaf()); 
 367     ATTR_LEADING_SPACES 
= -3, 
 368     ATTR_TRAILING_SPACES 
= -4 
 370 static int validateAttr(const String8
& path
, const ResXMLParser
& parser
, 
 371         const char* ns
, const char* attr
, const char* validChars
, bool required
) 
 375     ssize_t index 
= parser
.indexOfAttribute(ns
, attr
); 
 377     if (index 
>= 0 && (str
=parser
.getAttributeStringValue(index
, &len
)) != NULL
) { 
 379             for (size_t i
=0; i
<len
; i
++) { 
 381                 const char* p 
= validChars
; 
 391                     fprintf(stderr
, "%s:%d: Tag <%s> attribute %s has invalid character '%c'.\n", 
 392                             path
.string(), parser
.getLineNumber(), 
 393                             String8(parser
.getElementName(&len
)).string(), attr
, (char)str
[i
]); 
 399             fprintf(stderr
, "%s:%d: Tag <%s> attribute %s can not start with a space.\n", 
 400                     path
.string(), parser
.getLineNumber(), 
 401                     String8(parser
.getElementName(&len
)).string(), attr
); 
 402             return ATTR_LEADING_SPACES
; 
 404         if (str
[len
-1] == ' ') { 
 405             fprintf(stderr
, "%s:%d: Tag <%s> attribute %s can not end with a space.\n", 
 406                     path
.string(), parser
.getLineNumber(), 
 407                     String8(parser
.getElementName(&len
)).string(), attr
); 
 408             return ATTR_TRAILING_SPACES
; 
 413         fprintf(stderr
, "%s:%d: Tag <%s> missing required attribute %s.\n", 
 414                 path
.string(), parser
.getLineNumber(), 
 415                 String8(parser
.getElementName(&len
)).string(), attr
); 
 416         return ATTR_NOT_FOUND
; 
 421 static void checkForIds(const String8
& path
, ResXMLParser
& parser
) 
 423     ResXMLTree::event_code_t code
; 
 424     while ((code
=parser
.next()) != ResXMLTree::END_DOCUMENT
 
 425            && code 
> ResXMLTree::BAD_DOCUMENT
) { 
 426         if (code 
== ResXMLTree::START_TAG
) { 
 427             ssize_t index 
= parser
.indexOfAttribute(NULL
, "id"); 
 429                 fprintf(stderr
, "%s:%d: WARNING: found plain 'id' attribute; did you mean the new 'android:id' name?\n", 
 430                         path
.string(), parser
.getLineNumber()); 
 436 static void applyFileOverlay(const sp
<AaptAssets
>& assets
,  
 437                              const sp
<ResourceTypeSet
>& baseSet
, 
 440     // Replace any base level files in this category with any found from the overlay 
 441     // Also add any found only in the overlay. 
 442     sp
<AaptAssets
> overlay 
= assets
->getOverlay(); 
 443     String8 
resTypeString(resType
); 
 445     // work through the linked list of overlays 
 446     while (overlay
.get()) { 
 447         KeyedVector
<String8
, sp
<ResourceTypeSet
> >* overlayRes 
= overlay
->getResources(); 
 449         // get the overlay resources of the requested type 
 450         ssize_t index 
= overlayRes
->indexOfKey(resTypeString
); 
 452             sp
<ResourceTypeSet
> overlaySet 
= overlayRes
->valueAt(index
); 
 454             // for each of the resources, check for a match in the previously built 
 455             // non-overlay "baseset". 
 456             size_t overlayCount 
= overlaySet
->size(); 
 457             for (size_t overlayIndex
=0; overlayIndex
<overlayCount
; overlayIndex
++) { 
 458                 size_t baseIndex 
= baseSet
->indexOfKey(overlaySet
->keyAt(overlayIndex
)); 
 459                 if (baseIndex 
!= UNKNOWN_ERROR
) { 
 460                     // look for same flavor.  For a given file (strings.xml, for example) 
 461                     // there may be a locale specific or other flavors - we want to match 
 463                     sp
<AaptGroup
> overlayGroup 
= overlaySet
->valueAt(overlayIndex
); 
 464                     sp
<AaptGroup
> baseGroup 
= baseSet
->valueAt(baseIndex
); 
 466                     DefaultKeyedVector
<AaptGroupEntry
, sp
<AaptFile
> > baseFiles 
=  
 467                             baseGroup
->getFiles(); 
 468                     DefaultKeyedVector
<AaptGroupEntry
, sp
<AaptFile
> > overlayFiles 
=  
 469                             overlayGroup
->getFiles(); 
 470                     size_t overlayGroupSize 
= overlayFiles
.size(); 
 471                     for (size_t overlayGroupIndex 
= 0;  
 472                             overlayGroupIndex
<overlayGroupSize
;  
 473                             overlayGroupIndex
++) { 
 474                         size_t baseFileIndex 
=  
 475                                 baseFiles
.indexOfKey(overlayFiles
.keyAt(overlayGroupIndex
)); 
 476                         if(baseFileIndex 
< UNKNOWN_ERROR
) { 
 477                             baseGroup
->removeFile(baseFileIndex
); 
 479                             // didn't find a match fall through and add it.. 
 481                         baseGroup
->addFile(overlayFiles
.valueAt(overlayGroupIndex
)); 
 484                     // this group doesn't exist (a file that's only in the overlay) 
 486                     baseSet
->add(overlaySet
->keyAt(overlayIndex
), 
 487                                  overlaySet
->valueAt(overlayIndex
)); 
 490             // this overlay didn't have resources for this type 
 493         overlay 
= overlay
->getOverlay(); 
 498 #define ASSIGN_IT(n) \ 
 500             ssize_t index = resources->indexOfKey(String8(#n)); \ 
 502                 n ## s = resources->valueAt(index); \ 
 506 status_t 
buildResources(Bundle
* bundle
, const sp
<AaptAssets
>& assets
) 
 508     // First, look for a package file to parse.  This is required to 
 509     // be able to generate the resource information. 
 510     sp
<AaptGroup
> androidManifestFile 
= 
 511             assets
->getFiles().valueFor(String8("AndroidManifest.xml")); 
 512     if (androidManifestFile 
== NULL
) { 
 513         fprintf(stderr
, "ERROR: No AndroidManifest.xml file found.\n"); 
 514         return UNKNOWN_ERROR
; 
 517     status_t err 
= parsePackage(assets
, androidManifestFile
); 
 518     if (err 
!= NO_ERROR
) { 
 522     NOISY(printf("Creating resources for package %s\n", 
 523                  assets
->getPackage().string())); 
 525     ResourceTable 
table(bundle
, String16(assets
->getPackage())); 
 526     err 
= table
.addIncludedResources(bundle
, assets
); 
 527     if (err 
!= NO_ERROR
) { 
 531     NOISY(printf("Found %d included resource packages\n", (int)table
.size())); 
 533     // -------------------------------------------------------------- 
 534     // First, gather all resource information. 
 535     // -------------------------------------------------------------- 
 537     // resType -> leafName -> group 
 538     KeyedVector
<String8
, sp
<ResourceTypeSet
> > *resources 
=  
 539             new KeyedVector
<String8
, sp
<ResourceTypeSet
> >; 
 540     collect_files(assets
, resources
); 
 542     sp
<ResourceTypeSet
> drawables
; 
 543     sp
<ResourceTypeSet
> layouts
; 
 544     sp
<ResourceTypeSet
> anims
; 
 545     sp
<ResourceTypeSet
> xmls
; 
 546     sp
<ResourceTypeSet
> raws
; 
 547     sp
<ResourceTypeSet
> colors
; 
 548     sp
<ResourceTypeSet
> menus
; 
 558     assets
->setResources(resources
); 
 559     // now go through any resource overlays and collect their files 
 560     sp
<AaptAssets
> current 
= assets
->getOverlay(); 
 561     while(current
.get()) { 
 562         KeyedVector
<String8
, sp
<ResourceTypeSet
> > *resources 
=  
 563                 new KeyedVector
<String8
, sp
<ResourceTypeSet
> >; 
 564         current
->setResources(resources
); 
 565         collect_files(current
, resources
); 
 566         current 
= current
->getOverlay(); 
 568     // apply the overlay files to the base set 
 569     applyFileOverlay(assets
, drawables
, "drawable"); 
 570     applyFileOverlay(assets
, layouts
, "layout"); 
 571     applyFileOverlay(assets
, anims
, "anim"); 
 572     applyFileOverlay(assets
, xmls
, "xml"); 
 573     applyFileOverlay(assets
, raws
, "raw"); 
 574     applyFileOverlay(assets
, colors
, "color"); 
 575     applyFileOverlay(assets
, menus
, "menu"); 
 577     bool hasErrors 
= false; 
 579     if (drawables 
!= NULL
) { 
 580         err 
= preProcessImages(bundle
, assets
, drawables
); 
 581         if (err 
== NO_ERROR
) { 
 582             err 
= makeFileResources(bundle
, assets
, &table
, drawables
, "drawable"); 
 583             if (err 
!= NO_ERROR
) { 
 591     if (layouts 
!= NULL
) { 
 592         err 
= makeFileResources(bundle
, assets
, &table
, layouts
, "layout"); 
 593         if (err 
!= NO_ERROR
) { 
 599         err 
= makeFileResources(bundle
, assets
, &table
, anims
, "anim"); 
 600         if (err 
!= NO_ERROR
) { 
 606         err 
= makeFileResources(bundle
, assets
, &table
, xmls
, "xml"); 
 607         if (err 
!= NO_ERROR
) { 
 613         err 
= makeFileResources(bundle
, assets
, &table
, raws
, "raw"); 
 614         if (err 
!= NO_ERROR
) { 
 621     while(current
.get()) { 
 622         KeyedVector
<String8
, sp
<ResourceTypeSet
> > *resources 
=  
 623                 current
->getResources(); 
 625         ssize_t index 
= resources
->indexOfKey(String8("values")); 
 627             ResourceDirIterator 
it(resources
->valueAt(index
), String8("values")); 
 629             while ((res
=it
.next()) == NO_ERROR
) { 
 630                 sp
<AaptFile
> file 
= it
.getFile(); 
 631                 res 
= compileResourceFile(bundle
, assets
, file
, it
.getParams(),  
 632                                           (current
!=assets
), &table
); 
 633                 if (res 
!= NO_ERROR
) { 
 638         current 
= current
->getOverlay(); 
 641     if (colors 
!= NULL
) { 
 642         err 
= makeFileResources(bundle
, assets
, &table
, colors
, "color"); 
 643         if (err 
!= NO_ERROR
) { 
 649         err 
= makeFileResources(bundle
, assets
, &table
, menus
, "menu"); 
 650         if (err 
!= NO_ERROR
) { 
 655     // -------------------------------------------------------------------- 
 656     // Assignment of resource IDs and initial generation of resource table. 
 657     // -------------------------------------------------------------------- 
 659     if (table
.hasResources()) { 
 660         sp
<AaptFile
> resFile(getResourceFile(assets
)); 
 661         if (resFile 
== NULL
) { 
 662             fprintf(stderr
, "Error: unable to generate entry for resource data\n"); 
 663             return UNKNOWN_ERROR
; 
 666         err 
= table
.assignResourceIds(); 
 667         if (err 
< NO_ERROR
) { 
 672     // -------------------------------------------------------------- 
 673     // Finally, we can now we can compile XML files, which may reference 
 675     // -------------------------------------------------------------- 
 677     if (layouts 
!= NULL
) { 
 678         ResourceDirIterator 
it(layouts
, String8("layout")); 
 679         while ((err
=it
.next()) == NO_ERROR
) { 
 680             String8 src 
= it
.getFile()->getPrintableSource(); 
 681             err 
= compileXmlFile(assets
, it
.getFile(), &table
); 
 682             if (err 
== NO_ERROR
) { 
 684                 block
.setTo(it
.getFile()->getData(), it
.getFile()->getSize(), true); 
 685                 checkForIds(src
, block
); 
 691         if (err 
< NO_ERROR
) { 
 698         ResourceDirIterator 
it(anims
, String8("anim")); 
 699         while ((err
=it
.next()) == NO_ERROR
) { 
 700             err 
= compileXmlFile(assets
, it
.getFile(), &table
); 
 701             if (err 
!= NO_ERROR
) { 
 706         if (err 
< NO_ERROR
) { 
 713         ResourceDirIterator 
it(xmls
, String8("xml")); 
 714         while ((err
=it
.next()) == NO_ERROR
) { 
 715             err 
= compileXmlFile(assets
, it
.getFile(), &table
); 
 716             if (err 
!= NO_ERROR
) { 
 721         if (err 
< NO_ERROR
) { 
 727     if (drawables 
!= NULL
) { 
 728         err 
= postProcessImages(assets
, &table
, drawables
); 
 729         if (err 
!= NO_ERROR
) { 
 734     if (colors 
!= NULL
) { 
 735         ResourceDirIterator 
it(colors
, String8("color")); 
 736         while ((err
=it
.next()) == NO_ERROR
) { 
 737           err 
= compileXmlFile(assets
, it
.getFile(), &table
); 
 738             if (err 
!= NO_ERROR
) { 
 743         if (err 
< NO_ERROR
) { 
 750         ResourceDirIterator 
it(menus
, String8("menu")); 
 751         while ((err
=it
.next()) == NO_ERROR
) { 
 752             String8 src 
= it
.getFile()->getPrintableSource(); 
 753             err 
= compileXmlFile(assets
, it
.getFile(), &table
); 
 754             if (err 
!= NO_ERROR
) { 
 758             block
.setTo(it
.getFile()->getData(), it
.getFile()->getSize(), true); 
 759             checkForIds(src
, block
); 
 762         if (err 
< NO_ERROR
) { 
 768     const sp
<AaptFile
> manifestFile(androidManifestFile
->getFiles().valueAt(0)); 
 769     String8 
manifestPath(manifestFile
->getPrintableSource()); 
 771     // Perform a basic validation of the manifest file.  This time we 
 772     // parse it with the comments intact, so that we can use them to 
 773     // generate java docs...  so we are not going to write this one 
 774     // back out to the final manifest data. 
 775     err 
= compileXmlFile(assets
, manifestFile
, &table
, 
 776             XML_COMPILE_ASSIGN_ATTRIBUTE_IDS
 
 777             | XML_COMPILE_STRIP_WHITESPACE 
| XML_COMPILE_STRIP_RAW_VALUES
); 
 778     if (err 
< NO_ERROR
) { 
 782     block
.setTo(manifestFile
->getData(), manifestFile
->getSize(), true); 
 783     String16 
manifest16("manifest"); 
 784     String16 
permission16("permission"); 
 785     String16 
permission_group16("permission-group"); 
 786     String16 
uses_permission16("uses-permission"); 
 787     String16 
instrumentation16("instrumentation"); 
 788     String16 
application16("application"); 
 789     String16 
provider16("provider"); 
 790     String16 
service16("service"); 
 791     String16 
receiver16("receiver"); 
 792     String16 
activity16("activity"); 
 793     String16 
action16("action"); 
 794     String16 
category16("category"); 
 795     String16 
data16("scheme"); 
 796     const char* packageIdentChars 
= "abcdefghijklmnopqrstuvwxyz" 
 797         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789"; 
 798     const char* packageIdentCharsWithTheStupid 
= "abcdefghijklmnopqrstuvwxyz" 
 799         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789-"; 
 800     const char* classIdentChars 
= "abcdefghijklmnopqrstuvwxyz" 
 801         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789$"; 
 802     const char* processIdentChars 
= "abcdefghijklmnopqrstuvwxyz" 
 803         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789:"; 
 804     const char* authoritiesIdentChars 
= "abcdefghijklmnopqrstuvwxyz" 
 805         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789-:;"; 
 806     const char* typeIdentChars 
= "abcdefghijklmnopqrstuvwxyz" 
 807         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789:-/*+"; 
 808     const char* schemeIdentChars 
= "abcdefghijklmnopqrstuvwxyz" 
 809         "ABCDEFGHIJKLMNOPQRSTUVWXYZ._0123456789-"; 
 810     ResXMLTree::event_code_t code
; 
 811     sp
<AaptSymbols
> permissionSymbols
; 
 812     sp
<AaptSymbols
> permissionGroupSymbols
; 
 813     while ((code
=block
.next()) != ResXMLTree::END_DOCUMENT
 
 814            && code 
> ResXMLTree::BAD_DOCUMENT
) { 
 815         if (code 
== ResXMLTree::START_TAG
) { 
 817             if (block
.getElementNamespace(&len
) != NULL
) { 
 820             if (strcmp16(block
.getElementName(&len
), manifest16
.string()) == 0) { 
 821                 if (validateAttr(manifestPath
, block
, NULL
, "package", 
 822                                  packageIdentChars
, true) != ATTR_OKAY
) { 
 825             } else if (strcmp16(block
.getElementName(&len
), permission16
.string()) == 0 
 826                     || strcmp16(block
.getElementName(&len
), permission_group16
.string()) == 0) { 
 827                 const bool isGroup 
= strcmp16(block
.getElementName(&len
), 
 828                         permission_group16
.string()) == 0; 
 829                 if (validateAttr(manifestPath
, block
, RESOURCES_ANDROID_NAMESPACE
, "name", 
 830                                  isGroup 
? packageIdentCharsWithTheStupid
 
 831                                  : packageIdentChars
, true) != ATTR_OKAY
) { 
 834                 SourcePos 
srcPos(manifestPath
, block
.getLineNumber()); 
 835                 sp
<AaptSymbols
> syms
; 
 837                     syms 
= permissionSymbols
; 
 839                         sp
<AaptSymbols
> symbols 
= 
 840                                 assets
->getSymbolsFor(String8("Manifest")); 
 841                         syms 
= permissionSymbols 
= symbols
->addNestedSymbol( 
 842                                 String8("permission"), srcPos
); 
 845                     syms 
= permissionGroupSymbols
; 
 847                         sp
<AaptSymbols
> symbols 
= 
 848                                 assets
->getSymbolsFor(String8("Manifest")); 
 849                         syms 
= permissionGroupSymbols 
= symbols
->addNestedSymbol( 
 850                                 String8("permission_group"), srcPos
); 
 854                 ssize_t index 
= block
.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE
, "name"); 
 855                 const uint16_t* id 
= block
.getAttributeStringValue(index
, &len
); 
 857                     fprintf(stderr
, "%s:%d: missing name attribute in element <%s>.\n",  
 858                             manifestPath
.string(), block
.getLineNumber(), 
 859                             String8(block
.getElementName(&len
)).string()); 
 864                 char* p 
= idStr
.lockBuffer(idStr
.size()); 
 865                 char* e 
= p 
+ idStr
.size(); 
 866                 bool begins_with_digit 
= true;  // init to true so an empty string fails 
 869                     if (*e 
>= '0' && *e 
<= '9') { 
 870                       begins_with_digit 
= true; 
 873                     if ((*e 
>= 'a' && *e 
<= 'z') || 
 874                         (*e 
>= 'A' && *e 
<= 'Z') || 
 876                       begins_with_digit 
= false; 
 879                     if (isGroup 
&& (*e 
== '-')) { 
 881                         begins_with_digit 
= false; 
 887                 idStr
.unlockBuffer(); 
 888                 // verify that we stopped because we hit a period or 
 889                 // the beginning of the string, and that the 
 890                 // identifier didn't begin with a digit. 
 891                 if (begins_with_digit 
|| (e 
!= p 
&& *(e
-1) != '.')) { 
 893                           "%s:%d: Permission name <%s> is not a valid Java symbol\n", 
 894                           manifestPath
.string(), block
.getLineNumber(), idStr
.string()); 
 897                 syms
->addStringSymbol(String8(e
), idStr
, srcPos
); 
 898                 const uint16_t* cmt 
= block
.getComment(&len
); 
 899                 if (cmt 
!= NULL 
&& *cmt 
!= 0) { 
 900                     //printf("Comment of %s: %s\n", String8(e).string(), 
 901                     //        String8(cmt).string()); 
 902                     syms
->appendComment(String8(e
), String16(cmt
), srcPos
); 
 904                     //printf("No comment for %s\n", String8(e).string()); 
 906                 syms
->makeSymbolPublic(String8(e
), srcPos
); 
 907             } else if (strcmp16(block
.getElementName(&len
), uses_permission16
.string()) == 0) { 
 908                 if (validateAttr(manifestPath
, block
, RESOURCES_ANDROID_NAMESPACE
, "name", 
 909                                  packageIdentChars
, true) != ATTR_OKAY
) { 
 912             } else if (strcmp16(block
.getElementName(&len
), instrumentation16
.string()) == 0) { 
 913                 if (validateAttr(manifestPath
, block
, RESOURCES_ANDROID_NAMESPACE
, "name", 
 914                                  classIdentChars
, true) != ATTR_OKAY
) { 
 917                 if (validateAttr(manifestPath
, block
, 
 918                                  RESOURCES_ANDROID_NAMESPACE
, "targetPackage", 
 919                                  packageIdentChars
, true) != ATTR_OKAY
) { 
 922             } else if (strcmp16(block
.getElementName(&len
), application16
.string()) == 0) { 
 923                 if (validateAttr(manifestPath
, block
, RESOURCES_ANDROID_NAMESPACE
, "name", 
 924                                  classIdentChars
, false) != ATTR_OKAY
) { 
 927                 if (validateAttr(manifestPath
, block
, 
 928                                  RESOURCES_ANDROID_NAMESPACE
, "permission", 
 929                                  packageIdentChars
, false) != ATTR_OKAY
) { 
 932                 if (validateAttr(manifestPath
, block
, 
 933                                  RESOURCES_ANDROID_NAMESPACE
, "process", 
 934                                  processIdentChars
, false) != ATTR_OKAY
) { 
 937                 if (validateAttr(manifestPath
, block
, 
 938                                  RESOURCES_ANDROID_NAMESPACE
, "taskAffinity", 
 939                                  processIdentChars
, false) != ATTR_OKAY
) { 
 942             } else if (strcmp16(block
.getElementName(&len
), provider16
.string()) == 0) { 
 943                 if (validateAttr(manifestPath
, block
, RESOURCES_ANDROID_NAMESPACE
, "name", 
 944                                  classIdentChars
, true) != ATTR_OKAY
) { 
 947                 if (validateAttr(manifestPath
, block
, 
 948                                  RESOURCES_ANDROID_NAMESPACE
, "authorities", 
 949                                  authoritiesIdentChars
, true) != ATTR_OKAY
) { 
 952                 if (validateAttr(manifestPath
, block
, 
 953                                  RESOURCES_ANDROID_NAMESPACE
, "permission", 
 954                                  packageIdentChars
, false) != ATTR_OKAY
) { 
 957                 if (validateAttr(manifestPath
, block
, 
 958                                  RESOURCES_ANDROID_NAMESPACE
, "process", 
 959                                  processIdentChars
, false) != ATTR_OKAY
) { 
 962             } else if (strcmp16(block
.getElementName(&len
), service16
.string()) == 0 
 963                        || strcmp16(block
.getElementName(&len
), receiver16
.string()) == 0 
 964                        || strcmp16(block
.getElementName(&len
), activity16
.string()) == 0) { 
 965                 if (validateAttr(manifestPath
, block
, RESOURCES_ANDROID_NAMESPACE
, "name", 
 966                                  classIdentChars
, true) != ATTR_OKAY
) { 
 969                 if (validateAttr(manifestPath
, block
, 
 970                                  RESOURCES_ANDROID_NAMESPACE
, "permission", 
 971                                  packageIdentChars
, false) != ATTR_OKAY
) { 
 974                 if (validateAttr(manifestPath
, block
, 
 975                                  RESOURCES_ANDROID_NAMESPACE
, "process", 
 976                                  processIdentChars
, false) != ATTR_OKAY
) { 
 979                 if (validateAttr(manifestPath
, block
, 
 980                                  RESOURCES_ANDROID_NAMESPACE
, "taskAffinity", 
 981                                  processIdentChars
, false) != ATTR_OKAY
) { 
 984             } else if (strcmp16(block
.getElementName(&len
), action16
.string()) == 0 
 985                        || strcmp16(block
.getElementName(&len
), category16
.string()) == 0) { 
 986                 if (validateAttr(manifestPath
, block
, 
 987                                  RESOURCES_ANDROID_NAMESPACE
, "name", 
 988                                  packageIdentChars
, true) != ATTR_OKAY
) { 
 991             } else if (strcmp16(block
.getElementName(&len
), data16
.string()) == 0) { 
 992                 if (validateAttr(manifestPath
, block
, 
 993                                  RESOURCES_ANDROID_NAMESPACE
, "mimeType", 
 994                                  typeIdentChars
, true) != ATTR_OKAY
) { 
 997                 if (validateAttr(manifestPath
, block
, 
 998                                  RESOURCES_ANDROID_NAMESPACE
, "scheme", 
 999                                  schemeIdentChars
, true) != ATTR_OKAY
) { 
1006     if (table
.validateLocalizations()) { 
1011         return UNKNOWN_ERROR
; 
1014     // Generate final compiled manifest file. 
1015     manifestFile
->clearData(); 
1016     err 
= compileXmlFile(assets
, manifestFile
, &table
); 
1017     if (err 
< NO_ERROR
) { 
1022     //printXMLBlock(&block); 
1024     // -------------------------------------------------------------- 
1025     // Generate the final resource table. 
1026     // Re-flatten because we may have added new resource IDs 
1027     // -------------------------------------------------------------- 
1029     if (table
.hasResources()) { 
1030         sp
<AaptSymbols
> symbols 
= assets
->getSymbolsFor(String8("R")); 
1031         err 
= table
.addSymbols(symbols
); 
1032         if (err 
< NO_ERROR
) { 
1036         sp
<AaptFile
> resFile(getResourceFile(assets
)); 
1037         if (resFile 
== NULL
) { 
1038             fprintf(stderr
, "Error: unable to generate entry for resource data\n"); 
1039             return UNKNOWN_ERROR
; 
1042         err 
= table
.flatten(bundle
, resFile
); 
1043         if (err 
< NO_ERROR
) { 
1047         if (bundle
->getPublicOutputFile()) { 
1048             FILE* fp 
= fopen(bundle
->getPublicOutputFile(), "w+"); 
1050                 fprintf(stderr
, "ERROR: Unable to open public definitions output file %s: %s\n", 
1051                         (const char*)bundle
->getPublicOutputFile(), strerror(errno
)); 
1052                 return UNKNOWN_ERROR
; 
1054             if (bundle
->getVerbose()) { 
1055                 printf("  Writing public definitions to %s.\n", bundle
->getPublicOutputFile()); 
1057             table
.writePublicDefinitions(String16(assets
->getPackage()), fp
); 
1062               rt
.add(resFile
->getData(), resFile
->getSize(), NULL
); 
1063               printf("Generated resources:\n"); 
1067         // These resources are now considered to be a part of the included 
1068         // resources, for others to reference. 
1069         err 
= assets
->addIncludedResources(resFile
); 
1070         if (err 
< NO_ERROR
) { 
1071             fprintf(stderr
, "ERROR: Unable to parse generated resources, aborting.\n"); 
1079 static const char* getIndentSpace(int indent
) 
1081 static const char whitespace
[] = 
1084     return whitespace 
+ sizeof(whitespace
) - 1 - indent
*4; 
1087 static status_t 
fixupSymbol(String16
* inoutSymbol
) 
1089     inoutSymbol
->replaceAll('.', '_'); 
1090     inoutSymbol
->replaceAll(':', '_'); 
1094 static String16 
getAttributeComment(const sp
<AaptAssets
>& assets
, 
1095                                     const String8
& name
, 
1096                                     String16
* outTypeComment 
= NULL
) 
1098     sp
<AaptSymbols
> asym 
= assets
->getSymbolsFor(String8("R")); 
1100         //printf("Got R symbols!\n"); 
1101         asym 
= asym
->getNestedSymbols().valueFor(String8("attr")); 
1103             //printf("Got attrs symbols! comment %s=%s\n", 
1104             //     name.string(), String8(asym->getComment(name)).string()); 
1105             if (outTypeComment 
!= NULL
) { 
1106                 *outTypeComment 
= asym
->getTypeComment(name
); 
1108             return asym
->getComment(name
); 
1114 static status_t 
writeLayoutClasses( 
1115     FILE* fp
, const sp
<AaptAssets
>& assets
, 
1116     const sp
<AaptSymbols
>& symbols
, int indent
, bool includePrivate
) 
1118     const char* indentStr 
= getIndentSpace(indent
); 
1119     if (!includePrivate
) { 
1120         fprintf(fp
, "%s/** @doconly */\n", indentStr
); 
1122     fprintf(fp
, "%spublic static final class styleable {\n", indentStr
); 
1125     String16 
attr16("attr"); 
1126     String16 
package16(assets
->getPackage()); 
1128     indentStr 
= getIndentSpace(indent
); 
1129     bool hasErrors 
= false; 
1132     size_t N 
= symbols
->getNestedSymbols().size(); 
1133     for (i
=0; i
<N
; i
++) { 
1134         sp
<AaptSymbols
> nsymbols 
= symbols
->getNestedSymbols().valueAt(i
); 
1135         String16 
nclassName16(symbols
->getNestedSymbols().keyAt(i
)); 
1136         String8 
realClassName(nclassName16
); 
1137         if (fixupSymbol(&nclassName16
) != NO_ERROR
) { 
1140         String8 
nclassName(nclassName16
); 
1142         SortedVector
<uint32_t> idents
; 
1143         Vector
<uint32_t> origOrder
; 
1144         Vector
<bool> publicFlags
; 
1147         size_t NA 
= nsymbols
->getSymbols().size(); 
1148         for (a
=0; a
<NA
; a
++) { 
1149             const AaptSymbolEntry
& sym(nsymbols
->getSymbols().valueAt(a
)); 
1150             int32_t code 
= sym
.typeCode 
== AaptSymbolEntry::TYPE_INT32
 
1152             bool isPublic 
= true; 
1154                 String16 
name16(sym
.name
); 
1155                 uint32_t typeSpecFlags
; 
1156                 code 
= assets
->getIncludedResources().identifierForName( 
1157                     name16
.string(), name16
.size(), 
1158                     attr16
.string(), attr16
.size(), 
1159                     package16
.string(), package16
.size(), &typeSpecFlags
); 
1161                     fprintf(stderr
, "ERROR: In <declare-styleable> %s, unable to find attribute %s\n", 
1162                             nclassName
.string(), sym
.name
.string()); 
1165                 isPublic 
= (typeSpecFlags
&ResTable_typeSpec::SPEC_PUBLIC
) != 0; 
1168             origOrder
.add(code
); 
1169             publicFlags
.add(isPublic
); 
1174         String16 comment 
= symbols
->getComment(realClassName
); 
1175         fprintf(fp
, "%s/** ", indentStr
); 
1176         if (comment
.size() > 0) { 
1177             fprintf(fp
, "%s\n", String8(comment
).string()); 
1179             fprintf(fp
, "Attributes that can be used with a %s.\n", nclassName
.string()); 
1181         bool hasTable 
= false; 
1182         for (a
=0; a
<NA
; a
++) { 
1183             ssize_t pos 
= idents
.indexOf(origOrder
.itemAt(a
)); 
1188                             "%s   <p>Includes the following attributes:</p>\n" 
1189                             "%s   <table border=\"2\" width=\"85%%\" align=\"center\" frame=\"hsides\" rules=\"all\" cellpadding=\"5\">\n" 
1190                             "%s   <colgroup align=\"left\" />\n" 
1191                             "%s   <colgroup align=\"left\" />\n" 
1192                             "%s   <tr><th>Attribute<th>Summary</tr>\n", 
1199                 const AaptSymbolEntry
& sym 
= nsymbols
->getSymbols().valueAt(a
); 
1200                 if (!publicFlags
.itemAt(a
) && !includePrivate
) { 
1203                 String8 
name8(sym
.name
); 
1204                 String16 
comment(sym
.comment
); 
1205                 if (comment
.size() <= 0) { 
1206                     comment 
= getAttributeComment(assets
, name8
); 
1208                 if (comment
.size() > 0) { 
1209                     const char16_t* p 
= comment
.string(); 
1210                     while (*p 
!= 0 && *p 
!= '.') { 
1212                             while (*p 
!= 0 && *p 
!= '}') { 
1222                     comment 
= String16(comment
.string(), p
-comment
.string()); 
1224                 String16 
name(name8
); 
1226                 fprintf(fp
, "%s   <tr><th><code>{@link #%s_%s %s:%s}</code><td>%s</tr>\n", 
1227                         indentStr
, nclassName
.string(), 
1228                         String8(name
).string(), 
1229                         assets
->getPackage().string(), 
1230                         String8(name
).string(), 
1231                         String8(comment
).string()); 
1235             fprintf(fp
, "%s   </table>\n", indentStr
); 
1237         for (a
=0; a
<NA
; a
++) { 
1238             ssize_t pos 
= idents
.indexOf(origOrder
.itemAt(a
)); 
1240                 const AaptSymbolEntry
& sym 
= nsymbols
->getSymbols().valueAt(a
); 
1241                 if (!publicFlags
.itemAt(a
) && !includePrivate
) { 
1244                 String16 
name(sym
.name
); 
1246                 fprintf(fp
, "%s   @see #%s_%s\n", 
1247                         indentStr
, nclassName
.string(), 
1248                         String8(name
).string()); 
1251         fprintf(fp
, "%s */\n", getIndentSpace(indent
)); 
1254                 "%spublic static final int[] %s = {\n" 
1256                 indentStr
, nclassName
.string(), 
1257                 getIndentSpace(indent
+1)); 
1259         for (a
=0; a
<NA
; a
++) { 
1262                     fprintf(fp
, ",\n%s", getIndentSpace(indent
+1)); 
1267             fprintf(fp
, "0x%08x", idents
[a
]); 
1270         fprintf(fp
, "\n%s};\n", indentStr
); 
1272         for (a
=0; a
<NA
; a
++) { 
1273             ssize_t pos 
= idents
.indexOf(origOrder
.itemAt(a
)); 
1275                 const AaptSymbolEntry
& sym 
= nsymbols
->getSymbols().valueAt(a
); 
1276                 if (!publicFlags
.itemAt(a
) && !includePrivate
) { 
1279                 String8 
name8(sym
.name
); 
1280                 String16 
comment(sym
.comment
); 
1281                 String16 typeComment
; 
1282                 if (comment
.size() <= 0) { 
1283                     comment 
= getAttributeComment(assets
, name8
, &typeComment
); 
1285                     getAttributeComment(assets
, name8
, &typeComment
); 
1287                 String16 
name(name8
); 
1288                 if (fixupSymbol(&name
) != NO_ERROR
) { 
1292                 uint32_t typeSpecFlags 
= 0; 
1293                 String16 
name16(sym
.name
); 
1294                 assets
->getIncludedResources().identifierForName( 
1295                     name16
.string(), name16
.size(), 
1296                     attr16
.string(), attr16
.size(), 
1297                     package16
.string(), package16
.size(), &typeSpecFlags
); 
1298                 //printf("%s:%s/%s: 0x%08x\n", String8(package16).string(), 
1299                 //    String8(attr16).string(), String8(name16).string(), typeSpecFlags); 
1300                 const bool pub 
= (typeSpecFlags
&ResTable_typeSpec::SPEC_PUBLIC
) != 0; 
1302                 fprintf(fp
, "%s/**\n", indentStr
); 
1303                 if (comment
.size() > 0) { 
1304                     fprintf(fp
, "%s  <p>\n%s  @attr description\n", indentStr
, indentStr
); 
1305                     fprintf(fp
, "%s  %s\n", indentStr
, String8(comment
).string()); 
1308                             "%s  <p>This symbol is the offset where the {@link %s.R.attr#%s}\n" 
1309                             "%s  attribute's value can be found in the {@link #%s} array.\n", 
1311                             pub 
? assets
->getPackage().string() 
1312                                 : assets
->getSymbolsPrivatePackage().string(), 
1313                             String8(name
).string(), 
1314                             indentStr
, nclassName
.string()); 
1316                 if (typeComment
.size() > 0) { 
1317                     fprintf(fp
, "\n\n%s  %s\n", indentStr
, String8(typeComment
).string()); 
1319                 if (comment
.size() > 0) { 
1322                                 "%s  <p>This corresponds to the global attribute" 
1323                                 "%s  resource symbol {@link %s.R.attr#%s}.\n", 
1324                                 indentStr
, indentStr
, 
1325                                 assets
->getPackage().string(), 
1326                                 String8(name
).string()); 
1329                                 "%s  <p>This is a private symbol.\n", indentStr
); 
1332                 fprintf(fp
, "%s  @attr name %s:%s\n", indentStr
, 
1333                         "android", String8(name
).string()); 
1334                 fprintf(fp
, "%s*/\n", indentStr
); 
1336                         "%spublic static final int %s_%s = %d;\n", 
1337                         indentStr
, nclassName
.string(), 
1338                         String8(name
).string(), (int)pos
); 
1344     fprintf(fp
, "%s};\n", getIndentSpace(indent
)); 
1345     return hasErrors 
? UNKNOWN_ERROR 
: NO_ERROR
; 
1348 static status_t 
writeSymbolClass( 
1349     FILE* fp
, const sp
<AaptAssets
>& assets
, bool includePrivate
, 
1350     const sp
<AaptSymbols
>& symbols
, const String8
& className
, int indent
) 
1352     fprintf(fp
, "%spublic %sfinal class %s {\n", 
1353             getIndentSpace(indent
), 
1354             indent 
!= 0 ? "static " : "", className
.string()); 
1358     status_t err 
= NO_ERROR
; 
1360     size_t N 
= symbols
->getSymbols().size(); 
1361     for (i
=0; i
<N
; i
++) { 
1362         const AaptSymbolEntry
& sym 
= symbols
->getSymbols().valueAt(i
); 
1363         if (sym
.typeCode 
!= AaptSymbolEntry::TYPE_INT32
) { 
1366         if (!includePrivate 
&& !sym
.isPublic
) { 
1369         String16 
name(sym
.name
); 
1370         String8 
realName(name
); 
1371         if (fixupSymbol(&name
) != NO_ERROR
) { 
1372             return UNKNOWN_ERROR
; 
1374         String16 
comment(sym
.comment
); 
1375         bool haveComment 
= false; 
1376         if (comment
.size() > 0) { 
1380                     getIndentSpace(indent
), String8(comment
).string()); 
1381         } else if (sym
.isPublic 
&& !includePrivate
) { 
1382             sym
.sourcePos
.warning("No comment for public symbol %s:%s/%s", 
1383                 assets
->getPackage().string(), className
.string(), 
1384                 String8(sym
.name
).string()); 
1386         String16 
typeComment(sym
.typeComment
); 
1387         if (typeComment
.size() > 0) { 
1392                         getIndentSpace(indent
), String8(typeComment
).string()); 
1396                         getIndentSpace(indent
), String8(typeComment
).string()); 
1400             fprintf(fp
,"%s */\n", getIndentSpace(indent
)); 
1402         fprintf(fp
, "%spublic static final int %s=0x%08x;\n", 
1403                 getIndentSpace(indent
), 
1404                 String8(name
).string(), (int)sym
.int32Val
); 
1407     for (i
=0; i
<N
; i
++) { 
1408         const AaptSymbolEntry
& sym 
= symbols
->getSymbols().valueAt(i
); 
1409         if (sym
.typeCode 
!= AaptSymbolEntry::TYPE_STRING
) { 
1412         if (!includePrivate 
&& !sym
.isPublic
) { 
1415         String16 
name(sym
.name
); 
1416         if (fixupSymbol(&name
) != NO_ERROR
) { 
1417             return UNKNOWN_ERROR
; 
1419         String16 
comment(sym
.comment
); 
1420         if (comment
.size() > 0) { 
1424                     getIndentSpace(indent
), String8(comment
).string(), 
1425                     getIndentSpace(indent
)); 
1426         } else if (sym
.isPublic 
&& !includePrivate
) { 
1427             sym
.sourcePos
.warning("No comment for public symbol %s:%s/%s", 
1428                 assets
->getPackage().string(), className
.string(), 
1429                 String8(sym
.name
).string()); 
1431         fprintf(fp
, "%spublic static final String %s=\"%s\";\n", 
1432                 getIndentSpace(indent
), 
1433                 String8(name
).string(), sym
.stringVal
.string()); 
1436     sp
<AaptSymbols
> styleableSymbols
; 
1438     N 
= symbols
->getNestedSymbols().size(); 
1439     for (i
=0; i
<N
; i
++) { 
1440         sp
<AaptSymbols
> nsymbols 
= symbols
->getNestedSymbols().valueAt(i
); 
1441         String8 
nclassName(symbols
->getNestedSymbols().keyAt(i
)); 
1442         if (nclassName 
== "styleable") { 
1443             styleableSymbols 
= nsymbols
; 
1445             err 
= writeSymbolClass(fp
, assets
, includePrivate
, nsymbols
, nclassName
, indent
); 
1447         if (err 
!= NO_ERROR
) { 
1452     if (styleableSymbols 
!= NULL
) { 
1453         err 
= writeLayoutClasses(fp
, assets
, styleableSymbols
, indent
, includePrivate
); 
1454         if (err 
!= NO_ERROR
) { 
1460     fprintf(fp
, "%s}\n", getIndentSpace(indent
)); 
1464 status_t 
writeResourceSymbols(Bundle
* bundle
, const sp
<AaptAssets
>& assets
, 
1465     const String8
& package
, bool includePrivate
) 
1467     if (!bundle
->getRClassDir()) { 
1471     const size_t N 
= assets
->getSymbols().size(); 
1472     for (size_t i
=0; i
<N
; i
++) { 
1473         sp
<AaptSymbols
> symbols 
= assets
->getSymbols().valueAt(i
); 
1474         String8 
className(assets
->getSymbols().keyAt(i
)); 
1475         String8 
dest(bundle
->getRClassDir()); 
1476         if (bundle
->getMakePackageDirs()) { 
1477             String8 
pkg(package
); 
1478             const char* last 
= pkg
.string(); 
1479             const char* s 
= last
-1; 
1482                 if (s 
> last 
&& (*s 
== '.' || *s 
== 0)) { 
1483                     String8 
part(last
, s
-last
); 
1484                     dest
.appendPath(part
); 
1485 #ifdef HAVE_MS_C_RUNTIME 
1486                     _mkdir(dest
.string()); 
1488                     mkdir(dest
.string(), S_IRUSR
|S_IWUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
); 
1494         dest
.appendPath(className
); 
1495         dest
.append(".java"); 
1496         FILE* fp 
= fopen(dest
.string(), "w+"); 
1498             fprintf(stderr
, "ERROR: Unable to open class file %s: %s\n", 
1499                     dest
.string(), strerror(errno
)); 
1500             return UNKNOWN_ERROR
; 
1502         if (bundle
->getVerbose()) { 
1503             printf("  Writing symbols for class %s.\n", className
.string()); 
1507         "/* AUTO-GENERATED FILE.  DO NOT MODIFY.\n" 
1509         " * This class was automatically generated by the\n" 
1510         " * aapt tool from the resource data it found.  It\n" 
1511         " * should not be modified by hand.\n" 
1514         "package %s;\n\n", package
.string()); 
1516         status_t err 
= writeSymbolClass(fp
, assets
, includePrivate
, symbols
, className
, 0); 
1517         if (err 
!= NO_ERROR
) {