2 // Copyright 2006 The Android Open Source Project
5 #include "AaptAssets.h"
8 #include <utils/misc.h>
9 #include <utils/SortedVector.h>
15 static const char* kDefaultLocale
= "default";
16 static const char* kWildcardName
= "any";
17 static const char* kAssetDir
= "assets";
18 static const char* kResourceDir
= "res";
19 static const char* kInvalidChars
= "/\\:";
20 static const size_t kMaxAssetFileName
= 100;
22 static const String8
kResString(kResourceDir
);
25 * Names of asset files must meet the following criteria:
27 * - the filename length must be less than kMaxAssetFileName bytes long
28 * (and can't be empty)
29 * - all characters must be 7-bit printable ASCII
30 * - none of { '/' '\\' ':' }
32 * Pass in just the filename, not the full path.
34 static bool validateFileName(const char* fileName
)
36 const char* cp
= fileName
;
40 if ((*cp
& 0x80) != 0)
41 return false; // reject high ASCII
42 if (*cp
< 0x20 || *cp
>= 0x7f)
43 return false; // reject control chars and 0x7f
44 if (strchr(kInvalidChars
, *cp
) != NULL
)
45 return false; // reject path sep chars
50 if (len
< 1 || len
> kMaxAssetFileName
)
51 return false; // reject empty or too long
56 static bool isHidden(const char *root
, const char *path
)
58 const char *ext
= NULL
;
59 const char *type
= NULL
;
61 // Skip all hidden files.
63 // Skip ., .. and .svn but don't chatter about it.
64 if (strcmp(path
, ".") == 0
65 || strcmp(path
, "..") == 0
66 || strcmp(path
, ".svn") == 0) {
70 } else if (path
[0] == '_') {
71 // skip directories starting with _ (don't chatter about it)
72 String8
subdirName(root
);
73 subdirName
.appendPath(path
);
74 if (getFileType(subdirName
.string()) == kFileTypeDirectory
) {
77 } else if (strcmp(path
, "CVS") == 0) {
78 // Skip CVS but don't chatter about it.
80 } else if (strcasecmp(path
, "thumbs.db") == 0
81 || strcasecmp(path
, "picasa.ini") == 0) {
82 // Skip suspected image indexes files.
84 } else if (path
[strlen(path
)-1] == '~') {
85 // Skip suspected emacs backup files.
87 } else if ((ext
= strrchr(path
, '.')) != NULL
&& strcmp(ext
, ".scc") == 0) {
88 // Skip VisualSourceSafe files and don't chatter about it
91 // Let everything else through.
95 /* If we get this far, "type" should be set and the file
98 String8
subdirName(root
);
99 subdirName
.appendPath(path
);
100 fprintf(stderr
, " (skipping %s %s '%s')\n", type
,
101 getFileType(subdirName
.string())==kFileTypeDirectory
? "dir":"file",
102 subdirName
.string());
107 // =========================================================================
108 // =========================================================================
109 // =========================================================================
112 AaptGroupEntry::parseNamePart(const String8
& part
, int* axis
, uint32_t* value
)
114 ResTable_config config
;
117 if (getMccName(part
.string(), &config
)) {
124 if (getMncName(part
.string(), &config
)) {
131 if (part
.length() == 2 && isalpha(part
[0]) && isalpha(part
[1])) {
132 *axis
= AXIS_LANGUAGE
;
133 *value
= part
[1] << 8 | part
[0];
137 // locale - language_REGION
138 if (part
.length() == 5 && isalpha(part
[0]) && isalpha(part
[1])
139 && part
[2] == '_' && isalpha(part
[3]) && isalpha(part
[4])) {
140 *axis
= AXIS_LANGUAGE
;
141 *value
= (part
[4] << 24) | (part
[3] << 16) | (part
[1] << 8) | (part
[0]);
145 // smallest screen dp width
146 if (getSmallestScreenWidthDpName(part
.string(), &config
)) {
147 *axis
= AXIS_SMALLESTSCREENWIDTHDP
;
148 *value
= config
.smallestScreenWidthDp
;
153 if (getScreenWidthDpName(part
.string(), &config
)) {
154 *axis
= AXIS_SCREENWIDTHDP
;
155 *value
= config
.screenWidthDp
;
160 if (getScreenHeightDpName(part
.string(), &config
)) {
161 *axis
= AXIS_SCREENHEIGHTDP
;
162 *value
= config
.screenHeightDp
;
166 // screen layout size
167 if (getScreenLayoutSizeName(part
.string(), &config
)) {
168 *axis
= AXIS_SCREENLAYOUTSIZE
;
169 *value
= (config
.screenLayout
&ResTable_config::MASK_SCREENSIZE
);
173 // screen layout long
174 if (getScreenLayoutLongName(part
.string(), &config
)) {
175 *axis
= AXIS_SCREENLAYOUTLONG
;
176 *value
= (config
.screenLayout
&ResTable_config::MASK_SCREENLONG
);
181 if (getOrientationName(part
.string(), &config
)) {
182 *axis
= AXIS_ORIENTATION
;
183 *value
= config
.orientation
;
188 if (getUiModeTypeName(part
.string(), &config
)) {
189 *axis
= AXIS_UIMODETYPE
;
190 *value
= (config
.uiMode
&ResTable_config::MASK_UI_MODE_TYPE
);
195 if (getUiModeNightName(part
.string(), &config
)) {
196 *axis
= AXIS_UIMODENIGHT
;
197 *value
= (config
.uiMode
&ResTable_config::MASK_UI_MODE_NIGHT
);
202 if (getDensityName(part
.string(), &config
)) {
203 *axis
= AXIS_DENSITY
;
204 *value
= config
.density
;
209 if (getTouchscreenName(part
.string(), &config
)) {
210 *axis
= AXIS_TOUCHSCREEN
;
211 *value
= config
.touchscreen
;
216 if (getKeysHiddenName(part
.string(), &config
)) {
217 *axis
= AXIS_KEYSHIDDEN
;
218 *value
= config
.inputFlags
;
223 if (getKeyboardName(part
.string(), &config
)) {
224 *axis
= AXIS_KEYBOARD
;
225 *value
= config
.keyboard
;
230 if (getNavHiddenName(part
.string(), &config
)) {
231 *axis
= AXIS_NAVHIDDEN
;
232 *value
= config
.inputFlags
;
237 if (getNavigationName(part
.string(), &config
)) {
238 *axis
= AXIS_NAVIGATION
;
239 *value
= config
.navigation
;
244 if (getScreenSizeName(part
.string(), &config
)) {
245 *axis
= AXIS_SCREENSIZE
;
246 *value
= config
.screenSize
;
251 if (getVersionName(part
.string(), &config
)) {
252 *axis
= AXIS_VERSION
;
253 *value
= config
.version
;
261 AaptGroupEntry::initFromDirName(const char* dir
, String8
* resType
)
263 Vector
<String8
> parts
;
265 String8 mcc
, mnc
, loc
, layoutsize
, layoutlong
, orient
, den
;
266 String8 touch
, key
, keysHidden
, nav
, navHidden
, size
, vers
;
267 String8 uiModeType
, uiModeNight
, smallestwidthdp
, widthdp
, heightdp
;
271 while (NULL
!= (q
= strchr(p
, '-'))) {
275 //printf("part: %s\n", parts[parts.size()-1].string());
281 //printf("part: %s\n", parts[parts.size()-1].string());
283 const int N
= parts
.size();
285 String8 part
= parts
[index
];
288 if (!isValidResourceType(part
)) {
300 if (getMccName(part
.string())) {
309 //printf("not mcc: %s\n", part.string());
313 if (getMncName(part
.string())) {
322 //printf("not mcc: %s\n", part.string());
326 if (part
.length() == 2 && isalpha(part
[0]) && isalpha(part
[1])) {
335 //printf("not language: %s\n", part.string());
340 && part
.length() == 3 && part
[0] == 'r' && part
[0] && part
[1]) {
343 loc
+= part
.string() + 1;
351 //printf("not region: %s\n", part.string());
354 if (getSmallestScreenWidthDpName(part
.string())) {
355 smallestwidthdp
= part
;
363 //printf("not smallest screen width dp: %s\n", part.string());
366 if (getScreenWidthDpName(part
.string())) {
375 //printf("not screen width dp: %s\n", part.string());
378 if (getScreenHeightDpName(part
.string())) {
387 //printf("not screen height dp: %s\n", part.string());
390 if (getScreenLayoutSizeName(part
.string())) {
399 //printf("not screen layout size: %s\n", part.string());
402 if (getScreenLayoutLongName(part
.string())) {
411 //printf("not screen layout long: %s\n", part.string());
415 if (getOrientationName(part
.string())) {
424 //printf("not orientation: %s\n", part.string());
428 if (getUiModeTypeName(part
.string())) {
437 //printf("not ui mode type: %s\n", part.string());
441 if (getUiModeNightName(part
.string())) {
450 //printf("not ui mode night: %s\n", part.string());
454 if (getDensityName(part
.string())) {
463 //printf("not density: %s\n", part.string());
467 if (getTouchscreenName(part
.string())) {
476 //printf("not touchscreen: %s\n", part.string());
480 if (getKeysHiddenName(part
.string())) {
489 //printf("not keysHidden: %s\n", part.string());
493 if (getKeyboardName(part
.string())) {
502 //printf("not keyboard: %s\n", part.string());
506 if (getNavHiddenName(part
.string())) {
515 //printf("not navHidden: %s\n", part.string());
518 if (getNavigationName(part
.string())) {
527 //printf("not navigation: %s\n", part.string());
530 if (getScreenSizeName(part
.string())) {
539 //printf("not screen size: %s\n", part.string());
542 if (getVersionName(part
.string())) {
551 //printf("not version: %s\n", part.string());
554 // if there are extra parts, it doesn't match
561 this->screenLayoutSize
= layoutsize
;
562 this->screenLayoutLong
= layoutlong
;
563 this->smallestScreenWidthDp
= smallestwidthdp
;
564 this->screenWidthDp
= widthdp
;
565 this->screenHeightDp
= heightdp
;
566 this->orientation
= orient
;
567 this->uiModeType
= uiModeType
;
568 this->uiModeNight
= uiModeNight
;
570 this->touchscreen
= touch
;
571 this->keysHidden
= keysHidden
;
572 this->keyboard
= key
;
573 this->navHidden
= navHidden
;
574 this->navigation
= nav
;
575 this->screenSize
= size
;
576 this->version
= vers
;
578 // what is this anyway?
585 AaptGroupEntry::toString() const
587 String8 s
= this->mcc
;
593 s
+= smallestScreenWidthDp
;
599 s
+= screenLayoutSize
;
601 s
+= screenLayoutLong
;
603 s
+= this->orientation
;
628 AaptGroupEntry::toDirName(const String8
& resType
) const
631 if (this->mcc
!= "") {
635 if (this->mnc
!= "") {
639 if (this->locale
!= "") {
643 if (this->smallestScreenWidthDp
!= "") {
645 s
+= smallestScreenWidthDp
;
647 if (this->screenWidthDp
!= "") {
651 if (this->screenHeightDp
!= "") {
655 if (this->screenLayoutSize
!= "") {
657 s
+= screenLayoutSize
;
659 if (this->screenLayoutLong
!= "") {
661 s
+= screenLayoutLong
;
663 if (this->orientation
!= "") {
667 if (this->uiModeType
!= "") {
671 if (this->uiModeNight
!= "") {
675 if (this->density
!= "") {
679 if (this->touchscreen
!= "") {
683 if (this->keysHidden
!= "") {
687 if (this->keyboard
!= "") {
691 if (this->navHidden
!= "") {
695 if (this->navigation
!= "") {
699 if (this->screenSize
!= "") {
703 if (this->version
!= "") {
711 bool AaptGroupEntry::getMccName(const char* name
,
712 ResTable_config
* out
)
714 if (strcmp(name
, kWildcardName
) == 0) {
715 if (out
) out
->mcc
= 0;
718 const char* c
= name
;
719 if (tolower(*c
) != 'm') return false;
721 if (tolower(*c
) != 'c') return false;
723 if (tolower(*c
) != 'c') return false;
728 while (*c
>= '0' && *c
<= '9') {
731 if (*c
!= 0) return false;
732 if (c
-val
!= 3) return false;
736 if (out
) out
->mcc
= d
;
743 bool AaptGroupEntry::getMncName(const char* name
,
744 ResTable_config
* out
)
746 if (strcmp(name
, kWildcardName
) == 0) {
747 if (out
) out
->mcc
= 0;
750 const char* c
= name
;
751 if (tolower(*c
) != 'm') return false;
753 if (tolower(*c
) != 'n') return false;
755 if (tolower(*c
) != 'c') return false;
760 while (*c
>= '0' && *c
<= '9') {
763 if (*c
!= 0) return false;
764 if (c
-val
== 0 || c
-val
> 3) return false;
767 out
->mnc
= atoi(val
);
774 * Does this directory name fit the pattern of a locale dir ("en-rUS" or
777 * TODO: Should insist that the first two letters are lower case, and the
778 * second two are upper.
780 bool AaptGroupEntry::getLocaleName(const char* fileName
,
781 ResTable_config
* out
)
783 if (strcmp(fileName
, kWildcardName
) == 0
784 || strcmp(fileName
, kDefaultLocale
) == 0) {
786 out
->language
[0] = 0;
787 out
->language
[1] = 0;
794 if (strlen(fileName
) == 2 && isalpha(fileName
[0]) && isalpha(fileName
[1])) {
796 out
->language
[0] = fileName
[0];
797 out
->language
[1] = fileName
[1];
804 if (strlen(fileName
) == 5 &&
805 isalpha(fileName
[0]) &&
806 isalpha(fileName
[1]) &&
807 fileName
[2] == '-' &&
808 isalpha(fileName
[3]) &&
809 isalpha(fileName
[4])) {
811 out
->language
[0] = fileName
[0];
812 out
->language
[1] = fileName
[1];
813 out
->country
[0] = fileName
[3];
814 out
->country
[1] = fileName
[4];
822 bool AaptGroupEntry::getScreenLayoutSizeName(const char* name
,
823 ResTable_config
* out
)
825 if (strcmp(name
, kWildcardName
) == 0) {
826 if (out
) out
->screenLayout
=
827 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
828 | ResTable_config::SCREENSIZE_ANY
;
830 } else if (strcmp(name
, "small") == 0) {
831 if (out
) out
->screenLayout
=
832 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
833 | ResTable_config::SCREENSIZE_SMALL
;
835 } else if (strcmp(name
, "normal") == 0) {
836 if (out
) out
->screenLayout
=
837 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
838 | ResTable_config::SCREENSIZE_NORMAL
;
840 } else if (strcmp(name
, "large") == 0) {
841 if (out
) out
->screenLayout
=
842 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
843 | ResTable_config::SCREENSIZE_LARGE
;
845 } else if (strcmp(name
, "xlarge") == 0) {
846 if (out
) out
->screenLayout
=
847 (out
->screenLayout
&~ResTable_config::MASK_SCREENSIZE
)
848 | ResTable_config::SCREENSIZE_XLARGE
;
855 bool AaptGroupEntry::getScreenLayoutLongName(const char* name
,
856 ResTable_config
* out
)
858 if (strcmp(name
, kWildcardName
) == 0) {
859 if (out
) out
->screenLayout
=
860 (out
->screenLayout
&~ResTable_config::MASK_SCREENLONG
)
861 | ResTable_config::SCREENLONG_ANY
;
863 } else if (strcmp(name
, "long") == 0) {
864 if (out
) out
->screenLayout
=
865 (out
->screenLayout
&~ResTable_config::MASK_SCREENLONG
)
866 | ResTable_config::SCREENLONG_YES
;
868 } else if (strcmp(name
, "notlong") == 0) {
869 if (out
) out
->screenLayout
=
870 (out
->screenLayout
&~ResTable_config::MASK_SCREENLONG
)
871 | ResTable_config::SCREENLONG_NO
;
878 bool AaptGroupEntry::getOrientationName(const char* name
,
879 ResTable_config
* out
)
881 if (strcmp(name
, kWildcardName
) == 0) {
882 if (out
) out
->orientation
= out
->ORIENTATION_ANY
;
884 } else if (strcmp(name
, "port") == 0) {
885 if (out
) out
->orientation
= out
->ORIENTATION_PORT
;
887 } else if (strcmp(name
, "land") == 0) {
888 if (out
) out
->orientation
= out
->ORIENTATION_LAND
;
890 } else if (strcmp(name
, "square") == 0) {
891 if (out
) out
->orientation
= out
->ORIENTATION_SQUARE
;
898 bool AaptGroupEntry::getUiModeTypeName(const char* name
,
899 ResTable_config
* out
)
901 if (strcmp(name
, kWildcardName
) == 0) {
902 if (out
) out
->uiMode
=
903 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
904 | ResTable_config::UI_MODE_TYPE_ANY
;
906 } else if (strcmp(name
, "desk") == 0) {
907 if (out
) out
->uiMode
=
908 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
909 | ResTable_config::UI_MODE_TYPE_DESK
;
911 } else if (strcmp(name
, "car") == 0) {
912 if (out
) out
->uiMode
=
913 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
914 | ResTable_config::UI_MODE_TYPE_CAR
;
921 bool AaptGroupEntry::getUiModeNightName(const char* name
,
922 ResTable_config
* out
)
924 if (strcmp(name
, kWildcardName
) == 0) {
925 if (out
) out
->uiMode
=
926 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
927 | ResTable_config::UI_MODE_NIGHT_ANY
;
929 } else if (strcmp(name
, "night") == 0) {
930 if (out
) out
->uiMode
=
931 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
932 | ResTable_config::UI_MODE_NIGHT_YES
;
934 } else if (strcmp(name
, "notnight") == 0) {
935 if (out
) out
->uiMode
=
936 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
937 | ResTable_config::UI_MODE_NIGHT_NO
;
944 bool AaptGroupEntry::getDensityName(const char* name
,
945 ResTable_config
* out
)
947 if (strcmp(name
, kWildcardName
) == 0) {
948 if (out
) out
->density
= ResTable_config::DENSITY_DEFAULT
;
952 if (strcmp(name
, "nodpi") == 0) {
953 if (out
) out
->density
= ResTable_config::DENSITY_NONE
;
957 if (strcmp(name
, "ldpi") == 0) {
958 if (out
) out
->density
= ResTable_config::DENSITY_LOW
;
962 if (strcmp(name
, "mdpi") == 0) {
963 if (out
) out
->density
= ResTable_config::DENSITY_MEDIUM
;
967 if (strcmp(name
, "hdpi") == 0) {
968 if (out
) out
->density
= ResTable_config::DENSITY_HIGH
;
972 if (strcmp(name
, "xhdpi") == 0) {
973 if (out
) out
->density
= ResTable_config::DENSITY_MEDIUM
*2;
977 char* c
= (char*)name
;
978 while (*c
>= '0' && *c
<= '9') {
982 // check that we have 'dpi' after the last digit.
983 if (toupper(c
[0]) != 'D' ||
984 toupper(c
[1]) != 'P' ||
985 toupper(c
[2]) != 'I' ||
990 // temporarily replace the first letter with \0 to
999 if (out
) out
->density
= d
;
1006 bool AaptGroupEntry::getTouchscreenName(const char* name
,
1007 ResTable_config
* out
)
1009 if (strcmp(name
, kWildcardName
) == 0) {
1010 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_ANY
;
1012 } else if (strcmp(name
, "notouch") == 0) {
1013 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_NOTOUCH
;
1015 } else if (strcmp(name
, "stylus") == 0) {
1016 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_STYLUS
;
1018 } else if (strcmp(name
, "finger") == 0) {
1019 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_FINGER
;
1026 bool AaptGroupEntry::getKeysHiddenName(const char* name
,
1027 ResTable_config
* out
)
1031 if (strcmp(name
, kWildcardName
) == 0) {
1032 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1033 value
= ResTable_config::KEYSHIDDEN_ANY
;
1034 } else if (strcmp(name
, "keysexposed") == 0) {
1035 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1036 value
= ResTable_config::KEYSHIDDEN_NO
;
1037 } else if (strcmp(name
, "keyshidden") == 0) {
1038 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1039 value
= ResTable_config::KEYSHIDDEN_YES
;
1040 } else if (strcmp(name
, "keyssoft") == 0) {
1041 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1042 value
= ResTable_config::KEYSHIDDEN_SOFT
;
1046 if (out
) out
->inputFlags
= (out
->inputFlags
&~mask
) | value
;
1053 bool AaptGroupEntry::getKeyboardName(const char* name
,
1054 ResTable_config
* out
)
1056 if (strcmp(name
, kWildcardName
) == 0) {
1057 if (out
) out
->keyboard
= out
->KEYBOARD_ANY
;
1059 } else if (strcmp(name
, "nokeys") == 0) {
1060 if (out
) out
->keyboard
= out
->KEYBOARD_NOKEYS
;
1062 } else if (strcmp(name
, "qwerty") == 0) {
1063 if (out
) out
->keyboard
= out
->KEYBOARD_QWERTY
;
1065 } else if (strcmp(name
, "12key") == 0) {
1066 if (out
) out
->keyboard
= out
->KEYBOARD_12KEY
;
1073 bool AaptGroupEntry::getNavHiddenName(const char* name
,
1074 ResTable_config
* out
)
1078 if (strcmp(name
, kWildcardName
) == 0) {
1079 mask
= ResTable_config::MASK_NAVHIDDEN
;
1080 value
= ResTable_config::NAVHIDDEN_ANY
;
1081 } else if (strcmp(name
, "navexposed") == 0) {
1082 mask
= ResTable_config::MASK_NAVHIDDEN
;
1083 value
= ResTable_config::NAVHIDDEN_NO
;
1084 } else if (strcmp(name
, "navhidden") == 0) {
1085 mask
= ResTable_config::MASK_NAVHIDDEN
;
1086 value
= ResTable_config::NAVHIDDEN_YES
;
1090 if (out
) out
->inputFlags
= (out
->inputFlags
&~mask
) | value
;
1097 bool AaptGroupEntry::getNavigationName(const char* name
,
1098 ResTable_config
* out
)
1100 if (strcmp(name
, kWildcardName
) == 0) {
1101 if (out
) out
->navigation
= out
->NAVIGATION_ANY
;
1103 } else if (strcmp(name
, "nonav") == 0) {
1104 if (out
) out
->navigation
= out
->NAVIGATION_NONAV
;
1106 } else if (strcmp(name
, "dpad") == 0) {
1107 if (out
) out
->navigation
= out
->NAVIGATION_DPAD
;
1109 } else if (strcmp(name
, "trackball") == 0) {
1110 if (out
) out
->navigation
= out
->NAVIGATION_TRACKBALL
;
1112 } else if (strcmp(name
, "wheel") == 0) {
1113 if (out
) out
->navigation
= out
->NAVIGATION_WHEEL
;
1120 bool AaptGroupEntry::getScreenSizeName(const char* name
, ResTable_config
* out
)
1122 if (strcmp(name
, kWildcardName
) == 0) {
1124 out
->screenWidth
= out
->SCREENWIDTH_ANY
;
1125 out
->screenHeight
= out
->SCREENHEIGHT_ANY
;
1130 const char* x
= name
;
1131 while (*x
>= '0' && *x
<= '9') x
++;
1132 if (x
== name
|| *x
!= 'x') return false;
1133 String8
xName(name
, x
-name
);
1137 while (*y
>= '0' && *y
<= '9') y
++;
1138 if (y
== name
|| *y
!= 0) return false;
1139 String8
yName(x
, y
-x
);
1141 uint16_t w
= (uint16_t)atoi(xName
.string());
1142 uint16_t h
= (uint16_t)atoi(yName
.string());
1148 out
->screenWidth
= w
;
1149 out
->screenHeight
= h
;
1155 bool AaptGroupEntry::getSmallestScreenWidthDpName(const char* name
, ResTable_config
* out
)
1157 if (strcmp(name
, kWildcardName
) == 0) {
1159 out
->smallestScreenWidthDp
= out
->SCREENWIDTH_ANY
;
1164 if (*name
!= 's') return false;
1166 if (*name
!= 'w') return false;
1168 const char* x
= name
;
1169 while (*x
>= '0' && *x
<= '9') x
++;
1170 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1171 String8
xName(name
, x
-name
);
1174 out
->smallestScreenWidthDp
= (uint16_t)atoi(xName
.string());
1180 bool AaptGroupEntry::getScreenWidthDpName(const char* name
, ResTable_config
* out
)
1182 if (strcmp(name
, kWildcardName
) == 0) {
1184 out
->screenWidthDp
= out
->SCREENWIDTH_ANY
;
1189 if (*name
!= 'w') return false;
1191 const char* x
= name
;
1192 while (*x
>= '0' && *x
<= '9') x
++;
1193 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1194 String8
xName(name
, x
-name
);
1197 out
->screenWidthDp
= (uint16_t)atoi(xName
.string());
1203 bool AaptGroupEntry::getScreenHeightDpName(const char* name
, ResTable_config
* out
)
1205 if (strcmp(name
, kWildcardName
) == 0) {
1207 out
->screenHeightDp
= out
->SCREENWIDTH_ANY
;
1212 if (*name
!= 'h') return false;
1214 const char* x
= name
;
1215 while (*x
>= '0' && *x
<= '9') x
++;
1216 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1217 String8
xName(name
, x
-name
);
1220 out
->screenHeightDp
= (uint16_t)atoi(xName
.string());
1226 bool AaptGroupEntry::getVersionName(const char* name
, ResTable_config
* out
)
1228 if (strcmp(name
, kWildcardName
) == 0) {
1230 out
->sdkVersion
= out
->SDKVERSION_ANY
;
1231 out
->minorVersion
= out
->MINORVERSION_ANY
;
1241 const char* s
= name
;
1242 while (*s
>= '0' && *s
<= '9') s
++;
1243 if (s
== name
|| *s
!= 0) return false;
1244 String8
sdkName(name
, s
-name
);
1247 out
->sdkVersion
= (uint16_t)atoi(sdkName
.string());
1248 out
->minorVersion
= 0;
1254 int AaptGroupEntry::compare(const AaptGroupEntry
& o
) const
1256 int v
= mcc
.compare(o
.mcc
);
1257 if (v
== 0) v
= mnc
.compare(o
.mnc
);
1258 if (v
== 0) v
= locale
.compare(o
.locale
);
1259 if (v
== 0) v
= vendor
.compare(o
.vendor
);
1260 if (v
== 0) v
= smallestScreenWidthDp
.compare(o
.smallestScreenWidthDp
);
1261 if (v
== 0) v
= screenWidthDp
.compare(o
.screenWidthDp
);
1262 if (v
== 0) v
= screenHeightDp
.compare(o
.screenHeightDp
);
1263 if (v
== 0) v
= screenLayoutSize
.compare(o
.screenLayoutSize
);
1264 if (v
== 0) v
= screenLayoutLong
.compare(o
.screenLayoutLong
);
1265 if (v
== 0) v
= orientation
.compare(o
.orientation
);
1266 if (v
== 0) v
= uiModeType
.compare(o
.uiModeType
);
1267 if (v
== 0) v
= uiModeNight
.compare(o
.uiModeNight
);
1268 if (v
== 0) v
= density
.compare(o
.density
);
1269 if (v
== 0) v
= touchscreen
.compare(o
.touchscreen
);
1270 if (v
== 0) v
= keysHidden
.compare(o
.keysHidden
);
1271 if (v
== 0) v
= keyboard
.compare(o
.keyboard
);
1272 if (v
== 0) v
= navHidden
.compare(o
.navHidden
);
1273 if (v
== 0) v
= navigation
.compare(o
.navigation
);
1274 if (v
== 0) v
= screenSize
.compare(o
.screenSize
);
1275 if (v
== 0) v
= version
.compare(o
.version
);
1279 ResTable_config
AaptGroupEntry::toParams() const
1281 ResTable_config params
;
1282 memset(¶ms
, 0, sizeof(params
));
1283 getMccName(mcc
.string(), ¶ms
);
1284 getMncName(mnc
.string(), ¶ms
);
1285 getLocaleName(locale
.string(), ¶ms
);
1286 getSmallestScreenWidthDpName(smallestScreenWidthDp
.string(), ¶ms
);
1287 getScreenWidthDpName(screenWidthDp
.string(), ¶ms
);
1288 getScreenHeightDpName(screenHeightDp
.string(), ¶ms
);
1289 getScreenLayoutSizeName(screenLayoutSize
.string(), ¶ms
);
1290 getScreenLayoutLongName(screenLayoutLong
.string(), ¶ms
);
1291 getOrientationName(orientation
.string(), ¶ms
);
1292 getUiModeTypeName(uiModeType
.string(), ¶ms
);
1293 getUiModeNightName(uiModeNight
.string(), ¶ms
);
1294 getDensityName(density
.string(), ¶ms
);
1295 getTouchscreenName(touchscreen
.string(), ¶ms
);
1296 getKeysHiddenName(keysHidden
.string(), ¶ms
);
1297 getKeyboardName(keyboard
.string(), ¶ms
);
1298 getNavHiddenName(navHidden
.string(), ¶ms
);
1299 getNavigationName(navigation
.string(), ¶ms
);
1300 getScreenSizeName(screenSize
.string(), ¶ms
);
1301 getVersionName(version
.string(), ¶ms
);
1303 // Fix up version number based on specified parameters.
1305 if (params
.smallestScreenWidthDp
!= ResTable_config::SCREENWIDTH_ANY
1306 || params
.screenWidthDp
!= ResTable_config::SCREENWIDTH_ANY
1307 || params
.screenHeightDp
!= ResTable_config::SCREENHEIGHT_ANY
) {
1308 minSdk
= SDK_HONEYCOMB_MR2
;
1309 } else if ((params
.uiMode
&ResTable_config::MASK_UI_MODE_TYPE
)
1310 != ResTable_config::UI_MODE_TYPE_ANY
1311 || (params
.uiMode
&ResTable_config::MASK_UI_MODE_NIGHT
)
1312 != ResTable_config::UI_MODE_NIGHT_ANY
) {
1314 } else if ((params
.screenLayout
&ResTable_config::MASK_SCREENSIZE
)
1315 != ResTable_config::SCREENSIZE_ANY
1316 || (params
.screenLayout
&ResTable_config::MASK_SCREENLONG
)
1317 != ResTable_config::SCREENLONG_ANY
1318 || params
.density
!= ResTable_config::DENSITY_DEFAULT
) {
1322 if (minSdk
> params
.sdkVersion
) {
1323 params
.sdkVersion
= minSdk
;
1329 // =========================================================================
1330 // =========================================================================
1331 // =========================================================================
1333 void* AaptFile::editData(size_t size
)
1335 if (size
<= mBufferSize
) {
1339 size_t allocSize
= (size
*3)/2;
1340 void* buf
= realloc(mData
, allocSize
);
1346 mBufferSize
= allocSize
;
1350 void* AaptFile::editData(size_t* outSize
)
1353 *outSize
= mDataSize
;
1358 void* AaptFile::padData(size_t wordSize
)
1360 const size_t extra
= mDataSize%wordSize
;
1365 size_t initial
= mDataSize
;
1366 void* data
= editData(initial
+(wordSize
-extra
));
1368 memset(((uint8_t*)data
) + initial
, 0, wordSize
-extra
);
1373 status_t
AaptFile::writeData(const void* data
, size_t size
)
1375 size_t end
= mDataSize
;
1376 size_t total
= size
+ end
;
1377 void* buf
= editData(total
);
1379 return UNKNOWN_ERROR
;
1381 memcpy(((char*)buf
)+end
, data
, size
);
1385 void AaptFile::clearData()
1387 if (mData
!= NULL
) free(mData
);
1393 String8
AaptFile::getPrintableSource() const
1396 String8
name(mGroupEntry
.locale
.string());
1397 name
.appendPath(mGroupEntry
.vendor
.string());
1398 name
.appendPath(mPath
);
1399 name
.append(" #generated");
1405 // =========================================================================
1406 // =========================================================================
1407 // =========================================================================
1409 status_t
AaptGroup::addFile(const sp
<AaptFile
>& file
)
1411 if (mFiles
.indexOfKey(file
->getGroupEntry()) < 0) {
1412 file
->mPath
= mPath
;
1413 mFiles
.add(file
->getGroupEntry(), file
);
1417 SourcePos(file
->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
1418 getPrintableSource().string());
1419 return UNKNOWN_ERROR
;
1422 void AaptGroup::removeFile(size_t index
)
1424 mFiles
.removeItemsAt(index
);
1427 void AaptGroup::print() const
1429 printf(" %s\n", getPath().string());
1430 const size_t N
=mFiles
.size();
1432 for (i
=0; i
<N
; i
++) {
1433 sp
<AaptFile
> file
= mFiles
.valueAt(i
);
1434 const AaptGroupEntry
& e
= file
->getGroupEntry();
1435 if (file
->hasData()) {
1436 printf(" Gen: (%s) %d bytes\n", e
.toString().string(),
1437 (int)file
->getSize());
1439 printf(" Src: %s\n", file
->getPrintableSource().string());
1444 String8
AaptGroup::getPrintableSource() const
1446 if (mFiles
.size() > 0) {
1447 // Arbitrarily pull the first source file out of the list.
1448 return mFiles
.valueAt(0)->getPrintableSource();
1451 // Should never hit this case, but to be safe...
1456 // =========================================================================
1457 // =========================================================================
1458 // =========================================================================
1460 status_t
AaptDir::addFile(const String8
& name
, const sp
<AaptGroup
>& file
)
1462 if (mFiles
.indexOfKey(name
) >= 0) {
1463 return ALREADY_EXISTS
;
1465 mFiles
.add(name
, file
);
1469 status_t
AaptDir::addDir(const String8
& name
, const sp
<AaptDir
>& dir
)
1471 if (mDirs
.indexOfKey(name
) >= 0) {
1472 return ALREADY_EXISTS
;
1474 mDirs
.add(name
, dir
);
1478 sp
<AaptDir
> AaptDir::makeDir(const String8
& path
)
1481 String8 remain
= path
;
1483 sp
<AaptDir
> subdir
= this;
1484 while (name
= remain
.walkPath(&remain
), remain
!= "") {
1485 subdir
= subdir
->makeDir(name
);
1488 ssize_t i
= subdir
->mDirs
.indexOfKey(name
);
1490 return subdir
->mDirs
.valueAt(i
);
1492 sp
<AaptDir
> dir
= new AaptDir(name
, subdir
->mPath
.appendPathCopy(name
));
1493 subdir
->mDirs
.add(name
, dir
);
1497 void AaptDir::removeFile(const String8
& name
)
1499 mFiles
.removeItem(name
);
1502 void AaptDir::removeDir(const String8
& name
)
1504 mDirs
.removeItem(name
);
1507 status_t
AaptDir::renameFile(const sp
<AaptFile
>& file
, const String8
& newName
)
1509 sp
<AaptGroup
> origGroup
;
1511 // Find and remove the given file with shear, brute force!
1512 const size_t NG
= mFiles
.size();
1514 for (i
=0; origGroup
== NULL
&& i
<NG
; i
++) {
1515 sp
<AaptGroup
> g
= mFiles
.valueAt(i
);
1516 const size_t NF
= g
->getFiles().size();
1517 for (size_t j
=0; j
<NF
; j
++) {
1518 if (g
->getFiles().valueAt(j
) == file
) {
1522 mFiles
.removeItemsAt(i
);
1529 //printf("Renaming %s to %s\n", file->getPath().getPathName(), newName.string());
1531 // Place the file under its new name.
1532 if (origGroup
!= NULL
) {
1533 return addLeafFile(newName
, file
);
1539 status_t
AaptDir::addLeafFile(const String8
& leafName
, const sp
<AaptFile
>& file
)
1541 sp
<AaptGroup
> group
;
1542 if (mFiles
.indexOfKey(leafName
) >= 0) {
1543 group
= mFiles
.valueFor(leafName
);
1545 group
= new AaptGroup(leafName
, mPath
.appendPathCopy(leafName
));
1546 mFiles
.add(leafName
, group
);
1549 return group
->addFile(file
);
1552 ssize_t
AaptDir::slurpFullTree(Bundle
* bundle
, const String8
& srcDir
,
1553 const AaptGroupEntry
& kind
, const String8
& resType
)
1555 Vector
<String8
> fileNames
;
1560 dir
= opendir(srcDir
.string());
1562 fprintf(stderr
, "ERROR: opendir(%s): %s\n", srcDir
.string(), strerror(errno
));
1563 return UNKNOWN_ERROR
;
1567 * Slurp the filenames out of the directory.
1570 struct dirent
* entry
;
1572 entry
= readdir(dir
);
1576 if (isHidden(srcDir
.string(), entry
->d_name
))
1579 fileNames
.add(String8(entry
->d_name
));
1588 * Stash away the files and recursively descend into subdirectories.
1590 const size_t N
= fileNames
.size();
1592 for (i
= 0; i
< N
; i
++) {
1593 String8
pathName(srcDir
);
1596 pathName
.appendPath(fileNames
[i
].string());
1597 type
= getFileType(pathName
.string());
1598 if (type
== kFileTypeDirectory
) {
1600 bool notAdded
= false;
1601 if (mDirs
.indexOfKey(fileNames
[i
]) >= 0) {
1602 subdir
= mDirs
.valueFor(fileNames
[i
]);
1604 subdir
= new AaptDir(fileNames
[i
], mPath
.appendPathCopy(fileNames
[i
]));
1607 ssize_t res
= subdir
->slurpFullTree(bundle
, pathName
, kind
,
1609 if (res
< NO_ERROR
) {
1612 if (res
> 0 && notAdded
) {
1613 mDirs
.add(fileNames
[i
], subdir
);
1616 } else if (type
== kFileTypeRegular
) {
1617 sp
<AaptFile
> file
= new AaptFile(pathName
, kind
, resType
);
1618 status_t err
= addLeafFile(fileNames
[i
], file
);
1619 if (err
!= NO_ERROR
) {
1626 if (bundle
->getVerbose())
1627 printf(" (ignoring non-file/dir '%s')\n", pathName
.string());
1634 status_t
AaptDir::validate() const
1636 const size_t NF
= mFiles
.size();
1637 const size_t ND
= mDirs
.size();
1639 for (i
= 0; i
< NF
; i
++) {
1640 if (!validateFileName(mFiles
.valueAt(i
)->getLeaf().string())) {
1641 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1642 "Invalid filename. Unable to add.");
1643 return UNKNOWN_ERROR
;
1647 for (j
= i
+1; j
< NF
; j
++) {
1648 if (strcasecmp(mFiles
.valueAt(i
)->getLeaf().string(),
1649 mFiles
.valueAt(j
)->getLeaf().string()) == 0) {
1650 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1651 "File is case-insensitive equivalent to: %s",
1652 mFiles
.valueAt(j
)->getPrintableSource().string());
1653 return UNKNOWN_ERROR
;
1656 // TODO: if ".gz", check for non-.gz; if non-, check for ".gz"
1657 // (this is mostly caught by the "marked" stuff, below)
1660 for (j
= 0; j
< ND
; j
++) {
1661 if (strcasecmp(mFiles
.valueAt(i
)->getLeaf().string(),
1662 mDirs
.valueAt(j
)->getLeaf().string()) == 0) {
1663 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1664 "File conflicts with dir from: %s",
1665 mDirs
.valueAt(j
)->getPrintableSource().string());
1666 return UNKNOWN_ERROR
;
1671 for (i
= 0; i
< ND
; i
++) {
1672 if (!validateFileName(mDirs
.valueAt(i
)->getLeaf().string())) {
1673 SourcePos(mDirs
.valueAt(i
)->getPrintableSource(), -1).error(
1674 "Invalid directory name, unable to add.");
1675 return UNKNOWN_ERROR
;
1679 for (j
= i
+1; j
< ND
; j
++) {
1680 if (strcasecmp(mDirs
.valueAt(i
)->getLeaf().string(),
1681 mDirs
.valueAt(j
)->getLeaf().string()) == 0) {
1682 SourcePos(mDirs
.valueAt(i
)->getPrintableSource(), -1).error(
1683 "Directory is case-insensitive equivalent to: %s",
1684 mDirs
.valueAt(j
)->getPrintableSource().string());
1685 return UNKNOWN_ERROR
;
1689 status_t err
= mDirs
.valueAt(i
)->validate();
1690 if (err
!= NO_ERROR
) {
1698 void AaptDir::print() const
1700 const size_t ND
=getDirs().size();
1702 for (i
=0; i
<ND
; i
++) {
1703 getDirs().valueAt(i
)->print();
1706 const size_t NF
=getFiles().size();
1707 for (i
=0; i
<NF
; i
++) {
1708 getFiles().valueAt(i
)->print();
1712 String8
AaptDir::getPrintableSource() const
1714 if (mFiles
.size() > 0) {
1715 // Arbitrarily pull the first file out of the list as the source dir.
1716 return mFiles
.valueAt(0)->getPrintableSource().getPathDir();
1718 if (mDirs
.size() > 0) {
1719 // Or arbitrarily pull the first dir out of the list as the source dir.
1720 return mDirs
.valueAt(0)->getPrintableSource().getPathDir();
1723 // Should never hit this case, but to be safe...
1728 // =========================================================================
1729 // =========================================================================
1730 // =========================================================================
1732 sp
<AaptFile
> AaptAssets::addFile(
1733 const String8
& filePath
, const AaptGroupEntry
& entry
,
1734 const String8
& srcDir
, sp
<AaptGroup
>* outGroup
,
1735 const String8
& resType
)
1737 sp
<AaptDir
> dir
= this;
1738 sp
<AaptGroup
> group
;
1740 String8 root
, remain(filePath
), partialPath
;
1741 while (remain
.length() > 0) {
1742 root
= remain
.walkPath(&remain
);
1743 partialPath
.appendPath(root
);
1745 const String8
rootStr(root
);
1747 if (remain
.length() == 0) {
1748 ssize_t i
= dir
->getFiles().indexOfKey(rootStr
);
1750 group
= dir
->getFiles().valueAt(i
);
1752 group
= new AaptGroup(rootStr
, filePath
);
1753 status_t res
= dir
->addFile(rootStr
, group
);
1754 if (res
!= NO_ERROR
) {
1758 file
= new AaptFile(srcDir
.appendPathCopy(filePath
), entry
, resType
);
1759 status_t res
= group
->addFile(file
);
1760 if (res
!= NO_ERROR
) {
1766 ssize_t i
= dir
->getDirs().indexOfKey(rootStr
);
1768 dir
= dir
->getDirs().valueAt(i
);
1770 sp
<AaptDir
> subdir
= new AaptDir(rootStr
, partialPath
);
1771 status_t res
= dir
->addDir(rootStr
, subdir
);
1772 if (res
!= NO_ERROR
) {
1780 mGroupEntries
.add(entry
);
1781 if (outGroup
) *outGroup
= group
;
1785 void AaptAssets::addResource(const String8
& leafName
, const String8
& path
,
1786 const sp
<AaptFile
>& file
, const String8
& resType
)
1788 sp
<AaptDir
> res
= AaptDir::makeDir(kResString
);
1789 String8 dirname
= file
->getGroupEntry().toDirName(resType
);
1790 sp
<AaptDir
> subdir
= res
->makeDir(dirname
);
1791 sp
<AaptGroup
> grr
= new AaptGroup(leafName
, path
);
1794 subdir
->addFile(leafName
, grr
);
1798 ssize_t
AaptAssets::slurpFromArgs(Bundle
* bundle
)
1803 const Vector
<const char *>& resDirs
= bundle
->getResourceSourceDirs();
1804 const size_t dirCount
=resDirs
.size();
1805 sp
<AaptAssets
> current
= this;
1807 const int N
= bundle
->getFileSpecCount();
1810 * If a package manifest was specified, include that first.
1812 if (bundle
->getAndroidManifestFile() != NULL
) {
1813 // place at root of zip.
1814 String8
srcFile(bundle
->getAndroidManifestFile());
1815 addFile(srcFile
.getPathLeaf(), AaptGroupEntry(), srcFile
.getPathDir(),
1821 * If a directory of custom assets was supplied, slurp 'em up.
1823 if (bundle
->getAssetSourceDir()) {
1824 const char* assetDir
= bundle
->getAssetSourceDir();
1826 FileType type
= getFileType(assetDir
);
1827 if (type
== kFileTypeNonexistent
) {
1828 fprintf(stderr
, "ERROR: asset directory '%s' does not exist\n", assetDir
);
1829 return UNKNOWN_ERROR
;
1831 if (type
!= kFileTypeDirectory
) {
1832 fprintf(stderr
, "ERROR: '%s' is not a directory\n", assetDir
);
1833 return UNKNOWN_ERROR
;
1836 String8
assetRoot(assetDir
);
1837 sp
<AaptDir
> assetAaptDir
= makeDir(String8(kAssetDir
));
1838 AaptGroupEntry group
;
1839 count
= assetAaptDir
->slurpFullTree(bundle
, assetRoot
, group
,
1846 mGroupEntries
.add(group
);
1848 totalCount
+= count
;
1850 if (bundle
->getVerbose())
1851 printf("Found %d custom asset file%s in %s\n",
1852 count
, (count
==1) ? "" : "s", assetDir
);
1856 * If a directory of resource-specific assets was supplied, slurp 'em up.
1858 for (size_t i
=0; i
<dirCount
; i
++) {
1859 const char *res
= resDirs
[i
];
1861 type
= getFileType(res
);
1862 if (type
== kFileTypeNonexistent
) {
1863 fprintf(stderr
, "ERROR: resource directory '%s' does not exist\n", res
);
1864 return UNKNOWN_ERROR
;
1866 if (type
== kFileTypeDirectory
) {
1868 sp
<AaptAssets
> nextOverlay
= new AaptAssets();
1869 current
->setOverlay(nextOverlay
);
1870 current
= nextOverlay
;
1872 count
= current
->slurpResourceTree(bundle
, String8(res
));
1878 totalCount
+= count
;
1881 fprintf(stderr
, "ERROR: '%s' is not a directory\n", res
);
1882 return UNKNOWN_ERROR
;
1888 * Now do any additional raw files.
1890 for (int arg
=0; arg
<N
; arg
++) {
1891 const char* assetDir
= bundle
->getFileSpecEntry(arg
);
1893 FileType type
= getFileType(assetDir
);
1894 if (type
== kFileTypeNonexistent
) {
1895 fprintf(stderr
, "ERROR: input directory '%s' does not exist\n", assetDir
);
1896 return UNKNOWN_ERROR
;
1898 if (type
!= kFileTypeDirectory
) {
1899 fprintf(stderr
, "ERROR: '%s' is not a directory\n", assetDir
);
1900 return UNKNOWN_ERROR
;
1903 String8
assetRoot(assetDir
);
1905 if (bundle
->getVerbose())
1906 printf("Processing raw dir '%s'\n", (const char*) assetDir
);
1909 * Do a recursive traversal of subdir tree. We don't make any
1910 * guarantees about ordering, so we're okay with an inorder search
1911 * using whatever order the OS happens to hand back to us.
1913 count
= slurpFullTree(bundle
, assetRoot
, AaptGroupEntry(), String8());
1915 /* failure; report error and remove archive */
1919 totalCount
+= count
;
1921 if (bundle
->getVerbose())
1922 printf("Found %d asset file%s in %s\n",
1923 count
, (count
==1) ? "" : "s", assetDir
);
1927 if (count
!= NO_ERROR
) {
1937 ssize_t
AaptAssets::slurpFullTree(Bundle
* bundle
, const String8
& srcDir
,
1938 const AaptGroupEntry
& kind
,
1939 const String8
& resType
)
1941 ssize_t res
= AaptDir::slurpFullTree(bundle
, srcDir
, kind
, resType
);
1943 mGroupEntries
.add(kind
);
1949 ssize_t
AaptAssets::slurpResourceTree(Bundle
* bundle
, const String8
& srcDir
)
1953 DIR* dir
= opendir(srcDir
.string());
1955 fprintf(stderr
, "ERROR: opendir(%s): %s\n", srcDir
.string(), strerror(errno
));
1956 return UNKNOWN_ERROR
;
1962 * Run through the directory, looking for dirs that match the
1966 struct dirent
* entry
= readdir(dir
);
1967 if (entry
== NULL
) {
1971 if (isHidden(srcDir
.string(), entry
->d_name
)) {
1975 String8
subdirName(srcDir
);
1976 subdirName
.appendPath(entry
->d_name
);
1978 AaptGroupEntry group
;
1980 bool b
= group
.initFromDirName(entry
->d_name
, &resType
);
1982 fprintf(stderr
, "invalid resource directory name: %s/%s\n", srcDir
.string(),
1988 if (bundle
->getMaxResVersion() != NULL
&& group
.version
.length() != 0) {
1989 int maxResInt
= atoi(bundle
->getMaxResVersion());
1990 const char *verString
= group
.version
.string();
1991 int dirVersionInt
= atoi(verString
+ 1); // skip 'v' in version name
1992 if (dirVersionInt
> maxResInt
) {
1993 fprintf(stderr
, "max res %d, skipping %s\n", maxResInt
, entry
->d_name
);
1998 FileType type
= getFileType(subdirName
.string());
2000 if (type
== kFileTypeDirectory
) {
2001 sp
<AaptDir
> dir
= makeDir(String8(entry
->d_name
));
2002 ssize_t res
= dir
->slurpFullTree(bundle
, subdirName
, group
,
2009 mGroupEntries
.add(group
);
2015 if (bundle
->getVerbose()) {
2016 fprintf(stderr
, " (ignoring file '%s')\n", subdirName
.string());
2032 AaptAssets::slurpResourceZip(Bundle
* bundle
, const char* filename
)
2035 SortedVector
<AaptGroupEntry
> entries
;
2037 ZipFile
* zip
= new ZipFile
;
2038 status_t err
= zip
->open(filename
, ZipFile::kOpenReadOnly
);
2039 if (err
!= NO_ERROR
) {
2040 fprintf(stderr
, "error opening zip file %s\n", filename
);
2046 const int N
= zip
->getNumEntries();
2047 for (int i
=0; i
<N
; i
++) {
2048 ZipEntry
* entry
= zip
->getEntryByIndex(i
);
2049 if (entry
->getDeleted()) {
2053 String8
entryName(entry
->getFileName());
2055 String8 dirName
= entryName
.getPathDir();
2056 sp
<AaptDir
> dir
= dirName
== "" ? this : makeDir(dirName
);
2059 AaptGroupEntry kind
;
2062 if (entryName
.walkPath(&remain
) == kResourceDir
) {
2063 // these are the resources, pull their type out of the directory name
2064 kind
.initFromDirName(remain
.walkPath().string(), &resType
);
2066 // these are untyped and don't have an AaptGroupEntry
2068 if (entries
.indexOf(kind
) < 0) {
2070 mGroupEntries
.add(kind
);
2073 // use the one from the zip file if they both exist.
2074 dir
->removeFile(entryName
.getPathLeaf());
2076 sp
<AaptFile
> file
= new AaptFile(entryName
, kind
, resType
);
2077 status_t err
= dir
->addLeafFile(entryName
.getPathLeaf(), file
);
2078 if (err
!= NO_ERROR
) {
2079 fprintf(stderr
, "err=%s entryName=%s\n", strerror(err
), entryName
.string());
2083 file
->setCompressionMethod(entry
->getCompressionMethod());
2086 if (entryName
== "AndroidManifest.xml") {
2087 printf("AndroidManifest.xml\n");
2089 printf("\n\nfile: %s\n", entryName
.string());
2092 size_t len
= entry
->getUncompressedLen();
2093 void* data
= zip
->uncompress(entry
);
2094 void* buf
= file
->editData(len
);
2095 memcpy(buf
, data
, len
);
2099 const unsigned char* p
= (unsigned char*)data
;
2100 const unsigned char* end
= p
+len
;
2102 for (int i
=0; i
<32 && p
< end
; i
++) {
2103 printf("0x%03x ", i
*0x10 + OFF
);
2104 for (int j
=0; j
<0x10 && p
< end
; j
++) {
2105 printf(" %02x", *p
);
2122 sp
<AaptSymbols
> AaptAssets::getSymbolsFor(const String8
& name
)
2124 sp
<AaptSymbols
> sym
= mSymbols
.valueFor(name
);
2126 sym
= new AaptSymbols();
2127 mSymbols
.add(name
, sym
);
2132 status_t
AaptAssets::buildIncludedResources(Bundle
* bundle
)
2134 if (!mHaveIncludedAssets
) {
2135 // Add in all includes.
2136 const Vector
<const char*>& incl
= bundle
->getPackageIncludes();
2137 const size_t N
=incl
.size();
2138 for (size_t i
=0; i
<N
; i
++) {
2139 if (bundle
->getVerbose())
2140 printf("Including resources from package: %s\n", incl
[i
]);
2141 if (!mIncludedAssets
.addAssetPath(String8(incl
[i
]), NULL
)) {
2142 fprintf(stderr
, "ERROR: Asset package include '%s' not found.\n",
2144 return UNKNOWN_ERROR
;
2147 mHaveIncludedAssets
= true;
2153 status_t
AaptAssets::addIncludedResources(const sp
<AaptFile
>& file
)
2155 const ResTable
& res
= getIncludedResources();
2157 return const_cast<ResTable
&>(res
).add(file
->getData(), file
->getSize(), NULL
);
2160 const ResTable
& AaptAssets::getIncludedResources() const
2162 return mIncludedAssets
.getResources(false);
2165 void AaptAssets::print() const
2167 printf("Locale/Vendor pairs:\n");
2168 const size_t N
=mGroupEntries
.size();
2169 for (size_t i
=0; i
<N
; i
++) {
2171 mGroupEntries
.itemAt(i
).locale
.string(),
2172 mGroupEntries
.itemAt(i
).vendor
.string());
2175 printf("\nFiles:\n");
2179 sp
<AaptDir
> AaptAssets::resDir(const String8
& name
)
2181 const Vector
<sp
<AaptDir
> >& dirs
= mDirs
;
2182 const size_t N
= dirs
.size();
2183 for (size_t i
=0; i
<N
; i
++) {
2184 const sp
<AaptDir
>& d
= dirs
.itemAt(i
);
2185 if (d
->getLeaf() == name
) {
2193 valid_symbol_name(const String8
& symbol
)
2195 static char const * const KEYWORDS
[] = {
2196 "abstract", "assert", "boolean", "break",
2197 "byte", "case", "catch", "char", "class", "const", "continue",
2198 "default", "do", "double", "else", "enum", "extends", "final",
2199 "finally", "float", "for", "goto", "if", "implements", "import",
2200 "instanceof", "int", "interface", "long", "native", "new", "package",
2201 "private", "protected", "public", "return", "short", "static",
2202 "strictfp", "super", "switch", "synchronized", "this", "throw",
2203 "throws", "transient", "try", "void", "volatile", "while",
2204 "true", "false", "null",
2207 const char*const* k
= KEYWORDS
;
2208 const char*const s
= symbol
.string();
2210 if (0 == strcmp(s
, *k
)) {