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
;
916 } else if (strcmp(name
, "television") == 0) {
917 if (out
) out
->uiMode
=
918 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_TYPE
)
919 | ResTable_config::UI_MODE_TYPE_TELEVISION
;
926 bool AaptGroupEntry::getUiModeNightName(const char* name
,
927 ResTable_config
* out
)
929 if (strcmp(name
, kWildcardName
) == 0) {
930 if (out
) out
->uiMode
=
931 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
932 | ResTable_config::UI_MODE_NIGHT_ANY
;
934 } else if (strcmp(name
, "night") == 0) {
935 if (out
) out
->uiMode
=
936 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
937 | ResTable_config::UI_MODE_NIGHT_YES
;
939 } else if (strcmp(name
, "notnight") == 0) {
940 if (out
) out
->uiMode
=
941 (out
->uiMode
&~ResTable_config::MASK_UI_MODE_NIGHT
)
942 | ResTable_config::UI_MODE_NIGHT_NO
;
949 bool AaptGroupEntry::getDensityName(const char* name
,
950 ResTable_config
* out
)
952 if (strcmp(name
, kWildcardName
) == 0) {
953 if (out
) out
->density
= ResTable_config::DENSITY_DEFAULT
;
957 if (strcmp(name
, "nodpi") == 0) {
958 if (out
) out
->density
= ResTable_config::DENSITY_NONE
;
962 if (strcmp(name
, "ldpi") == 0) {
963 if (out
) out
->density
= ResTable_config::DENSITY_LOW
;
967 if (strcmp(name
, "mdpi") == 0) {
968 if (out
) out
->density
= ResTable_config::DENSITY_MEDIUM
;
972 if (strcmp(name
, "hdpi") == 0) {
973 if (out
) out
->density
= ResTable_config::DENSITY_HIGH
;
977 if (strcmp(name
, "xhdpi") == 0) {
978 if (out
) out
->density
= ResTable_config::DENSITY_MEDIUM
*2;
982 char* c
= (char*)name
;
983 while (*c
>= '0' && *c
<= '9') {
987 // check that we have 'dpi' after the last digit.
988 if (toupper(c
[0]) != 'D' ||
989 toupper(c
[1]) != 'P' ||
990 toupper(c
[2]) != 'I' ||
995 // temporarily replace the first letter with \0 to
1004 if (out
) out
->density
= d
;
1011 bool AaptGroupEntry::getTouchscreenName(const char* name
,
1012 ResTable_config
* out
)
1014 if (strcmp(name
, kWildcardName
) == 0) {
1015 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_ANY
;
1017 } else if (strcmp(name
, "notouch") == 0) {
1018 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_NOTOUCH
;
1020 } else if (strcmp(name
, "stylus") == 0) {
1021 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_STYLUS
;
1023 } else if (strcmp(name
, "finger") == 0) {
1024 if (out
) out
->touchscreen
= out
->TOUCHSCREEN_FINGER
;
1031 bool AaptGroupEntry::getKeysHiddenName(const char* name
,
1032 ResTable_config
* out
)
1036 if (strcmp(name
, kWildcardName
) == 0) {
1037 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1038 value
= ResTable_config::KEYSHIDDEN_ANY
;
1039 } else if (strcmp(name
, "keysexposed") == 0) {
1040 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1041 value
= ResTable_config::KEYSHIDDEN_NO
;
1042 } else if (strcmp(name
, "keyshidden") == 0) {
1043 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1044 value
= ResTable_config::KEYSHIDDEN_YES
;
1045 } else if (strcmp(name
, "keyssoft") == 0) {
1046 mask
= ResTable_config::MASK_KEYSHIDDEN
;
1047 value
= ResTable_config::KEYSHIDDEN_SOFT
;
1051 if (out
) out
->inputFlags
= (out
->inputFlags
&~mask
) | value
;
1058 bool AaptGroupEntry::getKeyboardName(const char* name
,
1059 ResTable_config
* out
)
1061 if (strcmp(name
, kWildcardName
) == 0) {
1062 if (out
) out
->keyboard
= out
->KEYBOARD_ANY
;
1064 } else if (strcmp(name
, "nokeys") == 0) {
1065 if (out
) out
->keyboard
= out
->KEYBOARD_NOKEYS
;
1067 } else if (strcmp(name
, "qwerty") == 0) {
1068 if (out
) out
->keyboard
= out
->KEYBOARD_QWERTY
;
1070 } else if (strcmp(name
, "12key") == 0) {
1071 if (out
) out
->keyboard
= out
->KEYBOARD_12KEY
;
1078 bool AaptGroupEntry::getNavHiddenName(const char* name
,
1079 ResTable_config
* out
)
1083 if (strcmp(name
, kWildcardName
) == 0) {
1084 mask
= ResTable_config::MASK_NAVHIDDEN
;
1085 value
= ResTable_config::NAVHIDDEN_ANY
;
1086 } else if (strcmp(name
, "navexposed") == 0) {
1087 mask
= ResTable_config::MASK_NAVHIDDEN
;
1088 value
= ResTable_config::NAVHIDDEN_NO
;
1089 } else if (strcmp(name
, "navhidden") == 0) {
1090 mask
= ResTable_config::MASK_NAVHIDDEN
;
1091 value
= ResTable_config::NAVHIDDEN_YES
;
1095 if (out
) out
->inputFlags
= (out
->inputFlags
&~mask
) | value
;
1102 bool AaptGroupEntry::getNavigationName(const char* name
,
1103 ResTable_config
* out
)
1105 if (strcmp(name
, kWildcardName
) == 0) {
1106 if (out
) out
->navigation
= out
->NAVIGATION_ANY
;
1108 } else if (strcmp(name
, "nonav") == 0) {
1109 if (out
) out
->navigation
= out
->NAVIGATION_NONAV
;
1111 } else if (strcmp(name
, "dpad") == 0) {
1112 if (out
) out
->navigation
= out
->NAVIGATION_DPAD
;
1114 } else if (strcmp(name
, "trackball") == 0) {
1115 if (out
) out
->navigation
= out
->NAVIGATION_TRACKBALL
;
1117 } else if (strcmp(name
, "wheel") == 0) {
1118 if (out
) out
->navigation
= out
->NAVIGATION_WHEEL
;
1125 bool AaptGroupEntry::getScreenSizeName(const char* name
, ResTable_config
* out
)
1127 if (strcmp(name
, kWildcardName
) == 0) {
1129 out
->screenWidth
= out
->SCREENWIDTH_ANY
;
1130 out
->screenHeight
= out
->SCREENHEIGHT_ANY
;
1135 const char* x
= name
;
1136 while (*x
>= '0' && *x
<= '9') x
++;
1137 if (x
== name
|| *x
!= 'x') return false;
1138 String8
xName(name
, x
-name
);
1142 while (*y
>= '0' && *y
<= '9') y
++;
1143 if (y
== name
|| *y
!= 0) return false;
1144 String8
yName(x
, y
-x
);
1146 uint16_t w
= (uint16_t)atoi(xName
.string());
1147 uint16_t h
= (uint16_t)atoi(yName
.string());
1153 out
->screenWidth
= w
;
1154 out
->screenHeight
= h
;
1160 bool AaptGroupEntry::getSmallestScreenWidthDpName(const char* name
, ResTable_config
* out
)
1162 if (strcmp(name
, kWildcardName
) == 0) {
1164 out
->smallestScreenWidthDp
= out
->SCREENWIDTH_ANY
;
1169 if (*name
!= 's') return false;
1171 if (*name
!= 'w') return false;
1173 const char* x
= name
;
1174 while (*x
>= '0' && *x
<= '9') x
++;
1175 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1176 String8
xName(name
, x
-name
);
1179 out
->smallestScreenWidthDp
= (uint16_t)atoi(xName
.string());
1185 bool AaptGroupEntry::getScreenWidthDpName(const char* name
, ResTable_config
* out
)
1187 if (strcmp(name
, kWildcardName
) == 0) {
1189 out
->screenWidthDp
= out
->SCREENWIDTH_ANY
;
1194 if (*name
!= 'w') return false;
1196 const char* x
= name
;
1197 while (*x
>= '0' && *x
<= '9') x
++;
1198 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1199 String8
xName(name
, x
-name
);
1202 out
->screenWidthDp
= (uint16_t)atoi(xName
.string());
1208 bool AaptGroupEntry::getScreenHeightDpName(const char* name
, ResTable_config
* out
)
1210 if (strcmp(name
, kWildcardName
) == 0) {
1212 out
->screenHeightDp
= out
->SCREENWIDTH_ANY
;
1217 if (*name
!= 'h') return false;
1219 const char* x
= name
;
1220 while (*x
>= '0' && *x
<= '9') x
++;
1221 if (x
== name
|| x
[0] != 'd' || x
[1] != 'p' || x
[2] != 0) return false;
1222 String8
xName(name
, x
-name
);
1225 out
->screenHeightDp
= (uint16_t)atoi(xName
.string());
1231 bool AaptGroupEntry::getVersionName(const char* name
, ResTable_config
* out
)
1233 if (strcmp(name
, kWildcardName
) == 0) {
1235 out
->sdkVersion
= out
->SDKVERSION_ANY
;
1236 out
->minorVersion
= out
->MINORVERSION_ANY
;
1246 const char* s
= name
;
1247 while (*s
>= '0' && *s
<= '9') s
++;
1248 if (s
== name
|| *s
!= 0) return false;
1249 String8
sdkName(name
, s
-name
);
1252 out
->sdkVersion
= (uint16_t)atoi(sdkName
.string());
1253 out
->minorVersion
= 0;
1259 int AaptGroupEntry::compare(const AaptGroupEntry
& o
) const
1261 int v
= mcc
.compare(o
.mcc
);
1262 if (v
== 0) v
= mnc
.compare(o
.mnc
);
1263 if (v
== 0) v
= locale
.compare(o
.locale
);
1264 if (v
== 0) v
= vendor
.compare(o
.vendor
);
1265 if (v
== 0) v
= smallestScreenWidthDp
.compare(o
.smallestScreenWidthDp
);
1266 if (v
== 0) v
= screenWidthDp
.compare(o
.screenWidthDp
);
1267 if (v
== 0) v
= screenHeightDp
.compare(o
.screenHeightDp
);
1268 if (v
== 0) v
= screenLayoutSize
.compare(o
.screenLayoutSize
);
1269 if (v
== 0) v
= screenLayoutLong
.compare(o
.screenLayoutLong
);
1270 if (v
== 0) v
= orientation
.compare(o
.orientation
);
1271 if (v
== 0) v
= uiModeType
.compare(o
.uiModeType
);
1272 if (v
== 0) v
= uiModeNight
.compare(o
.uiModeNight
);
1273 if (v
== 0) v
= density
.compare(o
.density
);
1274 if (v
== 0) v
= touchscreen
.compare(o
.touchscreen
);
1275 if (v
== 0) v
= keysHidden
.compare(o
.keysHidden
);
1276 if (v
== 0) v
= keyboard
.compare(o
.keyboard
);
1277 if (v
== 0) v
= navHidden
.compare(o
.navHidden
);
1278 if (v
== 0) v
= navigation
.compare(o
.navigation
);
1279 if (v
== 0) v
= screenSize
.compare(o
.screenSize
);
1280 if (v
== 0) v
= version
.compare(o
.version
);
1284 ResTable_config
AaptGroupEntry::toParams() const
1286 ResTable_config params
;
1287 memset(¶ms
, 0, sizeof(params
));
1288 getMccName(mcc
.string(), ¶ms
);
1289 getMncName(mnc
.string(), ¶ms
);
1290 getLocaleName(locale
.string(), ¶ms
);
1291 getSmallestScreenWidthDpName(smallestScreenWidthDp
.string(), ¶ms
);
1292 getScreenWidthDpName(screenWidthDp
.string(), ¶ms
);
1293 getScreenHeightDpName(screenHeightDp
.string(), ¶ms
);
1294 getScreenLayoutSizeName(screenLayoutSize
.string(), ¶ms
);
1295 getScreenLayoutLongName(screenLayoutLong
.string(), ¶ms
);
1296 getOrientationName(orientation
.string(), ¶ms
);
1297 getUiModeTypeName(uiModeType
.string(), ¶ms
);
1298 getUiModeNightName(uiModeNight
.string(), ¶ms
);
1299 getDensityName(density
.string(), ¶ms
);
1300 getTouchscreenName(touchscreen
.string(), ¶ms
);
1301 getKeysHiddenName(keysHidden
.string(), ¶ms
);
1302 getKeyboardName(keyboard
.string(), ¶ms
);
1303 getNavHiddenName(navHidden
.string(), ¶ms
);
1304 getNavigationName(navigation
.string(), ¶ms
);
1305 getScreenSizeName(screenSize
.string(), ¶ms
);
1306 getVersionName(version
.string(), ¶ms
);
1308 // Fix up version number based on specified parameters.
1310 if (params
.smallestScreenWidthDp
!= ResTable_config::SCREENWIDTH_ANY
1311 || params
.screenWidthDp
!= ResTable_config::SCREENWIDTH_ANY
1312 || params
.screenHeightDp
!= ResTable_config::SCREENHEIGHT_ANY
) {
1313 minSdk
= SDK_HONEYCOMB_MR2
;
1314 } else if ((params
.uiMode
&ResTable_config::MASK_UI_MODE_TYPE
)
1315 != ResTable_config::UI_MODE_TYPE_ANY
1316 || (params
.uiMode
&ResTable_config::MASK_UI_MODE_NIGHT
)
1317 != ResTable_config::UI_MODE_NIGHT_ANY
) {
1319 } else if ((params
.screenLayout
&ResTable_config::MASK_SCREENSIZE
)
1320 != ResTable_config::SCREENSIZE_ANY
1321 || (params
.screenLayout
&ResTable_config::MASK_SCREENLONG
)
1322 != ResTable_config::SCREENLONG_ANY
1323 || params
.density
!= ResTable_config::DENSITY_DEFAULT
) {
1327 if (minSdk
> params
.sdkVersion
) {
1328 params
.sdkVersion
= minSdk
;
1334 // =========================================================================
1335 // =========================================================================
1336 // =========================================================================
1338 void* AaptFile::editData(size_t size
)
1340 if (size
<= mBufferSize
) {
1344 size_t allocSize
= (size
*3)/2;
1345 void* buf
= realloc(mData
, allocSize
);
1351 mBufferSize
= allocSize
;
1355 void* AaptFile::editData(size_t* outSize
)
1358 *outSize
= mDataSize
;
1363 void* AaptFile::padData(size_t wordSize
)
1365 const size_t extra
= mDataSize%wordSize
;
1370 size_t initial
= mDataSize
;
1371 void* data
= editData(initial
+(wordSize
-extra
));
1373 memset(((uint8_t*)data
) + initial
, 0, wordSize
-extra
);
1378 status_t
AaptFile::writeData(const void* data
, size_t size
)
1380 size_t end
= mDataSize
;
1381 size_t total
= size
+ end
;
1382 void* buf
= editData(total
);
1384 return UNKNOWN_ERROR
;
1386 memcpy(((char*)buf
)+end
, data
, size
);
1390 void AaptFile::clearData()
1392 if (mData
!= NULL
) free(mData
);
1398 String8
AaptFile::getPrintableSource() const
1401 String8
name(mGroupEntry
.locale
.string());
1402 name
.appendPath(mGroupEntry
.vendor
.string());
1403 name
.appendPath(mPath
);
1404 name
.append(" #generated");
1410 // =========================================================================
1411 // =========================================================================
1412 // =========================================================================
1414 status_t
AaptGroup::addFile(const sp
<AaptFile
>& file
)
1416 if (mFiles
.indexOfKey(file
->getGroupEntry()) < 0) {
1417 file
->mPath
= mPath
;
1418 mFiles
.add(file
->getGroupEntry(), file
);
1422 SourcePos(file
->getSourceFile(), -1).error("Duplicate file.\n%s: Original is here.",
1423 getPrintableSource().string());
1424 return UNKNOWN_ERROR
;
1427 void AaptGroup::removeFile(size_t index
)
1429 mFiles
.removeItemsAt(index
);
1432 void AaptGroup::print() const
1434 printf(" %s\n", getPath().string());
1435 const size_t N
=mFiles
.size();
1437 for (i
=0; i
<N
; i
++) {
1438 sp
<AaptFile
> file
= mFiles
.valueAt(i
);
1439 const AaptGroupEntry
& e
= file
->getGroupEntry();
1440 if (file
->hasData()) {
1441 printf(" Gen: (%s) %d bytes\n", e
.toString().string(),
1442 (int)file
->getSize());
1444 printf(" Src: %s\n", file
->getPrintableSource().string());
1449 String8
AaptGroup::getPrintableSource() const
1451 if (mFiles
.size() > 0) {
1452 // Arbitrarily pull the first source file out of the list.
1453 return mFiles
.valueAt(0)->getPrintableSource();
1456 // Should never hit this case, but to be safe...
1461 // =========================================================================
1462 // =========================================================================
1463 // =========================================================================
1465 status_t
AaptDir::addFile(const String8
& name
, const sp
<AaptGroup
>& file
)
1467 if (mFiles
.indexOfKey(name
) >= 0) {
1468 return ALREADY_EXISTS
;
1470 mFiles
.add(name
, file
);
1474 status_t
AaptDir::addDir(const String8
& name
, const sp
<AaptDir
>& dir
)
1476 if (mDirs
.indexOfKey(name
) >= 0) {
1477 return ALREADY_EXISTS
;
1479 mDirs
.add(name
, dir
);
1483 sp
<AaptDir
> AaptDir::makeDir(const String8
& path
)
1486 String8 remain
= path
;
1488 sp
<AaptDir
> subdir
= this;
1489 while (name
= remain
.walkPath(&remain
), remain
!= "") {
1490 subdir
= subdir
->makeDir(name
);
1493 ssize_t i
= subdir
->mDirs
.indexOfKey(name
);
1495 return subdir
->mDirs
.valueAt(i
);
1497 sp
<AaptDir
> dir
= new AaptDir(name
, subdir
->mPath
.appendPathCopy(name
));
1498 subdir
->mDirs
.add(name
, dir
);
1502 void AaptDir::removeFile(const String8
& name
)
1504 mFiles
.removeItem(name
);
1507 void AaptDir::removeDir(const String8
& name
)
1509 mDirs
.removeItem(name
);
1512 status_t
AaptDir::renameFile(const sp
<AaptFile
>& file
, const String8
& newName
)
1514 sp
<AaptGroup
> origGroup
;
1516 // Find and remove the given file with shear, brute force!
1517 const size_t NG
= mFiles
.size();
1519 for (i
=0; origGroup
== NULL
&& i
<NG
; i
++) {
1520 sp
<AaptGroup
> g
= mFiles
.valueAt(i
);
1521 const size_t NF
= g
->getFiles().size();
1522 for (size_t j
=0; j
<NF
; j
++) {
1523 if (g
->getFiles().valueAt(j
) == file
) {
1527 mFiles
.removeItemsAt(i
);
1534 //printf("Renaming %s to %s\n", file->getPath().getPathName(), newName.string());
1536 // Place the file under its new name.
1537 if (origGroup
!= NULL
) {
1538 return addLeafFile(newName
, file
);
1544 status_t
AaptDir::addLeafFile(const String8
& leafName
, const sp
<AaptFile
>& file
)
1546 sp
<AaptGroup
> group
;
1547 if (mFiles
.indexOfKey(leafName
) >= 0) {
1548 group
= mFiles
.valueFor(leafName
);
1550 group
= new AaptGroup(leafName
, mPath
.appendPathCopy(leafName
));
1551 mFiles
.add(leafName
, group
);
1554 return group
->addFile(file
);
1557 ssize_t
AaptDir::slurpFullTree(Bundle
* bundle
, const String8
& srcDir
,
1558 const AaptGroupEntry
& kind
, const String8
& resType
)
1560 Vector
<String8
> fileNames
;
1565 dir
= opendir(srcDir
.string());
1567 fprintf(stderr
, "ERROR: opendir(%s): %s\n", srcDir
.string(), strerror(errno
));
1568 return UNKNOWN_ERROR
;
1572 * Slurp the filenames out of the directory.
1575 struct dirent
* entry
;
1577 entry
= readdir(dir
);
1581 if (isHidden(srcDir
.string(), entry
->d_name
))
1584 fileNames
.add(String8(entry
->d_name
));
1593 * Stash away the files and recursively descend into subdirectories.
1595 const size_t N
= fileNames
.size();
1597 for (i
= 0; i
< N
; i
++) {
1598 String8
pathName(srcDir
);
1601 pathName
.appendPath(fileNames
[i
].string());
1602 type
= getFileType(pathName
.string());
1603 if (type
== kFileTypeDirectory
) {
1605 bool notAdded
= false;
1606 if (mDirs
.indexOfKey(fileNames
[i
]) >= 0) {
1607 subdir
= mDirs
.valueFor(fileNames
[i
]);
1609 subdir
= new AaptDir(fileNames
[i
], mPath
.appendPathCopy(fileNames
[i
]));
1612 ssize_t res
= subdir
->slurpFullTree(bundle
, pathName
, kind
,
1614 if (res
< NO_ERROR
) {
1617 if (res
> 0 && notAdded
) {
1618 mDirs
.add(fileNames
[i
], subdir
);
1621 } else if (type
== kFileTypeRegular
) {
1622 sp
<AaptFile
> file
= new AaptFile(pathName
, kind
, resType
);
1623 status_t err
= addLeafFile(fileNames
[i
], file
);
1624 if (err
!= NO_ERROR
) {
1631 if (bundle
->getVerbose())
1632 printf(" (ignoring non-file/dir '%s')\n", pathName
.string());
1639 status_t
AaptDir::validate() const
1641 const size_t NF
= mFiles
.size();
1642 const size_t ND
= mDirs
.size();
1644 for (i
= 0; i
< NF
; i
++) {
1645 if (!validateFileName(mFiles
.valueAt(i
)->getLeaf().string())) {
1646 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1647 "Invalid filename. Unable to add.");
1648 return UNKNOWN_ERROR
;
1652 for (j
= i
+1; j
< NF
; j
++) {
1653 if (strcasecmp(mFiles
.valueAt(i
)->getLeaf().string(),
1654 mFiles
.valueAt(j
)->getLeaf().string()) == 0) {
1655 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1656 "File is case-insensitive equivalent to: %s",
1657 mFiles
.valueAt(j
)->getPrintableSource().string());
1658 return UNKNOWN_ERROR
;
1661 // TODO: if ".gz", check for non-.gz; if non-, check for ".gz"
1662 // (this is mostly caught by the "marked" stuff, below)
1665 for (j
= 0; j
< ND
; j
++) {
1666 if (strcasecmp(mFiles
.valueAt(i
)->getLeaf().string(),
1667 mDirs
.valueAt(j
)->getLeaf().string()) == 0) {
1668 SourcePos(mFiles
.valueAt(i
)->getPrintableSource(), -1).error(
1669 "File conflicts with dir from: %s",
1670 mDirs
.valueAt(j
)->getPrintableSource().string());
1671 return UNKNOWN_ERROR
;
1676 for (i
= 0; i
< ND
; i
++) {
1677 if (!validateFileName(mDirs
.valueAt(i
)->getLeaf().string())) {
1678 SourcePos(mDirs
.valueAt(i
)->getPrintableSource(), -1).error(
1679 "Invalid directory name, unable to add.");
1680 return UNKNOWN_ERROR
;
1684 for (j
= i
+1; j
< ND
; j
++) {
1685 if (strcasecmp(mDirs
.valueAt(i
)->getLeaf().string(),
1686 mDirs
.valueAt(j
)->getLeaf().string()) == 0) {
1687 SourcePos(mDirs
.valueAt(i
)->getPrintableSource(), -1).error(
1688 "Directory is case-insensitive equivalent to: %s",
1689 mDirs
.valueAt(j
)->getPrintableSource().string());
1690 return UNKNOWN_ERROR
;
1694 status_t err
= mDirs
.valueAt(i
)->validate();
1695 if (err
!= NO_ERROR
) {
1703 void AaptDir::print() const
1705 const size_t ND
=getDirs().size();
1707 for (i
=0; i
<ND
; i
++) {
1708 getDirs().valueAt(i
)->print();
1711 const size_t NF
=getFiles().size();
1712 for (i
=0; i
<NF
; i
++) {
1713 getFiles().valueAt(i
)->print();
1717 String8
AaptDir::getPrintableSource() const
1719 if (mFiles
.size() > 0) {
1720 // Arbitrarily pull the first file out of the list as the source dir.
1721 return mFiles
.valueAt(0)->getPrintableSource().getPathDir();
1723 if (mDirs
.size() > 0) {
1724 // Or arbitrarily pull the first dir out of the list as the source dir.
1725 return mDirs
.valueAt(0)->getPrintableSource().getPathDir();
1728 // Should never hit this case, but to be safe...
1733 // =========================================================================
1734 // =========================================================================
1735 // =========================================================================
1737 sp
<AaptFile
> AaptAssets::addFile(
1738 const String8
& filePath
, const AaptGroupEntry
& entry
,
1739 const String8
& srcDir
, sp
<AaptGroup
>* outGroup
,
1740 const String8
& resType
)
1742 sp
<AaptDir
> dir
= this;
1743 sp
<AaptGroup
> group
;
1745 String8 root
, remain(filePath
), partialPath
;
1746 while (remain
.length() > 0) {
1747 root
= remain
.walkPath(&remain
);
1748 partialPath
.appendPath(root
);
1750 const String8
rootStr(root
);
1752 if (remain
.length() == 0) {
1753 ssize_t i
= dir
->getFiles().indexOfKey(rootStr
);
1755 group
= dir
->getFiles().valueAt(i
);
1757 group
= new AaptGroup(rootStr
, filePath
);
1758 status_t res
= dir
->addFile(rootStr
, group
);
1759 if (res
!= NO_ERROR
) {
1763 file
= new AaptFile(srcDir
.appendPathCopy(filePath
), entry
, resType
);
1764 status_t res
= group
->addFile(file
);
1765 if (res
!= NO_ERROR
) {
1771 ssize_t i
= dir
->getDirs().indexOfKey(rootStr
);
1773 dir
= dir
->getDirs().valueAt(i
);
1775 sp
<AaptDir
> subdir
= new AaptDir(rootStr
, partialPath
);
1776 status_t res
= dir
->addDir(rootStr
, subdir
);
1777 if (res
!= NO_ERROR
) {
1785 mGroupEntries
.add(entry
);
1786 if (outGroup
) *outGroup
= group
;
1790 void AaptAssets::addResource(const String8
& leafName
, const String8
& path
,
1791 const sp
<AaptFile
>& file
, const String8
& resType
)
1793 sp
<AaptDir
> res
= AaptDir::makeDir(kResString
);
1794 String8 dirname
= file
->getGroupEntry().toDirName(resType
);
1795 sp
<AaptDir
> subdir
= res
->makeDir(dirname
);
1796 sp
<AaptGroup
> grr
= new AaptGroup(leafName
, path
);
1799 subdir
->addFile(leafName
, grr
);
1803 ssize_t
AaptAssets::slurpFromArgs(Bundle
* bundle
)
1808 const Vector
<const char *>& resDirs
= bundle
->getResourceSourceDirs();
1809 const size_t dirCount
=resDirs
.size();
1810 sp
<AaptAssets
> current
= this;
1812 const int N
= bundle
->getFileSpecCount();
1815 * If a package manifest was specified, include that first.
1817 if (bundle
->getAndroidManifestFile() != NULL
) {
1818 // place at root of zip.
1819 String8
srcFile(bundle
->getAndroidManifestFile());
1820 addFile(srcFile
.getPathLeaf(), AaptGroupEntry(), srcFile
.getPathDir(),
1826 * If a directory of custom assets was supplied, slurp 'em up.
1828 if (bundle
->getAssetSourceDir()) {
1829 const char* assetDir
= bundle
->getAssetSourceDir();
1831 FileType type
= getFileType(assetDir
);
1832 if (type
== kFileTypeNonexistent
) {
1833 fprintf(stderr
, "ERROR: asset directory '%s' does not exist\n", assetDir
);
1834 return UNKNOWN_ERROR
;
1836 if (type
!= kFileTypeDirectory
) {
1837 fprintf(stderr
, "ERROR: '%s' is not a directory\n", assetDir
);
1838 return UNKNOWN_ERROR
;
1841 String8
assetRoot(assetDir
);
1842 sp
<AaptDir
> assetAaptDir
= makeDir(String8(kAssetDir
));
1843 AaptGroupEntry group
;
1844 count
= assetAaptDir
->slurpFullTree(bundle
, assetRoot
, group
,
1851 mGroupEntries
.add(group
);
1853 totalCount
+= count
;
1855 if (bundle
->getVerbose())
1856 printf("Found %d custom asset file%s in %s\n",
1857 count
, (count
==1) ? "" : "s", assetDir
);
1861 * If a directory of resource-specific assets was supplied, slurp 'em up.
1863 for (size_t i
=0; i
<dirCount
; i
++) {
1864 const char *res
= resDirs
[i
];
1866 type
= getFileType(res
);
1867 if (type
== kFileTypeNonexistent
) {
1868 fprintf(stderr
, "ERROR: resource directory '%s' does not exist\n", res
);
1869 return UNKNOWN_ERROR
;
1871 if (type
== kFileTypeDirectory
) {
1873 sp
<AaptAssets
> nextOverlay
= new AaptAssets();
1874 current
->setOverlay(nextOverlay
);
1875 current
= nextOverlay
;
1877 count
= current
->slurpResourceTree(bundle
, String8(res
));
1883 totalCount
+= count
;
1886 fprintf(stderr
, "ERROR: '%s' is not a directory\n", res
);
1887 return UNKNOWN_ERROR
;
1893 * Now do any additional raw files.
1895 for (int arg
=0; arg
<N
; arg
++) {
1896 const char* assetDir
= bundle
->getFileSpecEntry(arg
);
1898 FileType type
= getFileType(assetDir
);
1899 if (type
== kFileTypeNonexistent
) {
1900 fprintf(stderr
, "ERROR: input directory '%s' does not exist\n", assetDir
);
1901 return UNKNOWN_ERROR
;
1903 if (type
!= kFileTypeDirectory
) {
1904 fprintf(stderr
, "ERROR: '%s' is not a directory\n", assetDir
);
1905 return UNKNOWN_ERROR
;
1908 String8
assetRoot(assetDir
);
1910 if (bundle
->getVerbose())
1911 printf("Processing raw dir '%s'\n", (const char*) assetDir
);
1914 * Do a recursive traversal of subdir tree. We don't make any
1915 * guarantees about ordering, so we're okay with an inorder search
1916 * using whatever order the OS happens to hand back to us.
1918 count
= slurpFullTree(bundle
, assetRoot
, AaptGroupEntry(), String8());
1920 /* failure; report error and remove archive */
1924 totalCount
+= count
;
1926 if (bundle
->getVerbose())
1927 printf("Found %d asset file%s in %s\n",
1928 count
, (count
==1) ? "" : "s", assetDir
);
1932 if (count
!= NO_ERROR
) {
1942 ssize_t
AaptAssets::slurpFullTree(Bundle
* bundle
, const String8
& srcDir
,
1943 const AaptGroupEntry
& kind
,
1944 const String8
& resType
)
1946 ssize_t res
= AaptDir::slurpFullTree(bundle
, srcDir
, kind
, resType
);
1948 mGroupEntries
.add(kind
);
1954 ssize_t
AaptAssets::slurpResourceTree(Bundle
* bundle
, const String8
& srcDir
)
1958 DIR* dir
= opendir(srcDir
.string());
1960 fprintf(stderr
, "ERROR: opendir(%s): %s\n", srcDir
.string(), strerror(errno
));
1961 return UNKNOWN_ERROR
;
1967 * Run through the directory, looking for dirs that match the
1971 struct dirent
* entry
= readdir(dir
);
1972 if (entry
== NULL
) {
1976 if (isHidden(srcDir
.string(), entry
->d_name
)) {
1980 String8
subdirName(srcDir
);
1981 subdirName
.appendPath(entry
->d_name
);
1983 AaptGroupEntry group
;
1985 bool b
= group
.initFromDirName(entry
->d_name
, &resType
);
1987 fprintf(stderr
, "invalid resource directory name: %s/%s\n", srcDir
.string(),
1993 if (bundle
->getMaxResVersion() != NULL
&& group
.version
.length() != 0) {
1994 int maxResInt
= atoi(bundle
->getMaxResVersion());
1995 const char *verString
= group
.version
.string();
1996 int dirVersionInt
= atoi(verString
+ 1); // skip 'v' in version name
1997 if (dirVersionInt
> maxResInt
) {
1998 fprintf(stderr
, "max res %d, skipping %s\n", maxResInt
, entry
->d_name
);
2003 FileType type
= getFileType(subdirName
.string());
2005 if (type
== kFileTypeDirectory
) {
2006 sp
<AaptDir
> dir
= makeDir(String8(entry
->d_name
));
2007 ssize_t res
= dir
->slurpFullTree(bundle
, subdirName
, group
,
2014 mGroupEntries
.add(group
);
2020 if (bundle
->getVerbose()) {
2021 fprintf(stderr
, " (ignoring file '%s')\n", subdirName
.string());
2037 AaptAssets::slurpResourceZip(Bundle
* bundle
, const char* filename
)
2040 SortedVector
<AaptGroupEntry
> entries
;
2042 ZipFile
* zip
= new ZipFile
;
2043 status_t err
= zip
->open(filename
, ZipFile::kOpenReadOnly
);
2044 if (err
!= NO_ERROR
) {
2045 fprintf(stderr
, "error opening zip file %s\n", filename
);
2051 const int N
= zip
->getNumEntries();
2052 for (int i
=0; i
<N
; i
++) {
2053 ZipEntry
* entry
= zip
->getEntryByIndex(i
);
2054 if (entry
->getDeleted()) {
2058 String8
entryName(entry
->getFileName());
2060 String8 dirName
= entryName
.getPathDir();
2061 sp
<AaptDir
> dir
= dirName
== "" ? this : makeDir(dirName
);
2064 AaptGroupEntry kind
;
2067 if (entryName
.walkPath(&remain
) == kResourceDir
) {
2068 // these are the resources, pull their type out of the directory name
2069 kind
.initFromDirName(remain
.walkPath().string(), &resType
);
2071 // these are untyped and don't have an AaptGroupEntry
2073 if (entries
.indexOf(kind
) < 0) {
2075 mGroupEntries
.add(kind
);
2078 // use the one from the zip file if they both exist.
2079 dir
->removeFile(entryName
.getPathLeaf());
2081 sp
<AaptFile
> file
= new AaptFile(entryName
, kind
, resType
);
2082 status_t err
= dir
->addLeafFile(entryName
.getPathLeaf(), file
);
2083 if (err
!= NO_ERROR
) {
2084 fprintf(stderr
, "err=%s entryName=%s\n", strerror(err
), entryName
.string());
2088 file
->setCompressionMethod(entry
->getCompressionMethod());
2091 if (entryName
== "AndroidManifest.xml") {
2092 printf("AndroidManifest.xml\n");
2094 printf("\n\nfile: %s\n", entryName
.string());
2097 size_t len
= entry
->getUncompressedLen();
2098 void* data
= zip
->uncompress(entry
);
2099 void* buf
= file
->editData(len
);
2100 memcpy(buf
, data
, len
);
2104 const unsigned char* p
= (unsigned char*)data
;
2105 const unsigned char* end
= p
+len
;
2107 for (int i
=0; i
<32 && p
< end
; i
++) {
2108 printf("0x%03x ", i
*0x10 + OFF
);
2109 for (int j
=0; j
<0x10 && p
< end
; j
++) {
2110 printf(" %02x", *p
);
2127 sp
<AaptSymbols
> AaptAssets::getSymbolsFor(const String8
& name
)
2129 sp
<AaptSymbols
> sym
= mSymbols
.valueFor(name
);
2131 sym
= new AaptSymbols();
2132 mSymbols
.add(name
, sym
);
2137 status_t
AaptAssets::buildIncludedResources(Bundle
* bundle
)
2139 if (!mHaveIncludedAssets
) {
2140 // Add in all includes.
2141 const Vector
<const char*>& incl
= bundle
->getPackageIncludes();
2142 const size_t N
=incl
.size();
2143 for (size_t i
=0; i
<N
; i
++) {
2144 if (bundle
->getVerbose())
2145 printf("Including resources from package: %s\n", incl
[i
]);
2146 if (!mIncludedAssets
.addAssetPath(String8(incl
[i
]), NULL
)) {
2147 fprintf(stderr
, "ERROR: Asset package include '%s' not found.\n",
2149 return UNKNOWN_ERROR
;
2152 mHaveIncludedAssets
= true;
2158 status_t
AaptAssets::addIncludedResources(const sp
<AaptFile
>& file
)
2160 const ResTable
& res
= getIncludedResources();
2162 return const_cast<ResTable
&>(res
).add(file
->getData(), file
->getSize(), NULL
);
2165 const ResTable
& AaptAssets::getIncludedResources() const
2167 return mIncludedAssets
.getResources(false);
2170 void AaptAssets::print() const
2172 printf("Locale/Vendor pairs:\n");
2173 const size_t N
=mGroupEntries
.size();
2174 for (size_t i
=0; i
<N
; i
++) {
2176 mGroupEntries
.itemAt(i
).locale
.string(),
2177 mGroupEntries
.itemAt(i
).vendor
.string());
2180 printf("\nFiles:\n");
2184 sp
<AaptDir
> AaptAssets::resDir(const String8
& name
)
2186 const Vector
<sp
<AaptDir
> >& dirs
= mDirs
;
2187 const size_t N
= dirs
.size();
2188 for (size_t i
=0; i
<N
; i
++) {
2189 const sp
<AaptDir
>& d
= dirs
.itemAt(i
);
2190 if (d
->getLeaf() == name
) {
2198 valid_symbol_name(const String8
& symbol
)
2200 static char const * const KEYWORDS
[] = {
2201 "abstract", "assert", "boolean", "break",
2202 "byte", "case", "catch", "char", "class", "const", "continue",
2203 "default", "do", "double", "else", "enum", "extends", "final",
2204 "finally", "float", "for", "goto", "if", "implements", "import",
2205 "instanceof", "int", "interface", "long", "native", "new", "package",
2206 "private", "protected", "public", "return", "short", "static",
2207 "strictfp", "super", "switch", "synchronized", "this", "throw",
2208 "throws", "transient", "try", "void", "volatile", "while",
2209 "true", "false", "null",
2212 const char*const* k
= KEYWORDS
;
2213 const char*const s
= symbol
.string();
2215 if (0 == strcmp(s
, *k
)) {