Code cleanup of 2013

Signed-off-by: Connor Tumbleson <connor.tumbleson@gmail.com>
This commit is contained in:
Connor Tumbleson 2013-02-12 21:12:17 -06:00
parent f504ceca43
commit e82c0754de
71 changed files with 7649 additions and 7444 deletions

View File

@ -36,8 +36,8 @@ import java.util.logging.*;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class Main {
public static void main(String[] args)
throws IOException, InterruptedException, BrutException {
public static void main(String[] args) throws IOException,
InterruptedException, BrutException {
try {
Verbosity verbosity = Verbosity.NORMAL;
int i;
@ -48,7 +48,7 @@ public class Main {
version_print();
System.exit(1);
}
if (! opt.startsWith("-")) {
if (!opt.startsWith("-")) {
break;
}
if ("-v".equals(opt) || "--verbose".equals(opt)) {
@ -97,7 +97,7 @@ public class Main {
int i;
for (i = 0; i < args.length; i++) {
String opt = args[i];
if (! opt.startsWith("-")) {
if (!opt.startsWith("-")) {
break;
}
if ("-s".equals(opt) || "--no-src".equals(opt)) {
@ -132,8 +132,8 @@ public class Main {
outName = args[i + 1];
} else if (args.length == i + 1) {
outName = args[i];
outName = outName.endsWith(".apk") ?
outName.substring(0, outName.length() - 4) : outName + ".out";
outName = outName.endsWith(".apk") ? outName.substring(0,
outName.length() - 4) : outName + ".out";
outName = new File(outName).getName();
} else {
throw new InvalidArgsError();
@ -145,24 +145,26 @@ public class Main {
try {
decoder.decode();
} catch (OutDirExistsException ex) {
System.out.println(
"Destination directory (" + outDir.getAbsolutePath() + ") " +
"already exists. Use -f switch if you want to overwrite it.");
System.out
.println("Destination directory ("
+ outDir.getAbsolutePath()
+ ") "
+ "already exists. Use -f switch if you want to overwrite it.");
System.exit(1);
} catch (InFileNotFoundException ex) {
System.out.println(
"Input file (" + args[i] + ") " +
"was not found or was not readable.");
System.out.println("Input file (" + args[i] + ") "
+ "was not found or was not readable.");
System.exit(1);
} catch (CantFindFrameworkResException ex) {
System.out.println(
"Can't find framework resources for package of id: " +
String.valueOf(ex.getPkgId()) + ". You must install proper " +
"framework files, see project website for more info.");
System.out
.println("Can't find framework resources for package of id: "
+ String.valueOf(ex.getPkgId())
+ ". You must install proper "
+ "framework files, see project website for more info.");
System.exit(1);
} catch (IOException ex) {
System.out.println(
"Could not modify file. Please ensure you have permission.");
System.out
.println("Could not modify file. Please ensure you have permission.");
System.exit(1);
}
@ -185,7 +187,7 @@ public class Main {
String mAaptPath = "";
for (i = 0; i < args.length; i++) {
String opt = args[i];
if (! opt.startsWith("-")) {
if (!opt.startsWith("-")) {
break;
}
if ("-f".equals(opt) || "--force-all".equals(opt)) {
@ -225,7 +227,8 @@ public class Main {
throw new InvalidArgsError();
}
new Androlib().build(new File(appDirName), outFile, flags, mOrigApk, mAaptPath);
new Androlib().build(new File(appDirName), outFile, flags, mOrigApk,
mAaptPath);
}
private static void cmdInstallFramework(String[] args)
@ -264,74 +267,77 @@ public class Main {
}
private static void version_print() {
System.out.println(
Androlib.getVersion());
System.out.println(Androlib.getVersion());
}
private static void usage() {
System.out.println(
"Apktool v" + Androlib.getVersion() + " - a tool for reengineering Android apk files\n" +
"Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>\n" +
"with smali v" + ApktoolProperties.get("smaliVersion") +
", and baksmali v" + ApktoolProperties.get("baksmaliVersion") + "\n" +
"Updated by @iBotPeaches <connor.tumbleson@gmail.com> \n" +
"Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n" +
"\n" +
"Usage: apktool [-q|--quiet OR -v|--verbose] COMMAND [...]\n" +
"\n" +
"COMMANDs are:\n" +
"\n" +
" d[ecode] [OPTS] <file.apk> [<dir>]\n" +
" Decode <file.apk> to <dir>.\n" +
"\n" +
" OPTS:\n" +
"\n" +
" -s, --no-src\n" +
" Do not decode sources.\n" +
" -r, --no-res\n" +
" Do not decode resources.\n" +
" -d, --debug\n" +
" Decode in debug mode. Check project page for more info.\n" +
" -b, --no-debug-info\n" +
" Baksmali -- don't write out debug info (.local, .param, .line, etc.)\n" +
" -f, --force\n" +
" Force delete destination directory.\n" +
" -t <tag>, --frame-tag <tag>\n" +
" Try to use framework files tagged by <tag>.\n" +
" --frame-path <dir>\n" +
" Use the specified directory for framework files\n" +
" --keep-broken-res\n" +
" Use if there was an error and some resources were dropped, e.g.:\n" +
" \"Invalid config flags detected. Dropping resources\", but you\n" +
" want to decode them anyway, even with errors. You will have to\n" +
" fix them manually before building." +
"\n\n" +
" b[uild] [OPTS] [<app_path>] [<out_file>]\n" +
" Build an apk from already decoded application located in <app_path>.\n" +
"\n" +
" It will automatically detect, whether files was changed and perform\n" +
" needed steps only.\n" +
"\n" +
" If you omit <app_path> then current directory will be used.\n" +
" If you omit <out_file> then <app_path>/dist/<name_of_original.apk>\n" +
" will be used.\n" +
"\n" +
" OPTS:\n" +
"\n" +
" -f, --force-all\n" +
" Skip changes detection and build all files.\n" +
" -d, --debug\n" +
" Build in debug mode. Check project page for more info.\n" +
" -a, --aapt\n" +
" Loads aapt from specified location.\n" +
"\n" +
" if|install-framework <framework.apk> [<tag>] --frame-path [<location>] \n" +
" Install framework file to your system.\n" +
"\n" +
"For additional info, see: http://code.google.com/p/android-apktool/" +
"\n" +
"For smali/baksmali info, see: http://code.google.com/p/smali/"
);
System.out
.println("Apktool v"
+ Androlib.getVersion()
+ " - a tool for reengineering Android apk files\n"
+ "Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>\n"
+ "with smali v"
+ ApktoolProperties.get("smaliVersion")
+ ", and baksmali v"
+ ApktoolProperties.get("baksmaliVersion")
+ "\n"
+ "Updated by @iBotPeaches <connor.tumbleson@gmail.com> \n"
+ "Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n"
+ "\n"
+ "Usage: apktool [-q|--quiet OR -v|--verbose] COMMAND [...]\n"
+ "\n"
+ "COMMANDs are:\n"
+ "\n"
+ " d[ecode] [OPTS] <file.apk> [<dir>]\n"
+ " Decode <file.apk> to <dir>.\n"
+ "\n"
+ " OPTS:\n"
+ "\n"
+ " -s, --no-src\n"
+ " Do not decode sources.\n"
+ " -r, --no-res\n"
+ " Do not decode resources.\n"
+ " -d, --debug\n"
+ " Decode in debug mode. Check project page for more info.\n"
+ " -b, --no-debug-info\n"
+ " Baksmali -- don't write out debug info (.local, .param, .line, etc.)\n"
+ " -f, --force\n"
+ " Force delete destination directory.\n"
+ " -t <tag>, --frame-tag <tag>\n"
+ " Try to use framework files tagged by <tag>.\n"
+ " --frame-path <dir>\n"
+ " Use the specified directory for framework files\n"
+ " --keep-broken-res\n"
+ " Use if there was an error and some resources were dropped, e.g.:\n"
+ " \"Invalid config flags detected. Dropping resources\", but you\n"
+ " want to decode them anyway, even with errors. You will have to\n"
+ " fix them manually before building."
+ "\n\n"
+ " b[uild] [OPTS] [<app_path>] [<out_file>]\n"
+ " Build an apk from already decoded application located in <app_path>.\n"
+ "\n"
+ " It will automatically detect, whether files was changed and perform\n"
+ " needed steps only.\n"
+ "\n"
+ " If you omit <app_path> then current directory will be used.\n"
+ " If you omit <out_file> then <app_path>/dist/<name_of_original.apk>\n"
+ " will be used.\n"
+ "\n"
+ " OPTS:\n"
+ "\n"
+ " -f, --force-all\n"
+ " Skip changes detection and build all files.\n"
+ " -d, --debug\n"
+ " Build in debug mode. Check project page for more info.\n"
+ " -a, --aapt\n"
+ " Loads aapt from specified location.\n"
+ "\n"
+ " if|install-framework <framework.apk> [<tag>] --frame-path [<location>] \n"
+ " Install framework file to your system.\n"
+ "\n"
+ "For additional info, see: http://code.google.com/p/android-apktool/"
+ "\n"
+ "For smali/baksmali info, see: http://code.google.com/p/smali/");
}
private static void setupLogging(Verbosity verbosity) {

View File

@ -22,9 +22,9 @@ import android.util.AttributeSet;
/**
* The XML parsing interface returned for an XML resource. This is a standard
* XmlPullParser interface, as well as an extended AttributeSet interface and
* an additional close() method on this interface for the client to indicate
* when it is done reading the resource.
* XmlPullParser interface, as well as an extended AttributeSet interface and an
* additional close() method on this interface for the client to indicate when
* it is done reading the resource.
*/
public interface XmlResourceParser extends XmlPullParser, AttributeSet {
/**
@ -33,4 +33,3 @@ public interface XmlResourceParser extends XmlPullParser, AttributeSet {
*/
public void close();
}

View File

@ -21,29 +21,57 @@ package android.util;
*/
public interface AttributeSet {
int getAttributeCount();
String getAttributeName(int index);
String getAttributeValue(int index);
String getPositionDescription();
int getAttributeNameResource(int index);
int getAttributeListValue(int index,String options[],int defaultValue);
boolean getAttributeBooleanValue(int index,boolean defaultValue);
int getAttributeResourceValue(int index,int defaultValue);
int getAttributeIntValue(int index,int defaultValue);
int getAttributeUnsignedIntValue(int index,int defaultValue);
float getAttributeFloatValue(int index,float defaultValue);
String getIdAttribute();
String getClassAttribute();
int getIdAttributeResourceValue(int index);
int getStyleAttribute();
String getAttributeValue(String namespace, String attribute);
int getAttributeListValue(String namespace,String attribute,String options[],int defaultValue);
boolean getAttributeBooleanValue(String namespace,String attribute,boolean defaultValue);
int getAttributeResourceValue(String namespace,String attribute,int defaultValue);
int getAttributeIntValue(String namespace,String attribute,int defaultValue);
int getAttributeUnsignedIntValue(String namespace,String attribute,int defaultValue);
float getAttributeFloatValue(String namespace,String attribute,float defaultValue);
//TODO: remove
String getAttributeName(int index);
String getAttributeValue(int index);
String getPositionDescription();
int getAttributeNameResource(int index);
int getAttributeListValue(int index, String options[], int defaultValue);
boolean getAttributeBooleanValue(int index, boolean defaultValue);
int getAttributeResourceValue(int index, int defaultValue);
int getAttributeIntValue(int index, int defaultValue);
int getAttributeUnsignedIntValue(int index, int defaultValue);
float getAttributeFloatValue(int index, float defaultValue);
String getIdAttribute();
String getClassAttribute();
int getIdAttributeResourceValue(int index);
int getStyleAttribute();
String getAttributeValue(String namespace, String attribute);
int getAttributeListValue(String namespace, String attribute,
String options[], int defaultValue);
boolean getAttributeBooleanValue(String namespace, String attribute,
boolean defaultValue);
int getAttributeResourceValue(String namespace, String attribute,
int defaultValue);
int getAttributeIntValue(String namespace, String attribute,
int defaultValue);
int getAttributeUnsignedIntValue(String namespace, String attribute,
int defaultValue);
float getAttributeFloatValue(String namespace, String attribute,
float defaultValue);
// TODO: remove
int getAttributeValueType(int index);
int getAttributeValueData(int index);
}

View File

@ -26,58 +26,86 @@ public class TypedValue {
/** The <var>data</var> field holds a resource identifier. */
public static final int TYPE_REFERENCE = 0x01;
/** The <var>data</var> field holds an attribute resource
* identifier (referencing an attribute in the current theme
* style, not a resource entry). */
/**
* The <var>data</var> field holds an attribute resource identifier
* (referencing an attribute in the current theme style, not a resource
* entry).
*/
public static final int TYPE_ATTRIBUTE = 0x02;
/** The <var>string</var> field holds string data. In addition, if
* <var>data</var> is non-zero then it is the string block
* index of the string and <var>assetCookie</var> is the set of
* assets the string came from. */
/**
* The <var>string</var> field holds string data. In addition, if
* <var>data</var> is non-zero then it is the string block index of the
* string and <var>assetCookie</var> is the set of assets the string came
* from.
*/
public static final int TYPE_STRING = 0x03;
/** The <var>data</var> field holds an IEEE 754 floating point number. */
public static final int TYPE_FLOAT = 0x04;
/** The <var>data</var> field holds a complex number encoding a
* dimension value. */
/**
* The <var>data</var> field holds a complex number encoding a dimension
* value.
*/
public static final int TYPE_DIMENSION = 0x05;
/** The <var>data</var> field holds a complex number encoding a fraction
* of a container. */
/**
* The <var>data</var> field holds a complex number encoding a fraction of a
* container.
*/
public static final int TYPE_FRACTION = 0x06;
/** Identifies the start of plain integer values. Any type value
* from this to {@link #TYPE_LAST_INT} means the
* <var>data</var> field holds a generic integer value. */
/**
* Identifies the start of plain integer values. Any type value from this to
* {@link #TYPE_LAST_INT} means the <var>data</var> field holds a generic
* integer value.
*/
public static final int TYPE_FIRST_INT = 0x10;
/** The <var>data</var> field holds a number that was
* originally specified in decimal. */
/**
* The <var>data</var> field holds a number that was originally specified in
* decimal.
*/
public static final int TYPE_INT_DEC = 0x10;
/** The <var>data</var> field holds a number that was
* originally specified in hexadecimal (0xn). */
/**
* The <var>data</var> field holds a number that was originally specified in
* hexadecimal (0xn).
*/
public static final int TYPE_INT_HEX = 0x11;
/** The <var>data</var> field holds 0 or 1 that was originally
* specified as "false" or "true". */
/**
* The <var>data</var> field holds 0 or 1 that was originally specified as
* "false" or "true".
*/
public static final int TYPE_INT_BOOLEAN = 0x12;
/** Identifies the start of integer values that were specified as
* color constants (starting with '#'). */
/**
* Identifies the start of integer values that were specified as color
* constants (starting with '#').
*/
public static final int TYPE_FIRST_COLOR_INT = 0x1c;
/** The <var>data</var> field holds a color that was originally
* specified as #aarrggbb. */
/**
* The <var>data</var> field holds a color that was originally specified as
* #aarrggbb.
*/
public static final int TYPE_INT_COLOR_ARGB8 = 0x1c;
/** The <var>data</var> field holds a color that was originally
* specified as #rrggbb. */
/**
* The <var>data</var> field holds a color that was originally specified as
* #rrggbb.
*/
public static final int TYPE_INT_COLOR_RGB8 = 0x1d;
/** The <var>data</var> field holds a color that was originally
* specified as #argb. */
/**
* The <var>data</var> field holds a color that was originally specified as
* #argb.
*/
public static final int TYPE_INT_COLOR_ARGB4 = 0x1e;
/** The <var>data</var> field holds a color that was originally
* specified as #rgb. */
/**
* The <var>data</var> field holds a color that was originally specified as
* #rgb.
*/
public static final int TYPE_INT_COLOR_RGB4 = 0x1f;
/** Identifies the end of integer values that were specified as color
* constants. */
/**
* Identifies the end of integer values that were specified as color
* constants.
*/
public static final int TYPE_LAST_COLOR_INT = 0x1f;
/** Identifies the end of plain integer values. */
@ -87,15 +115,18 @@ public class TypedValue {
/** Complex data: bit location of unit information. */
public static final int COMPLEX_UNIT_SHIFT = 0;
/** Complex data: mask to extract unit information (after shifting by
* {@link #COMPLEX_UNIT_SHIFT}). This gives us 16 possible types, as
* defined below. */
/**
* Complex data: mask to extract unit information (after shifting by
* {@link #COMPLEX_UNIT_SHIFT}). This gives us 16 possible types, as defined
* below.
*/
public static final int COMPLEX_UNIT_MASK = 0xf;
/** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */
public static final int COMPLEX_UNIT_PX = 0;
/** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent
* Pixels. */
/**
* {@link #TYPE_DIMENSION} complex unit: Value is Device Independent Pixels.
*/
public static final int COMPLEX_UNIT_DIP = 1;
/** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */
public static final int COMPLEX_UNIT_SP = 2;
@ -106,18 +137,23 @@ public class TypedValue {
/** {@link #TYPE_DIMENSION} complex unit: Value is in millimeters. */
public static final int COMPLEX_UNIT_MM = 5;
/** {@link #TYPE_FRACTION} complex unit: A basic fraction of the overall
* size. */
/**
* {@link #TYPE_FRACTION} complex unit: A basic fraction of the overall size.
*/
public static final int COMPLEX_UNIT_FRACTION = 0;
/** {@link #TYPE_FRACTION} complex unit: A fraction of the parent size. */
public static final int COMPLEX_UNIT_FRACTION_PARENT = 1;
/** Complex data: where the radix information is, telling where the decimal
* place appears in the mantissa. */
/**
* Complex data: where the radix information is, telling where the decimal
* place appears in the mantissa.
*/
public static final int COMPLEX_RADIX_SHIFT = 4;
/** Complex data: mask to extract radix information (after shifting by
/**
* Complex data: mask to extract radix information (after shifting by
* {@link #COMPLEX_RADIX_SHIFT}). This give us 4 possible fixed point
* representations as defined below. */
* representations as defined below.
*/
public static final int COMPLEX_RADIX_MASK = 0x3;
/** Complex data: the mantissa is an integral number -- i.e., 0xnnnnnn.0 */
@ -131,16 +167,19 @@ public class TypedValue {
/** Complex data: bit location of mantissa information. */
public static final int COMPLEX_MANTISSA_SHIFT = 8;
/** Complex data: mask to extract mantissa information (after shifting by
* {@link #COMPLEX_MANTISSA_SHIFT}). This gives us 23 bits of precision;
* the top bit is the sign. */
/**
* Complex data: mask to extract mantissa information (after shifting by
* {@link #COMPLEX_MANTISSA_SHIFT}). This gives us 23 bits of precision; the
* top bit is the sign.
*/
public static final int COMPLEX_MANTISSA_MASK = 0xffffff;
/* ------------------------------------------------------------ */
/**
* If {@link #density} is equal to this value, then the density should be
* treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}.
* treated as the system's default density value:
* {@link DisplayMetrics#DENSITY_DEFAULT}.
*/
public static final int DENSITY_DEFAULT = 0;
@ -152,16 +191,16 @@ public class TypedValue {
/* ------------------------------------------------------------ */
/** The type held by this value, as defined by the constants here.
* This tells you how to interpret the other fields in the object. */
/**
* The type held by this value, as defined by the constants here. This tells
* you how to interpret the other fields in the object.
*/
public int type;
private static final float MANTISSA_MULT =
1.0f / (1<<TypedValue.COMPLEX_MANTISSA_SHIFT);
private static final float MANTISSA_MULT = 1.0f / (1 << TypedValue.COMPLEX_MANTISSA_SHIFT);
private static final float[] RADIX_MULTS = new float[] {
1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT,
1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT
};
1.0f * MANTISSA_MULT, 1.0f / (1 << 7) * MANTISSA_MULT,
1.0f / (1 << 15) * MANTISSA_MULT, 1.0f / (1 << 23) * MANTISSA_MULT };
/**
* Retrieve the base value from a complex data integer. This uses the
@ -169,37 +208,34 @@ public class TypedValue {
* the data to compute a floating point representation of the number they
* describe. The units are ignored.
*
* @param complex A complex data value.
* @param complex
* A complex data value.
*
* @return A floating point value corresponding to the complex data.
*/
public static float complexToFloat(int complex)
{
return (complex&(TypedValue.COMPLEX_MANTISSA_MASK
<<TypedValue.COMPLEX_MANTISSA_SHIFT))
* RADIX_MULTS[(complex>>TypedValue.COMPLEX_RADIX_SHIFT)
public static float complexToFloat(int complex) {
return (complex & (TypedValue.COMPLEX_MANTISSA_MASK << TypedValue.COMPLEX_MANTISSA_SHIFT))
* RADIX_MULTS[(complex >> TypedValue.COMPLEX_RADIX_SHIFT)
& TypedValue.COMPLEX_RADIX_MASK];
}
private static final String[] DIMENSION_UNIT_STRS = new String[] {
"px", "dip", "sp", "pt", "in", "mm"
};
private static final String[] FRACTION_UNIT_STRS = new String[] {
"%", "%p"
};
private static final String[] DIMENSION_UNIT_STRS = new String[] { "px",
"dip", "sp", "pt", "in", "mm" };
private static final String[] FRACTION_UNIT_STRS = new String[] { "%", "%p" };
/**
* Perform type conversion as per {@link #coerceToString()} on an
* explicitly supplied type and data.
* Perform type conversion as per {@link #coerceToString()} on an explicitly
* supplied type and data.
*
* @param type The data type identifier.
* @param data The data value.
* @param type
* The data type identifier.
* @param data
* The data value.
*
* @return String The coerced string value. If the value is
* null or the type is not known, null is returned.
* @return String The coerced string value. If the value is null or the type
* is not known, null is returned.
*/
public static final String coerceToString(int type, int data)
{
public static final String coerceToString(int type, int data) {
switch (type) {
case TYPE_NULL:
return null;
@ -210,11 +246,13 @@ public class TypedValue {
case TYPE_FLOAT:
return Float.toString(Float.intBitsToFloat(data));
case TYPE_DIMENSION:
return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[
(data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
return Float.toString(complexToFloat(data))
+ DIMENSION_UNIT_STRS[(data >> COMPLEX_UNIT_SHIFT)
& COMPLEX_UNIT_MASK];
case TYPE_FRACTION:
return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[
(data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
return Float.toString(complexToFloat(data) * 100)
+ FRACTION_UNIT_STRS[(data >> COMPLEX_UNIT_SHIFT)
& COMPLEX_UNIT_MASK];
case TYPE_INT_HEX:
return "0x" + Integer.toHexString(data);
case TYPE_INT_BOOLEAN:
@ -222,20 +260,22 @@ public class TypedValue {
}
if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) {
String res =String.format("%08x", data);
String res = String.format("%08x", data);
char[] vals = res.toCharArray();
switch (type) {
default:
case TYPE_INT_COLOR_ARGB8://#AaRrGgBb
case TYPE_INT_COLOR_ARGB8:// #AaRrGgBb
break;
case TYPE_INT_COLOR_RGB8://#FFRrGgBb->#RrGgBb
case TYPE_INT_COLOR_RGB8:// #FFRrGgBb->#RrGgBb
res = res.substring(2);
break;
case TYPE_INT_COLOR_ARGB4://#AARRGGBB->#ARGB
res = new StringBuffer().append(vals[0]).append(vals[2]).append(vals[4]).append(vals[6]).toString();
case TYPE_INT_COLOR_ARGB4:// #AARRGGBB->#ARGB
res = new StringBuffer().append(vals[0]).append(vals[2])
.append(vals[4]).append(vals[6]).toString();
break;
case TYPE_INT_COLOR_RGB4://#FFRRGGBB->#RGB
res = new StringBuffer().append(vals[2]).append(vals[4]).append(vals[6]).toString();
case TYPE_INT_COLOR_RGB4:// #FFRRGGBB->#RGB
res = new StringBuffer().append(vals[2]).append(vals[4])
.append(vals[6]).toString();
break;
}
return "#" + res;
@ -246,13 +286,11 @@ public class TypedValue {
case TYPE_INT_DEC:
res = Integer.toString(data);
break;
//defined before
/*case TYPE_INT_HEX:
res = "0x" + Integer.toHexString(data);
break;
case TYPE_INT_BOOLEAN:
res = (data != 0) ? "true":"false";
break;*/
// defined before
/*
* case TYPE_INT_HEX: res = "0x" + Integer.toHexString(data); break;
* case TYPE_INT_BOOLEAN: res = (data != 0) ? "true":"false"; break;
*/
}
return res;
}

View File

@ -46,7 +46,8 @@ public class Androlib {
return mAndRes.getResTable(apkFile, true);
}
public ResTable getResTable(ExtFile apkFile, boolean loadMainPkg) throws AndrolibException {
public ResTable getResTable(ExtFile apkFile, boolean loadMainPkg)
throws AndrolibException {
return mAndRes.getResTable(apkFile, loadMainPkg);
}
@ -64,8 +65,8 @@ public class Androlib {
}
}
public void decodeSourcesSmali(File apkFile, File outDir, boolean debug, boolean bakdeb)
throws AndrolibException {
public void decodeSourcesSmali(File apkFile, File outDir, boolean debug,
boolean bakdeb) throws AndrolibException {
try {
File smaliDir = new File(outDir, SMALI_DIRNAME);
OS.rmdir(smaliDir);
@ -102,7 +103,7 @@ public class Androlib {
public void decodeResourcesRaw(ExtFile apkFile, File outDir)
throws AndrolibException {
try {
//Directory apk = apkFile.getDirectory();
// Directory apk = apkFile.getDirectory();
LOGGER.info("Copying raw resources...");
apkFile.getDirectory().copyToDir(outDir, APK_RESOURCES_FILENAMES);
} catch (DirectoryException ex) {
@ -135,7 +136,7 @@ public class Androlib {
throws AndrolibException {
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
// options.setIndent(4);
// options.setIndent(4);
Yaml yaml = new Yaml(options);
FileWriter writer = null;
@ -148,7 +149,8 @@ public class Androlib {
if (writer != null) {
try {
writer.close();
} catch (IOException ex) {}
} catch (IOException ex) {
}
}
}
}
@ -166,24 +168,28 @@ public class Androlib {
if (in != null) {
try {
in.close();
} catch (IOException ex) {}
} catch (IOException ex) {
}
}
}
}
public void build(File appDir, File outFile,
HashMap<String, Boolean> flags, ExtFile origApk, String aaptPath) throws BrutException {
HashMap<String, Boolean> flags, ExtFile origApk, String aaptPath)
throws BrutException {
build(new ExtFile(appDir), outFile, flags, origApk, aaptPath);
}
public void build(ExtFile appDir, File outFile,
HashMap<String, Boolean> flags, ExtFile origApk, String aaptPath) throws BrutException {
HashMap<String, Boolean> flags, ExtFile origApk, String aaptPath)
throws BrutException {
mAaptPath = aaptPath;
Map<String, Object> meta = readMetaFile(appDir);
Object t1 = meta.get("isFrameworkApk");
flags.put("framework", t1 == null ? false : (Boolean) t1);
flags.put("compression", meta.get("compressionType") == null ? false : (Boolean) meta.get("compressionType"));
flags.put("compression", meta.get("compressionType") == null ? false
: (Boolean) meta.get("compressionType"));
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
// check the orig apk
@ -197,8 +203,8 @@ public class Androlib {
if (outFile == null) {
String outFileName = (String) meta.get("apkFileName");
outFile = new File(appDir, "dist" + File.separator +
(outFileName == null ? "out.apk" : outFileName));
outFile = new File(appDir, "dist" + File.separator
+ (outFileName == null ? "out.apk" : outFileName));
}
new File(appDir, APK_DIRNAME).mkdirs();
@ -206,24 +212,23 @@ public class Androlib {
buildResources(appDir, flags,
(Map<String, Object>) meta.get("usesFramework"));
buildLib(appDir, flags);
buildApk(appDir, outFile,flags);
buildApk(appDir, outFile, flags);
}
public void buildSources(File appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
if (! buildSourcesRaw(appDir, flags)
&& ! buildSourcesSmali(appDir, flags)
&& ! buildSourcesJava(appDir, flags)
) {
if (!buildSourcesRaw(appDir, flags)
&& !buildSourcesSmali(appDir, flags)
&& !buildSourcesJava(appDir, flags)) {
LOGGER.warning("Could not find sources");
}
}
public boolean buildSourcesRaw(File appDir,
HashMap<String, Boolean> flags) throws AndrolibException {
public boolean buildSourcesRaw(File appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
try {
File working = new File(appDir, "classes.dex");
if (! working.exists()) {
if (!working.exists()) {
return false;
}
if (flags.get("debug")) {
@ -241,14 +246,14 @@ public class Androlib {
}
}
public boolean buildSourcesSmali(File appDir,
HashMap<String, Boolean> flags) throws AndrolibException {
public boolean buildSourcesSmali(File appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
ExtFile smaliDir = new ExtFile(appDir, "smali");
if (! smaliDir.exists()) {
if (!smaliDir.exists()) {
return false;
}
File dex = new File(appDir, APK_DIRNAME + "/classes.dex");
if (! flags.get("forceBuildAll")) {
if (!flags.get("forceBuildAll")) {
LOGGER.info("Checking whether sources has changed...");
}
if (flags.get("forceBuildAll") || isModified(smaliDir, dex)) {
@ -259,14 +264,14 @@ public class Androlib {
return true;
}
public boolean buildSourcesJava(File appDir,
HashMap<String, Boolean> flags) throws AndrolibException {
public boolean buildSourcesJava(File appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
File javaDir = new File(appDir, "src");
if (! javaDir.exists()) {
if (!javaDir.exists()) {
return false;
}
File dex = new File(appDir, APK_DIRNAME + "/classes.dex");
if (! flags.get("forceBuildAll")) {
if (!flags.get("forceBuildAll")) {
LOGGER.info("Checking whether sources has changed...");
}
if (flags.get("forceBuildAll") || isModified(javaDir, dex)) {
@ -278,27 +283,26 @@ public class Androlib {
}
public void buildResources(ExtFile appDir, HashMap<String, Boolean> flags,
Map<String, Object> usesFramework)
throws BrutException {
if (! buildResourcesRaw(appDir, flags)
&& ! buildResourcesFull(appDir, flags, usesFramework)
&& ! buildManifest(appDir, flags, usesFramework)) {
Map<String, Object> usesFramework) throws BrutException {
if (!buildResourcesRaw(appDir, flags)
&& !buildResourcesFull(appDir, flags, usesFramework)
&& !buildManifest(appDir, flags, usesFramework)) {
LOGGER.warning("Could not find resources");
}
}
public boolean buildResourcesRaw(ExtFile appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
public boolean buildResourcesRaw(ExtFile appDir,
HashMap<String, Boolean> flags) throws AndrolibException {
try {
if (! new File(appDir, "resources.arsc").exists()) {
if (!new File(appDir, "resources.arsc").exists()) {
return false;
}
File apkDir = new File(appDir, APK_DIRNAME);
if (! flags.get("forceBuildAll")) {
if (!flags.get("forceBuildAll")) {
LOGGER.info("Checking whether resources has changed...");
}
if (flags.get("forceBuildAll") || isModified(
newFiles(APK_RESOURCES_FILENAMES, appDir),
if (flags.get("forceBuildAll")
|| isModified(newFiles(APK_RESOURCES_FILENAMES, appDir),
newFiles(APK_RESOURCES_FILENAMES, apkDir))) {
LOGGER.info("Copying raw resources...");
appDir.getDirectory()
@ -310,19 +314,19 @@ public class Androlib {
}
}
public boolean buildResourcesFull(File appDir, HashMap<String, Boolean> flags,
Map<String, Object> usesFramework)
public boolean buildResourcesFull(File appDir,
HashMap<String, Boolean> flags, Map<String, Object> usesFramework)
throws AndrolibException {
try {
if (! new File(appDir, "res").exists()) {
if (!new File(appDir, "res").exists()) {
return false;
}
if (! flags.get("forceBuildAll")) {
if (!flags.get("forceBuildAll")) {
LOGGER.info("Checking whether resources has changed...");
}
File apkDir = new File(appDir, APK_DIRNAME);
if (flags.get("forceBuildAll") || isModified(
newFiles(APP_RESOURCES_FILENAMES, appDir),
if (flags.get("forceBuildAll")
|| isModified(newFiles(APP_RESOURCES_FILENAMES, appDir),
newFiles(APK_RESOURCES_FILENAMES, apkDir))) {
LOGGER.info("Building resources...");
@ -330,21 +334,18 @@ public class Androlib {
apkFile.delete();
File ninePatch = new File(appDir, "9patch");
if (! ninePatch.exists()) {
if (!ninePatch.exists()) {
ninePatch = null;
}
mAndRes.aaptPackage(
apkFile,
new File(appDir, "AndroidManifest.xml"),
new File(appDir, "res"),
mAndRes.aaptPackage(apkFile, new File(appDir,
"AndroidManifest.xml"), new File(appDir, "res"),
ninePatch, null, parseUsesFramework(usesFramework),
flags, mAaptPath
);
flags, mAaptPath);
Directory tmpDir = new ExtFile(apkFile).getDirectory();
tmpDir.copyToDir(apkDir,
tmpDir.containsDir("res") ? APK_RESOURCES_FILENAMES :
APK_RESOURCES_WITHOUT_RES_FILENAMES);
tmpDir.containsDir("res") ? APK_RESOURCES_FILENAMES
: APK_RESOURCES_WITHOUT_RES_FILENAMES);
// delete tmpDir
apkFile.delete();
@ -359,32 +360,31 @@ public class Androlib {
}
}
public boolean buildManifestRaw(ExtFile appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
public boolean buildManifestRaw(ExtFile appDir,
HashMap<String, Boolean> flags) throws AndrolibException {
try {
File apkDir = new File(appDir, APK_DIRNAME);
LOGGER.info("Copying raw AndroidManifest.xml...");
appDir.getDirectory()
.copyToDir(apkDir, APK_MANIFEST_FILENAMES);
appDir.getDirectory().copyToDir(apkDir, APK_MANIFEST_FILENAMES);
return true;
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
}
}
public boolean buildManifest(ExtFile appDir, HashMap<String, Boolean> flags,
Map<String, Object> usesFramework)
public boolean buildManifest(ExtFile appDir,
HashMap<String, Boolean> flags, Map<String, Object> usesFramework)
throws BrutException {
try {
if (! new File(appDir, "AndroidManifest.xml").exists()) {
if (!new File(appDir, "AndroidManifest.xml").exists()) {
return false;
}
if (! flags.get("forceBuildAll")) {
if (!flags.get("forceBuildAll")) {
LOGGER.info("Checking whether resources has changed...");
}
File apkDir = new File(appDir, APK_DIRNAME);
if (flags.get("forceBuildAll") || isModified(
newFiles(APK_MANIFEST_FILENAMES, appDir),
if (flags.get("forceBuildAll")
|| isModified(newFiles(APK_MANIFEST_FILENAMES, appDir),
newFiles(APK_MANIFEST_FILENAMES, apkDir))) {
LOGGER.info("Building AndroidManifest.xml...");
@ -392,17 +392,13 @@ public class Androlib {
apkFile.delete();
File ninePatch = new File(appDir, "9patch");
if (! ninePatch.exists()) {
if (!ninePatch.exists()) {
ninePatch = null;
}
mAndRes.aaptPackage(
apkFile,
new File(appDir, "AndroidManifest.xml"),
null,
ninePatch, null, parseUsesFramework(usesFramework),
flags, mAaptPath
);
mAndRes.aaptPackage(apkFile, new File(appDir,
"AndroidManifest.xml"), null, ninePatch, null,
parseUsesFramework(usesFramework), flags, mAaptPath);
Directory tmpDir = new ExtFile(apkFile).getDirectory();
tmpDir.copyToDir(apkDir, APK_MANIFEST_FILENAMES);
@ -422,7 +418,7 @@ public class Androlib {
public void buildLib(File appDir, HashMap<String, Boolean> flags)
throws AndrolibException {
File working = new File(appDir, "lib");
if (! working.exists()) {
if (!working.exists()) {
return;
}
File stored = new File(appDir, APK_DIRNAME + "/lib");
@ -437,23 +433,23 @@ public class Androlib {
}
}
public void buildApk(File appDir, File outApk, HashMap<String, Boolean> flags)
throws AndrolibException {
public void buildApk(File appDir, File outApk,
HashMap<String, Boolean> flags) throws AndrolibException {
LOGGER.info("Building apk file...");
if (outApk.exists()) {
outApk.delete();
} else {
File outDir = outApk.getParentFile();
if (outDir != null && ! outDir.exists()) {
if (outDir != null && !outDir.exists()) {
outDir.mkdirs();
}
}
File assetDir = new File(appDir, "assets");
if (! assetDir.exists()) {
if (!assetDir.exists()) {
assetDir = null;
}
mAndRes.aaptPackage(outApk, null, null,
new File(appDir, APK_DIRNAME), assetDir, null, flags, mAaptPath);
mAndRes.aaptPackage(outApk, null, null, new File(appDir, APK_DIRNAME),
assetDir, null, flags, mAaptPath);
// retain signature
// aapt r (remove)
@ -484,10 +480,9 @@ public class Androlib {
public static String getVersion() {
String version = ApktoolProperties.get("application.version");
return version.endsWith("-SNAPSHOT") ?
version.substring(0, version.length() - 9) + '.' +
ApktoolProperties.get("git.commit.id.abbrev")
: version;
return version.endsWith("-SNAPSHOT") ? version.substring(0,
version.length() - 9)
+ '.' + ApktoolProperties.get("git.commit.id.abbrev") : version;
}
private File[] parseUsesFramework(Map<String, Object> usesFramework)
@ -511,21 +506,21 @@ public class Androlib {
}
private boolean isModified(File working, File stored) {
if (! stored.exists()) {
if (!stored.exists()) {
return true;
}
return BrutIO.recursiveModifiedTime(working) >
BrutIO.recursiveModifiedTime(stored);
return BrutIO.recursiveModifiedTime(working) > BrutIO
.recursiveModifiedTime(stored);
}
private boolean isModified(File[] working, File[] stored) {
for (int i = 0; i < stored.length; i++) {
if (! stored[i].exists()) {
if (!stored[i].exists()) {
return true;
}
}
return BrutIO.recursiveModifiedTime(working) >
BrutIO.recursiveModifiedTime(stored);
return BrutIO.recursiveModifiedTime(working) > BrutIO
.recursiveModifiedTime(stored);
}
private File[] newFiles(String[] names, File dir) {
@ -540,21 +535,19 @@ public class Androlib {
mOrigApkFile = new ExtFile(apkFile);
}
private ExtFile mOrigApkFile = null;
private String mAaptPath = null;
private final static Logger LOGGER =
Logger.getLogger(Androlib.class.getName());
private final static Logger LOGGER = Logger.getLogger(Androlib.class
.getName());
private final static String SMALI_DIRNAME = "smali";
private final static String APK_DIRNAME = "build/apk";
private final static String[] APK_RESOURCES_FILENAMES =
new String[]{"resources.arsc", "AndroidManifest.xml", "res"};
private final static String[] APK_RESOURCES_WITHOUT_RES_FILENAMES =
new String[]{"resources.arsc", "AndroidManifest.xml"};
private final static String[] APP_RESOURCES_FILENAMES =
new String[]{"AndroidManifest.xml", "res"};
private final static String[] APK_MANIFEST_FILENAMES =
new String[]{"AndroidManifest.xml"};
private final static String[] APK_RESOURCES_FILENAMES = new String[] {
"resources.arsc", "AndroidManifest.xml", "res" };
private final static String[] APK_RESOURCES_WITHOUT_RES_FILENAMES = new String[] {
"resources.arsc", "AndroidManifest.xml" };
private final static String[] APP_RESOURCES_FILENAMES = new String[] {
"AndroidManifest.xml", "res" };
private final static String[] APK_MANIFEST_FILENAMES = new String[] { "AndroidManifest.xml" };
}

View File

@ -96,13 +96,15 @@ public class ApkDecoder {
if (hasResources()) {
// read the resources.arsc checking for STORED vs DEFLATE compression
// read the resources.arsc checking for STORED vs DEFLATE
// compression
// this will determine whether we compress on rebuild or not.
JarFile jf = new JarFile(mApkFile.getAbsoluteFile());
JarEntry je = jf.getJarEntry("resources.arsc");
if (je != null) {
int compression = je.getMethod();
mCompressResources = (compression != ZipEntry.STORED) && (compression == ZipEntry.DEFLATED);
mCompressResources = (compression != ZipEntry.STORED)
&& (compression == ZipEntry.DEFLATED);
}
jf.close();

View File

@ -20,8 +20,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Logger;
import org.jf.baksmali.baksmali;
import org.jf.smali.main;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
@ -39,7 +37,8 @@ public class ApktoolProperties {
}
private static void loadProps() {
InputStream in = ApktoolProperties.class.getResourceAsStream("/properties/apktool.properties");
InputStream in = ApktoolProperties.class
.getResourceAsStream("/properties/apktool.properties");
sProps = new Properties();
try {
sProps.load(in);
@ -48,7 +47,8 @@ public class ApktoolProperties {
LOGGER.warning("Can't load properties.");
}
InputStream templateStream = ApktoolProperties.class.getResourceAsStream("/properties/baksmali.properties");
InputStream templateStream = ApktoolProperties.class
.getResourceAsStream("/properties/baksmali.properties");
Properties properties = new Properties();
String version = "(unknown)";
try {
@ -57,7 +57,8 @@ public class ApktoolProperties {
} catch (IOException ex) {
}
sProps.put("baksmaliVersion", version);
templateStream = ApktoolProperties.class.getResourceAsStream("/properties/smali.properties");
templateStream = ApktoolProperties.class
.getResourceAsStream("/properties/smali.properties");
properties = new Properties();
version = "(unknown)";
try {
@ -70,6 +71,6 @@ public class ApktoolProperties {
private static Properties sProps;
private static final Logger LOGGER =
Logger.getLogger(ApktoolProperties.class.getName());
private static final Logger LOGGER = Logger
.getLogger(ApktoolProperties.class.getName());
}

View File

@ -30,29 +30,29 @@ public class SmaliMod {
public static boolean assembleSmaliFile(InputStream smaliStream,
String name, DexFile dexFile, boolean verboseErrors,
boolean oldLexer, boolean printTokens)
throws IOException, RecognitionException {
boolean oldLexer, boolean printTokens) throws IOException,
RecognitionException {
CommonTokenStream tokens;
boolean lexerErrors = false;
LexerErrorInterface lexer;
InputStreamReader reader = new InputStreamReader(smaliStream, "UTF-8");
lexer = new smaliFlexLexer(reader);
tokens = new CommonTokenStream((TokenSource)lexer);
tokens = new CommonTokenStream((TokenSource) lexer);
if (printTokens) {
tokens.getTokens();
for (int i=0; i<tokens.size(); i++) {
for (int i = 0; i < tokens.size(); i++) {
Token token = tokens.get(i);
if (token.getChannel() == smaliParser.HIDDEN) {
if (token.getChannel() == BaseRecognizer.HIDDEN) {
continue;
}
System.out.println(smaliParser.tokenNames[token.getType()] + ": " + token.getText());
System.out.println(smaliParser.tokenNames[token.getType()]
+ ": " + token.getText());
}
}
@ -61,7 +61,8 @@ public class SmaliMod {
smaliParser.smali_file_return result = parser.smali_file();
if (parser.getNumberOfSyntaxErrors() > 0 || lexer.getNumberOfSyntaxErrors() > 0) {
if (parser.getNumberOfSyntaxErrors() > 0
|| lexer.getNumberOfSyntaxErrors() > 0) {
return false;
}

View File

@ -154,11 +154,13 @@ final public class AndrolibResources {
public void adjust_package_manifest(ResTable resTable, String filePath)
throws AndrolibException {
// check if packages different, and that package is not equal to "android"
// check if packages different, and that package is not equal to
// "android"
Map<String, String> packageInfo = resTable.getPackageInfo();
if ((packageInfo.get("cur_package").equalsIgnoreCase(packageInfo.get("orig_package"))
|| ("android".equalsIgnoreCase(packageInfo.get("cur_package"))
|| ("com.htc".equalsIgnoreCase(packageInfo.get("cur_package")))))) {
if ((packageInfo.get("cur_package").equalsIgnoreCase(
packageInfo.get("orig_package")) || ("android"
.equalsIgnoreCase(packageInfo.get("cur_package")) || ("com.htc"
.equalsIgnoreCase(packageInfo.get("cur_package")))))) {
LOGGER.info("Regular manifest package...");
} else {
@ -181,7 +183,8 @@ final public class AndrolibResources {
// re-save manifest.
// fancy an auto-sort :p
TransformerFactory transformerFactory = TransformerFactory.newInstance();
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filePath));
@ -219,7 +222,8 @@ final public class AndrolibResources {
"AndroidManifest.xml");
// fix package if needed
adjust_package_manifest(resTable, outDir.getAbsolutePath() + "/AndroidManifest.xml");
adjust_package_manifest(resTable, outDir.getAbsolutePath()
+ "/AndroidManifest.xml");
if (inApk.containsDir("res")) {
in = inApk.getDir("res");
@ -268,7 +272,8 @@ final public class AndrolibResources {
public void aaptPackage(File apkFile, File manifest, File resDir,
File rawDir, File assetDir, File[] include,
HashMap<String, Boolean> flags, String aaptPath) throws AndrolibException {
HashMap<String, Boolean> flags, String aaptPath)
throws AndrolibException {
List<String> cmd = new ArrayList<String>();
@ -280,7 +285,8 @@ final public class AndrolibResources {
cmd.add(aaptFile.getPath());
if (flags.get("verbose")) {
LOGGER.info(aaptFile.getPath() + " being used as aapt location.");
LOGGER.info(aaptFile.getPath()
+ " being used as aapt location.");
}
} else {
LOGGER.warning("aapt location could not be found. Defaulting back to default");
@ -420,7 +426,7 @@ final public class AndrolibResources {
" ");
serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_LINE_SEPARATOR,
System.getProperty("line.separator"));
serial.setProperty(ExtMXSerializer.PROPERTY_DEFAULT_ENCODING, "utf-8");
serial.setProperty(ExtXmlSerializer.PROPERTY_DEFAULT_ENCODING, "utf-8");
serial.setDisabledAttrEscape(true);
return serial;
}
@ -665,7 +671,8 @@ final public class AndrolibResources {
if (!dir.exists()) {
if (!dir.mkdirs()) {
if (sFrameworkFolder != null) {
System.out.println("Can't create Framework directory: " + dir);
System.out.println("Can't create Framework directory: "
+ dir);
}
throw new AndrolibException("Can't create directory: " + dir);
}

View File

@ -42,21 +42,20 @@ public class ResSmaliUpdater {
try {
dir = new FileDirectory(smaliDir);
} catch (DirectoryException ex) {
throw new AndrolibException(
"Could not tag res IDs", ex);
throw new AndrolibException("Could not tag res IDs", ex);
}
for (String fileName : dir.getFiles(true)) {
try {
tagResIdsForFile(resTable, dir, fileName);
} catch (IOException ex) {
throw new AndrolibException(
"Could not tag resIDs for file: " + fileName, ex);
throw new AndrolibException("Could not tag resIDs for file: "
+ fileName, ex);
} catch (DirectoryException ex) {
throw new AndrolibException(
"Could not tag resIDs for file: " + fileName, ex);
throw new AndrolibException("Could not tag resIDs for file: "
+ fileName, ex);
} catch (AndrolibException ex) {
throw new AndrolibException(
"Could not tag resIDs for file: " + fileName, ex);
throw new AndrolibException("Could not tag resIDs for file: "
+ fileName, ex);
}
}
}
@ -66,47 +65,47 @@ public class ResSmaliUpdater {
try {
Directory dir = new FileDirectory(smaliDir);
for (String fileName : dir.getFiles(true)) {
Iterator<String> it =
IOUtils.readLines(dir.getFileInput(fileName)).iterator();
Iterator<String> it = IOUtils.readLines(
dir.getFileInput(fileName)).iterator();
PrintWriter out = new PrintWriter(dir.getFileOutput(fileName));
while (it.hasNext()) {
String line = it.next();
out.println(line);
Matcher m1 = RES_NAME_PATTERN.matcher(line);
if (! m1.matches()) {
if (!m1.matches()) {
continue;
}
Matcher m2 = RES_ID_PATTERN.matcher(it.next());
if (! m2.matches()) {
if (!m2.matches()) {
throw new AndrolibException();
}
int resID = resTable.getPackage(m1.group(1))
.getType(m1.group(2)).getResSpec(m1.group(3))
.getId().id;
if (m2.group(1) != null) {
out.println(String.format(
RES_ID_FORMAT_FIELD, m2.group(1), resID));
out.println(String.format(RES_ID_FORMAT_FIELD,
m2.group(1), resID));
} else {
out.println(String.format(
RES_ID_FORMAT_CONST, m2.group(2), resID));
out.println(String.format(RES_ID_FORMAT_CONST,
m2.group(2), resID));
}
}
out.close();
}
} catch (IOException ex) {
throw new AndrolibException(
"Could not tag res IDs for: " + smaliDir.getAbsolutePath(), ex);
throw new AndrolibException("Could not tag res IDs for: "
+ smaliDir.getAbsolutePath(), ex);
} catch (DirectoryException ex) {
throw new AndrolibException(
"Could not tag res IDs for: " + smaliDir.getAbsolutePath(), ex);
throw new AndrolibException("Could not tag res IDs for: "
+ smaliDir.getAbsolutePath(), ex);
}
}
private void tagResIdsForFile(ResTable resTable, Directory dir,
String fileName) throws IOException, DirectoryException,
AndrolibException {
Iterator<String> it =
IOUtils.readLines(dir.getFileInput(fileName)).iterator();
Iterator<String> it = IOUtils.readLines(dir.getFileInput(fileName))
.iterator();
PrintWriter out = new PrintWriter(dir.getFileOutput(fileName));
while (it.hasNext()) {
String line = it.next();
@ -121,13 +120,13 @@ public class ResSmaliUpdater {
if (resID != -1) {
try {
ResResSpec spec = resTable.getResSpec(resID);
out.println(String.format(
RES_NAME_FORMAT, spec.getFullName()));
out.println(String.format(RES_NAME_FORMAT,
spec.getFullName()));
} catch (UndefinedResObject ex) {
if (! R_FILE_PATTERN.matcher(fileName).matches()) {
if (!R_FILE_PATTERN.matcher(fileName).matches()) {
LOGGER.warning(String.format(
"Undefined resource spec in %s: 0x%08x"
, fileName, resID));
"Undefined resource spec in %s: 0x%08x",
fileName, resID));
}
}
}
@ -148,20 +147,17 @@ public class ResSmaliUpdater {
return resID;
}
private final static String RES_ID_FORMAT_FIELD =
".field %s:I = 0x%08x";
private final static String RES_ID_FORMAT_CONST =
" const %s, 0x%08x";
private final static Pattern RES_ID_PATTERN = Pattern.compile(
"^(?:\\.field (.+?):I =| const(?:|/(?:|high)16) ([pv]\\d+?),) 0x(7[a-f]0[1-9a-f](?:|[0-9a-f]{4}))$");
private final static String RES_NAME_FORMAT =
"# APKTOOL/RES_NAME: %s";
private final static Pattern RES_NAME_PATTERN = Pattern.compile(
"^# APKTOOL/RES_NAME: ([a-zA-Z0-9.]+):([a-z]+)/([a-zA-Z0-9._]+)$");
private final static String RES_ID_FORMAT_FIELD = ".field %s:I = 0x%08x";
private final static String RES_ID_FORMAT_CONST = " const %s, 0x%08x";
private final static Pattern RES_ID_PATTERN = Pattern
.compile("^(?:\\.field (.+?):I =| const(?:|/(?:|high)16) ([pv]\\d+?),) 0x(7[a-f]0[1-9a-f](?:|[0-9a-f]{4}))$");
private final static String RES_NAME_FORMAT = "# APKTOOL/RES_NAME: %s";
private final static Pattern RES_NAME_PATTERN = Pattern
.compile("^# APKTOOL/RES_NAME: ([a-zA-Z0-9.]+):([a-z]+)/([a-zA-Z0-9._]+)$");
private final static Pattern R_FILE_PATTERN = Pattern.compile(
".*R\\$[a-z]+\\.smali$");
private final static Pattern R_FILE_PATTERN = Pattern
.compile(".*R\\$[a-z]+\\.smali$");
private final static Logger LOGGER =
Logger.getLogger(ResSmaliUpdater.class.getName());
private final static Logger LOGGER = Logger.getLogger(ResSmaliUpdater.class
.getName());
}

View File

@ -25,8 +25,7 @@ import java.util.*;
*/
public class ResConfig {
private final ResConfigFlags mFlags;
private final Map<ResResSpec, ResResource> mResources =
new LinkedHashMap<ResResSpec, ResResource>();
private final Map<ResResSpec, ResResource> mResources = new LinkedHashMap<ResResSpec, ResResource>();
public ResConfig(ResConfigFlags flags) {
this.mFlags = flags;
@ -53,15 +52,14 @@ public class ResConfig {
return mFlags;
}
public void addResource(ResResource res)
throws AndrolibException {
public void addResource(ResResource res) throws AndrolibException {
addResource(res, false);
}
public void addResource(ResResource res, boolean overwrite)
throws AndrolibException {
ResResSpec spec = res.getResSpec();
if (mResources.put(spec, res) != null && ! overwrite) {
if (mResources.put(spec, res) != null && !overwrite) {
throw new AndrolibException(String.format(
"Multiple resources: spec=%s, config=%s", spec, this));
}

View File

@ -57,8 +57,8 @@ public class ResConfigFlags {
public ResConfigFlags() {
mcc = 0;
mnc = 0;
language = new char[]{'\00', '\00'};
country = new char[]{'\00', '\00'};
language = new char[] { '\00', '\00' };
country = new char[] { '\00', '\00' };
layoutDirection = SCREENLAYOUT_LAYOUTDIR_ANY;
orientation = ORIENTATION_ANY;
touchscreen = TOUCHSCREEN_ANY;
@ -78,11 +78,12 @@ public class ResConfigFlags {
mQualifiers = "";
}
public ResConfigFlags(short mcc, short mnc, char[] language, char[] country,
short layoutDirection, byte orientation, byte touchscreen,
short density, byte keyboard, byte navigation, byte inputFlags,
short screenWidth, short screenHeight, short sdkVersion, byte screenLayout,
byte uiMode, short smallestScreenWidthDp, short screenWidthDp,
public ResConfigFlags(short mcc, short mnc, char[] language,
char[] country, short layoutDirection, byte orientation,
byte touchscreen, short density, byte keyboard, byte navigation,
byte inputFlags, short screenWidth, short screenHeight,
short sdkVersion, byte screenLayout, byte uiMode,
short smallestScreenWidthDp, short screenWidthDp,
short screenHeightDp, boolean isInvalid) {
if (orientation < 0 || orientation > 3) {
LOGGER.warning("Invalid orientation value: " + orientation);
@ -351,7 +352,7 @@ public class ResConfigFlags {
@Override
public String toString() {
return ! getQualifiers().equals("") ? getQualifiers() : "[DEFAULT]";
return !getQualifiers().equals("") ? getQualifiers() : "[DEFAULT]";
}
@Override
@ -373,7 +374,6 @@ public class ResConfigFlags {
return hash;
}
// TODO: Dirty static hack. This counter should be a part of ResPackage,
// but it would be hard right now and this feature is very rarely used.
private static int sErrCounter = 0;
@ -472,7 +472,6 @@ public class ResConfigFlags {
public final static byte UI_MODE_NIGHT_NO = 0x10;
public final static byte UI_MODE_NIGHT_YES = 0x20;
private static final Logger LOGGER =
Logger.getLogger(ResConfigFlags.class.getName());
private static final Logger LOGGER = Logger.getLogger(ResConfigFlags.class
.getName());
}

View File

@ -31,12 +31,9 @@ public class ResPackage {
private final ResTable mResTable;
private final int mId;
private final String mName;
private final Map<ResID, ResResSpec> mResSpecs =
new LinkedHashMap<ResID, ResResSpec>();
private final Map<ResConfigFlags, ResConfig> mConfigs =
new LinkedHashMap<ResConfigFlags, ResConfig>();
private final Map<String, ResType> mTypes =
new LinkedHashMap<String, ResType>();
private final Map<ResID, ResResSpec> mResSpecs = new LinkedHashMap<ResID, ResResSpec>();
private final Map<ResConfigFlags, ResConfig> mConfigs = new LinkedHashMap<ResConfigFlags, ResConfig>();
private final Map<String, ResType> mTypes = new LinkedHashMap<String, ResType>();
private final Set<ResID> mSynthesizedRes = new HashSet<ResID>();
private ResValueFactory mValueFactory;
@ -118,15 +115,14 @@ public class ResPackage {
}
public Collection<ResValuesFile> listValuesFiles() {
Map<Duo<ResType, ResConfig>, ResValuesFile> ret =
new HashMap<Duo<ResType, ResConfig>, ResValuesFile>();
Map<Duo<ResType, ResConfig>, ResValuesFile> ret = new HashMap<Duo<ResType, ResConfig>, ResValuesFile>();
for (ResResSpec spec : mResSpecs.values()) {
for (ResResource res : spec.listResources()) {
if (res.getValue() instanceof ResValuesXmlSerializable) {
ResType type = res.getResSpec().getType();
ResConfig config = res.getConfig();
Duo<ResType, ResConfig> key =
new Duo<ResType, ResConfig>(type, config);
Duo<ResType, ResConfig> key = new Duo<ResType, ResConfig>(
type, config);
ResValuesFile values = ret.get(key);
if (values == null) {
values = new ResValuesFile(this, type, config);
@ -194,7 +190,9 @@ public class ResPackage {
return false;
}
final ResPackage other = (ResPackage) obj;
if (this.mResTable != other.mResTable && (this.mResTable == null || !this.mResTable.equals(other.mResTable))) {
if (this.mResTable != other.mResTable
&& (this.mResTable == null || !this.mResTable
.equals(other.mResTable))) {
return false;
}
if (this.mId != other.mId) {
@ -206,7 +204,8 @@ public class ResPackage {
@Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + (this.mResTable != null ? this.mResTable.hashCode() : 0);
hash = 31 * hash
+ (this.mResTable != null ? this.mResTable.hashCode() : 0);
hash = 31 * hash + this.mId;
return hash;
}

View File

@ -29,8 +29,7 @@ public class ResResSpec {
private final String mName;
private final ResPackage mPackage;
private final ResType mType;
private final Map<ResConfigFlags, ResResource> mResources =
new LinkedHashMap<ResConfigFlags, ResResource>();
private final Map<ResConfigFlags, ResResource> mResources = new LinkedHashMap<ResConfigFlags, ResResource>();
public ResResSpec(ResID id, String name, ResPackage pkg, ResType type) {
this.mId = id;
@ -77,16 +76,13 @@ public class ResResSpec {
return getFullName(false, false);
}
public String getFullName(ResPackage relativeToPackage,
boolean excludeType) {
return getFullName(
getPackage().equals(relativeToPackage), excludeType);
public String getFullName(ResPackage relativeToPackage, boolean excludeType) {
return getFullName(getPackage().equals(relativeToPackage), excludeType);
}
public String getFullName(boolean excludePackage, boolean excludeType) {
return
(excludePackage ? "" : getPackage().getName() + ":") +
(excludeType ? "" : getType().getName() + "/") + getName();
return (excludePackage ? "" : getPackage().getName() + ":")
+ (excludeType ? "" : getType().getName() + "/") + getName();
}
public ResID getId() {
@ -105,16 +101,16 @@ public class ResResSpec {
return mType;
}
public void addResource(ResResource res)
throws AndrolibException {
public void addResource(ResResource res) throws AndrolibException {
addResource(res, false);
}
public void addResource(ResResource res, boolean overwrite)
throws AndrolibException {
ResConfigFlags flags = res.getConfig().getFlags();
if (mResources.put(flags, res) != null && ! overwrite) {
throw new AndrolibException(String.format("Multiple resources: spec=%s, config=%s", this, flags));
if (mResources.put(flags, res) != null && !overwrite) {
throw new AndrolibException(String.format(
"Multiple resources: spec=%s, config=%s", this, flags));
}
}

View File

@ -27,16 +27,15 @@ public class ResResource {
private final ResResSpec mResSpec;
private final ResValue mValue;
public ResResource(ResConfig config, ResResSpec spec,
ResValue value) {
public ResResource(ResConfig config, ResResSpec spec, ResValue value) {
this.mConfig = config;
this.mResSpec = spec;
this.mValue = value;
}
public String getFilePath() {
return mResSpec.getType().getName() +
mConfig.getFlags().getQualifiers() + "/" + mResSpec.getName();
return mResSpec.getType().getName()
+ mConfig.getFlags().getQualifiers() + "/" + mResSpec.getName();
}
public ResConfig getConfig() {

View File

@ -28,14 +28,10 @@ import java.util.*;
public class ResTable {
private final AndrolibResources mAndRes;
private final Map<Integer, ResPackage> mPackagesById =
new HashMap<Integer, ResPackage>();
private final Map<String, ResPackage> mPackagesByName =
new HashMap<String, ResPackage>();
private final Set<ResPackage> mMainPackages =
new LinkedHashSet<ResPackage>();
private final Set<ResPackage> mFramePackages =
new LinkedHashSet<ResPackage>();
private final Map<Integer, ResPackage> mPackagesById = new HashMap<Integer, ResPackage>();
private final Map<String, ResPackage> mPackagesByName = new HashMap<String, ResPackage>();
private final Set<ResPackage> mMainPackages = new LinkedHashSet<ResPackage>();
private final Set<ResPackage> mFramePackages = new LinkedHashSet<ResPackage>();
private String mFrameTag;
@ -103,8 +99,8 @@ public class ResTable {
throws AndrolibException {
Integer id = pkg.getId();
if (mPackagesById.containsKey(id)) {
throw new AndrolibException(
"Multiple packages: id=" + id.toString());
throw new AndrolibException("Multiple packages: id="
+ id.toString());
}
String name = pkg.getName();
if (mPackagesByName.containsKey(name)) {

View File

@ -25,14 +25,12 @@ import java.util.*;
*/
public final class ResType {
private final String mName;
private final Map<String, ResResSpec> mResSpecs =
new LinkedHashMap<String, ResResSpec>();
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>();
private final ResTable mResTable;
private final ResPackage mPackage;
public ResType(String name, ResTable resTable,
ResPackage package_) {
public ResType(String name, ResTable resTable, ResPackage package_) {
this.mName = name;
this.mResTable = resTable;
this.mPackage = package_;
@ -49,14 +47,13 @@ public final class ResType {
public ResResSpec getResSpec(String name) throws AndrolibException {
ResResSpec spec = mResSpecs.get(name);
if (spec == null) {
throw new UndefinedResObject(String.format(
"resource spec: %s/%s", getName(), name));
throw new UndefinedResObject(String.format("resource spec: %s/%s",
getName(), name));
}
return spec;
}
public void addResSpec(ResResSpec spec)
throws AndrolibException {
public void addResSpec(ResResSpec spec) throws AndrolibException {
if (mResSpecs.put(spec.getName(), spec) != null) {
throw new AndrolibException(String.format(
"Multiple res specs: %s/%s", getName(), spec.getName()));

View File

@ -26,8 +26,7 @@ public class ResValuesFile {
private final ResPackage mPackage;
private final ResType mType;
private final ResConfig mConfig;
private final Set<ResResource> mResources =
new LinkedHashSet<ResResource>();
private final Set<ResResource> mResources = new LinkedHashSet<ResResource>();
public ResValuesFile(ResPackage pkg, ResType type, ResConfig config) {
this.mPackage = pkg;
@ -36,9 +35,8 @@ public class ResValuesFile {
}
public String getPath() {
return "values" + mConfig.getFlags().getQualifiers()
+ "/" + mType.getName()
+ (mType.getName().endsWith("s") ? "" : "s")
return "values" + mConfig.getFlags().getQualifiers() + "/"
+ mType.getName() + (mType.getName().endsWith("s") ? "" : "s")
+ ".xml";
}
@ -71,10 +69,12 @@ public class ResValuesFile {
return false;
}
final ResValuesFile other = (ResValuesFile) obj;
if (this.mType != other.mType && (this.mType == null || !this.mType.equals(other.mType))) {
if (this.mType != other.mType
&& (this.mType == null || !this.mType.equals(other.mType))) {
return false;
}
if (this.mConfig != other.mConfig && (this.mConfig == null || !this.mConfig.equals(other.mConfig))) {
if (this.mConfig != other.mConfig
&& (this.mConfig == null || !this.mConfig.equals(other.mConfig))) {
return false;
}
return true;

View File

@ -22,15 +22,15 @@ import brut.androlib.res.xml.ResValuesXmlSerializable;
import brut.util.Duo;
import java.io.IOException;
import org.xmlpull.v1.XmlSerializer;
import org.apache.commons.lang3.StringUtils;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResArrayValue extends ResBagValue implements ResValuesXmlSerializable {
public class ResArrayValue extends ResBagValue implements
ResValuesXmlSerializable {
private String mRawItems;
ResArrayValue(ResReferenceValue parent,
Duo<Integer, ResScalarValue>[] items) {
ResArrayValue(ResReferenceValue parent, Duo<Integer, ResScalarValue>[] items) {
super(parent);
mItems = new ResScalarValue[items.length];
@ -45,15 +45,15 @@ public class ResArrayValue extends ResBagValue implements ResValuesXmlSerializab
}
@Override
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException {
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
String type = getType();
type = (type == null ? "" : type + "-") + "array";
// reference array (04 10 2012, BurgerZ)
// reference array (04 10 2012, BurgerZ)
if ("reference-array".equals(type)) {
type = "string-array";
}
// reference array (04 10 2012, BurgerZ)
// reference array (04 10 2012, BurgerZ)
serializer.startTag(null, type);
serializer.attribute(null, "name", res.getResSpec().getName());
for (int i = 0; i < mItems.length; i++) {
@ -73,7 +73,8 @@ public class ResArrayValue extends ResBagValue implements ResValuesXmlSerializab
if (mItems[i].encodeAsResXmlItemValue().startsWith("@string")) {
return "string";
} else if (mItems[i].encodeAsResXmlItemValue().startsWith("@drawable")) {
} else if (mItems[i].encodeAsResXmlItemValue().startsWith(
"@drawable")) {
return null;
} else if (!"string".equals(type) && !"integer".equals(type)) {
return null;
@ -86,6 +87,5 @@ public class ResArrayValue extends ResBagValue implements ResValuesXmlSerializab
private final ResScalarValue[] mItems;
public static final int BAG_KEY_ARRAY_START = 0x02000000;
}

View File

@ -43,8 +43,8 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
}
@Override
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException {
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
String type = getTypeAsString();
serializer.startTag(null, "attr");
@ -65,7 +65,6 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
serializer.endTag(null, "attr");
}
public static ResAttr factory(ResReferenceValue parent,
Duo<Integer, ResScalarValue>[] items, ResValueFactory factory,
ResPackage pkg) throws AndrolibException {
@ -93,29 +92,31 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
if (i == items.length) {
return new ResAttr(parent, scalarType, min, max, l10n);
}
Duo<ResReferenceValue, ResIntValue>[] attrItems =
new Duo[items.length - i];
Duo<ResReferenceValue, ResIntValue>[] attrItems = new Duo[items.length
- i];
int j = 0;
for (; i < items.length; i++) {
int resId = items[i].m1;
pkg.addSynthesizedRes(resId);
attrItems[j++] = new Duo<ResReferenceValue, ResIntValue>(
factory.newReference(resId, null), (ResIntValue) items[i].m2);
factory.newReference(resId, null),
(ResIntValue) items[i].m2);
}
switch (type & 0xff0000) {
case TYPE_ENUM:
return new ResEnumAttr(
parent, scalarType, min, max, l10n, attrItems);
return new ResEnumAttr(parent, scalarType, min, max, l10n,
attrItems);
case TYPE_FLAGS:
return new ResFlagsAttr(
parent, scalarType, min, max, l10n, attrItems);
return new ResFlagsAttr(parent, scalarType, min, max, l10n,
attrItems);
}
throw new AndrolibException("Could not decode attr value");
}
protected void serializeBody(XmlSerializer serializer, ResResource res)
throws AndrolibException, IOException {}
throws AndrolibException, IOException {
}
protected String getTypeAsString() {
String s = "";
@ -154,7 +155,6 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
private final Integer mMax;
private final Boolean mL10n;
public static final int BAG_KEY_ATTR_TYPE = 0x01000000;
private static final int BAG_KEY_ATTR_MIN = 0x01000001;
private static final int BAG_KEY_ATTR_MAX = 0x01000002;

View File

@ -33,8 +33,9 @@ public class ResBagValue extends ResValue implements ResValuesXmlSerializable {
this.mParent = parent;
}
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException {
@Override
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
String type = res.getResSpec().getType().getName();
if ("style".equals(type)) {
new ResStyleValue(mParent, new Duo[0], null)
@ -42,13 +43,13 @@ public class ResBagValue extends ResValue implements ResValuesXmlSerializable {
return;
}
if ("array".equals(type)) {
new ResArrayValue(mParent, new Duo[0])
.serializeToResValuesXml(serializer, res);
new ResArrayValue(mParent, new Duo[0]).serializeToResValuesXml(
serializer, res);
return;
}
if ("plurals".equals(type)) {
new ResPluralsValue(mParent, new Duo[0])
.serializeToResValuesXml(serializer, res);
new ResPluralsValue(mParent, new Duo[0]).serializeToResValuesXml(
serializer, res);
return;
}

View File

@ -31,6 +31,7 @@ public class ResBoolValue extends ResScalarValue {
return mValue;
}
@Override
protected String encodeAsResXml() {
return mValue ? "true" : "false";
}

View File

@ -77,8 +77,6 @@ public class ResEnumAttr extends ResAttr {
return value2;
}
private final Duo<ResReferenceValue, ResIntValue>[] mItems;
private final Map<Integer, String> mItemsCache =
new HashMap<Integer, String>();
private final Map<Integer, String> mItemsCache = new HashMap<Integer, String>();
}

View File

@ -33,7 +33,7 @@ public class ResFileValue extends ResValue {
}
public String getStrippedPath() throws AndrolibException {
if (! mPath.startsWith("res/")) {
if (!mPath.startsWith("res/")) {
throw new AndrolibException(
"File path does not start with \"res/\": " + mPath);
}

View File

@ -28,7 +28,8 @@ import org.xmlpull.v1.XmlSerializer;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResFlagsAttr extends ResAttr {
ResFlagsAttr(ResReferenceValue parent, int type, Integer min, Integer max, Boolean l10n, Duo<ResReferenceValue, ResIntValue>[] items) {
ResFlagsAttr(ResReferenceValue parent, int type, Integer min, Integer max,
Boolean l10n, Duo<ResReferenceValue, ResIntValue>[] items) {
super(parent, type, min, max, l10n);
mItems = new FlagItem[items.length];
@ -40,7 +41,7 @@ public class ResFlagsAttr extends ResAttr {
@Override
public String convertToResXmlFormat(ResScalarValue value)
throws AndrolibException {
if (! (value instanceof ResIntValue)) {
if (!(value instanceof ResIntValue)) {
return super.convertToResXmlFormat(value);
}
loadFlags();
@ -61,7 +62,7 @@ public class ResFlagsAttr extends ResAttr {
continue;
}
if (! isSubpartOf(flag, flags)) {
if (!isSubpartOf(flag, flags)) {
flags[flagsCount] = flag;
flagItems[flagsCount++] = flagItem;
}
@ -126,20 +127,19 @@ public class ResFlagsAttr extends ResAttr {
mFlags = Arrays.copyOf(flags, flagsCount);
Arrays.sort(mFlags, new Comparator<FlagItem>() {
@Override
public int compare(FlagItem o1, FlagItem o2) {
return Integer.valueOf(Integer.bitCount(o2.flag))
.compareTo(Integer.bitCount(o1.flag));
return Integer.valueOf(Integer.bitCount(o2.flag)).compareTo(
Integer.bitCount(o1.flag));
}
});
}
private final FlagItem[] mItems;
private FlagItem[] mZeroFlags;
private FlagItem[] mFlags;
private static class FlagItem {
public final ResReferenceValue ref;
public final int flag;

View File

@ -31,6 +31,7 @@ public class ResFloatValue extends ResScalarValue {
return mValue;
}
@Override
protected String encodeAsResXml() {
return String.valueOf(mValue);
}

View File

@ -26,9 +26,12 @@ import org.xmlpull.v1.XmlSerializer;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResIdValue extends ResValue implements ResValuesXmlSerializable {
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res) throws IOException, AndrolibException {
@Override
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
serializer.startTag(null, "item");
serializer.attribute(null, "type", res.getResSpec().getType().getName());
serializer
.attribute(null, "type", res.getResSpec().getType().getName());
serializer.attribute(null, "name", res.getResSpec().getName());
serializer.endTag(null, "item");
}

View File

@ -40,6 +40,7 @@ public class ResIntValue extends ResScalarValue {
return mValue;
}
@Override
protected String encodeAsResXml() throws AndrolibException {
return TypedValue.coerceToString(type, mValue);
}

View File

@ -28,21 +28,21 @@ import org.xmlpull.v1.XmlSerializer;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResPluralsValue extends ResBagValue implements ResValuesXmlSerializable {
public class ResPluralsValue extends ResBagValue implements
ResValuesXmlSerializable {
ResPluralsValue(ResReferenceValue parent,
Duo<Integer, ResScalarValue>[] items) {
super(parent);
mItems = new ResScalarValue[6];
for (int i = 0; i < items.length; i++) {
mItems[items[i].m1 - BAG_KEY_PLURALS_START] =
(ResScalarValue) items[i].m2;
mItems[items[i].m1 - BAG_KEY_PLURALS_START] = items[i].m2;
}
}
@Override
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException {
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
serializer.startTag(null, "plurals");
serializer.attribute(null, "name", res.getResSpec().getName());
for (int i = 0; i < mItems.length; i++) {
@ -55,13 +55,18 @@ public class ResPluralsValue extends ResBagValue implements ResValuesXmlSerializ
serializer.startTag(null, "item");
serializer.attribute(null, "quantity", QUANTITY_MAP[i]);
if (ResXmlEncoders.hasMultipleNonPositionalSubstitutions(rawValue.encodeAsResXmlValue())) {
if (ResXmlEncoders.hasMultipleNonPositionalSubstitutions(rawValue
.encodeAsResXmlValue())) {
serializer.text(item.encodeAsResXmlValueExt());
} else {
String recode = item.encodeAsResXmlValue();
//Dirty, but working fix @miuirussia
// Dirty, but working fix @miuirussia
for (int j = 0; j < 10; j++) {
recode = StringUtils.replace(recode, "%" + Integer.toString(j) + "$" + Integer.toString(j) + "$", "%" + Integer.toString(j) + "$");
recode = StringUtils.replace(
recode,
"%" + Integer.toString(j) + "$"
+ Integer.toString(j) + "$",
"%" + Integer.toString(j) + "$");
}
serializer.text(recode);
}
@ -70,12 +75,10 @@ public class ResPluralsValue extends ResBagValue implements ResValuesXmlSerializ
serializer.endTag(null, "plurals");
}
private final ResScalarValue[] mItems;
public static final int BAG_KEY_PLURALS_START = 0x01000004;
public static final int BAG_KEY_PLURALS_END = 0x01000009;
private static final String[] QUANTITY_MAP =
new String[] {"other", "zero", "one", "two", "few", "many"};
private static final String[] QUANTITY_MAP = new String[] { "other",
"zero", "one", "two", "few", "many" };
}

View File

@ -38,23 +38,23 @@ public class ResReferenceValue extends ResIntValue {
mTheme = theme;
}
@Override
protected String encodeAsResXml() throws AndrolibException {
if (isNull()) {
return "@null";
}
ResResSpec spec = getReferent();
boolean newId =
spec.hasDefaultResource() &&
spec.getDefaultResource().getValue() instanceof ResIdValue;
boolean newId = spec.hasDefaultResource()
&& spec.getDefaultResource().getValue() instanceof ResIdValue;
// generate the beginning to fix @android
String mStart = (mTheme ? '?' : '@') + (newId ? "+" : "");
//mStart = mStart.replace("@android", "@*android");
// mStart = mStart.replace("@android", "@*android");
return mStart +
spec.getFullName(mPackage,
mTheme && spec.getType().getName().equals("attr"));
return mStart
+ spec.getFullName(mPackage, mTheme
&& spec.getType().getName().equals("attr"));
}
public ResResSpec getReferent() throws AndrolibException {

View File

@ -27,8 +27,8 @@ import org.xmlpull.v1.XmlSerializer;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public abstract class ResScalarValue extends ResValue
implements ResXmlEncodable, ResValuesXmlSerializable {
public abstract class ResScalarValue extends ResValue implements
ResXmlEncodable, ResValuesXmlSerializable {
protected final String mType;
protected final String mRawValue;
@ -37,6 +37,7 @@ public abstract class ResScalarValue extends ResValue
mRawValue = rawValue;
}
@Override
public String encodeAsResXmlAttr() throws AndrolibException {
if (mRawValue != null) {
return mRawValue;
@ -48,6 +49,7 @@ public abstract class ResScalarValue extends ResValue
return encodeAsResXmlValue().replace("@android:", "@*android:");
}
@Override
public String encodeAsResXmlValue() throws AndrolibException {
if (mRawValue != null) {
return mRawValue;
@ -63,19 +65,19 @@ public abstract class ResScalarValue extends ResValue
StringBuilder result = new StringBuilder();
String tmp1[] = rawValue.split("%%", -1);
int tmp1_sz = tmp1.length;
for(int i=0;i<tmp1_sz;i++) {
for (int i = 0; i < tmp1_sz; i++) {
String cur1 = tmp1[i];
String tmp2[] = cur1.split("%", -1);
int tmp2_sz = tmp2.length;
for(int j=0;j<tmp2_sz;j++) {
for (int j = 0; j < tmp2_sz; j++) {
String cur2 = tmp2[j];
result.append(cur2);
if(j != (tmp2_sz-1)) {
if (j != (tmp2_sz - 1)) {
result.append('%').append(count).append('$');
count++;
}
}
if(i != (tmp1_sz-1)) {
if (i != (tmp1_sz - 1)) {
result.append("%%");
}
}
@ -86,17 +88,17 @@ public abstract class ResScalarValue extends ResValue
return encodeAsResXml();
}
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException {
@Override
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
String type = res.getResSpec().getType().getName();
boolean item = !"reference".equals(mType) && !type.equals(mType);
String body = encodeAsResXmlValue();
// check for resource reference
if (body.contains("@")){
if(!res.getFilePath().contains("string")) {
if (body.contains("@")) {
if (!res.getFilePath().contains("string")) {
item = true;
}
}
@ -112,7 +114,7 @@ public abstract class ResScalarValue extends ResValue
serializeExtraXmlAttrs(serializer, res);
if (! body.isEmpty()) {
if (!body.isEmpty()) {
serializer.ignorableWhitespace(body);
}

View File

@ -42,8 +42,9 @@ public class ResStringValue extends ResScalarValue {
@Override
public String encodeAsResXmlItemValue() {
return ResXmlEncoders.enumerateNonPositionalSubstitutions(
ResXmlEncoders.encodeAsXmlValue(mRawValue));
return ResXmlEncoders
.enumerateNonPositionalSubstitutions(ResXmlEncoders
.encodeAsXmlValue(mRawValue));
}
@Override

View File

@ -27,7 +27,8 @@ import org.xmlpull.v1.XmlSerializer;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResStyleValue extends ResBagValue implements ResValuesXmlSerializable {
public class ResStyleValue extends ResBagValue implements
ResValuesXmlSerializable {
ResStyleValue(ResReferenceValue parent,
Duo<Integer, ResScalarValue>[] items, ResValueFactory factory) {
super(parent);
@ -40,18 +41,19 @@ public class ResStyleValue extends ResBagValue implements ResValuesXmlSerializab
}
@Override
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException {
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException {
serializer.startTag(null, "style");
serializer.attribute(null, "name", res.getResSpec().getName());
if (! mParent.isNull()) {
if (!mParent.isNull()) {
serializer.attribute(null, "parent", mParent.encodeAsResXmlAttr());
}
for (int i = 0; i < mItems.length; i++) {
ResResSpec spec = mItems[i].m1.getReferent();
// hacky-fix remove bad ReferenceVars
if (spec.getDefaultResource().getValue().toString().contains("ResReferenceValue@")) {
if (spec.getDefaultResource().getValue().toString()
.contains("ResReferenceValue@")) {
continue;
}
ResAttr attr = (ResAttr) spec.getDefaultResource().getValue();
@ -74,6 +76,5 @@ public class ResStyleValue extends ResBagValue implements ResValuesXmlSerializab
serializer.endTag(null, "style");
}
private final Duo<ResReferenceValue, ResScalarValue>[] mItems;
}

View File

@ -59,7 +59,7 @@ public class ResValueFactory {
return new ResIntValue(value, rawValue, type);
}
throw new AndrolibException("Invalid value type: "+ type);
throw new AndrolibException("Invalid value type: " + type);
}
public ResValue factory(String value) {

View File

@ -47,10 +47,8 @@ public class ARSCDecoder {
ARSCDecoder decoder = new ARSCDecoder(arscStream, resTable,
findFlagsOffsets, keepBroken);
ResPackage[] pkgs = decoder.readTable();
return new ARSCData(
pkgs,
decoder.mFlagsOffsets == null ? null :
decoder.mFlagsOffsets.toArray(new FlagsOffset[0]),
return new ARSCData(pkgs, decoder.mFlagsOffsets == null ? null
: decoder.mFlagsOffsets.toArray(new FlagsOffset[0]),
resTable);
} catch (IOException ex) {
throw new AndrolibException("Could not decode arsc file", ex);
@ -94,10 +92,10 @@ public class ARSCDecoder {
checkChunkType(Header.TYPE_PACKAGE);
int id = (byte) mIn.readInt();
String name = mIn.readNulEndedString(128, true);
/*typeNameStrings*/ mIn.skipInt();
/*typeNameCount*/ mIn.skipInt();
/*specNameStrings*/ mIn.skipInt();
/*specNameCount*/ mIn.skipInt();
/* typeNameStrings */mIn.skipInt();
/* typeNameCount */mIn.skipInt();
/* specNameStrings */mIn.skipInt();
/* specNameCount */mIn.skipInt();
mTypeNames = StringBlock.read(mIn);
mSpecNames = StringBlock.read(mIn);
@ -125,7 +123,7 @@ public class ARSCDecoder {
if (mFlagsOffsets != null) {
mFlagsOffsets.add(new FlagsOffset(mCountIn.getCount(), entryCount));
}
/*flags*/ mIn.skipBytes(entryCount * 4);
/* flags */mIn.skipBytes(entryCount * 4);
mResId = (0xff000000 & mResId) | id << 16;
mType = new ResType(mTypeNames.getString(id - 1), mResTable, mPkg);
@ -142,9 +140,9 @@ public class ARSCDecoder {
private ResConfig readConfig() throws IOException, AndrolibException {
checkChunkType(Header.TYPE_CONFIG);
/*typeId*/ mIn.skipInt();
/* typeId */mIn.skipInt();
int entryCount = mIn.readInt();
/*entriesStart*/ mIn.skipInt();
/* entriesStart */mIn.skipInt();
ResConfigFlags flags = readConfigFlags();
int[] entryOffsets = mIn.readIntArray(entryCount);
@ -152,16 +150,15 @@ public class ARSCDecoder {
if (flags.isInvalid) {
String resName = mType.getName() + flags.getQualifiers();
if (mKeepBroken) {
LOGGER.warning(
"Invalid config flags detected: " + resName);
LOGGER.warning("Invalid config flags detected: " + resName);
} else {
LOGGER.warning(
"Invalid config flags detected. Dropping resources: " + resName);
LOGGER.warning("Invalid config flags detected. Dropping resources: "
+ resName);
}
}
mConfig = flags.isInvalid && ! mKeepBroken ?
null : mPkg.getOrCreateConfig(flags);
mConfig = flags.isInvalid && !mKeepBroken ? null : mPkg
.getOrCreateConfig(flags);
for (int i = 0; i < entryOffsets.length; i++) {
if (entryOffsets[i] != -1) {
@ -175,12 +172,12 @@ public class ARSCDecoder {
}
private void readEntry() throws IOException, AndrolibException {
/*size*/ mIn.skipBytes(2);
/* size */mIn.skipBytes(2);
short flags = mIn.readShort();
int specNamesId = mIn.readInt();
ResValue value = (flags & ENTRY_FLAG_COMPLEX) == 0 ?
readValue() : readComplexEntry();
ResValue value = (flags & ENTRY_FLAG_COMPLEX) == 0 ? readValue()
: readComplexEntry();
if (mConfig == null) {
return;
@ -191,8 +188,8 @@ public class ARSCDecoder {
if (mPkg.hasResSpec(resId)) {
spec = mPkg.getResSpec(resId);
} else {
spec = new ResResSpec(
resId, mSpecNames.getString(specNamesId), mPkg, mType);
spec = new ResResSpec(resId, mSpecNames.getString(specNamesId),
mPkg, mType);
mPkg.addResSpec(spec);
mType.addResSpec(spec);
}
@ -211,25 +208,26 @@ public class ARSCDecoder {
ResValueFactory factory = mPkg.getValueFactory();
Duo<Integer, ResScalarValue>[] items = new Duo[count];
for (int i = 0; i < count; i++) {
items[i] = new Duo<Integer, ResScalarValue>(
mIn.readInt(), (ResScalarValue) readValue());
items[i] = new Duo<Integer, ResScalarValue>(mIn.readInt(),
(ResScalarValue) readValue());
}
return factory.bagFactory(parent, items);
}
private ResValue readValue() throws IOException, AndrolibException {
/*size*/ mIn.skipCheckShort((short) 8);
/*zero*/ mIn.skipCheckByte((byte) 0);
/* size */mIn.skipCheckShort((short) 8);
/* zero */mIn.skipCheckByte((byte) 0);
byte type = mIn.readByte();
int data = mIn.readInt();
return type == TypedValue.TYPE_STRING ?
mPkg.getValueFactory().factory(mTableStrings.getHTML(data)) :
mPkg.getValueFactory().factory(type, data, null);
return type == TypedValue.TYPE_STRING ? mPkg.getValueFactory().factory(
mTableStrings.getHTML(data)) : mPkg.getValueFactory().factory(
type, data, null);
}
private ResConfigFlags readConfigFlags() throws IOException, AndrolibException {
private ResConfigFlags readConfigFlags() throws IOException,
AndrolibException {
int size = mIn.readInt();
if (size < 28) {
throw new AndrolibException("Config size < 28");
@ -240,10 +238,10 @@ public class ARSCDecoder {
short mcc = mIn.readShort();
short mnc = mIn.readShort();
char[] language = new char[]{
(char) mIn.readByte(), (char) mIn.readByte()};
char[] country = new char[]{
(char) mIn.readByte(), (char) mIn.readByte()};
char[] language = new char[] { (char) mIn.readByte(),
(char) mIn.readByte() };
char[] country = new char[] { (char) mIn.readByte(),
(char) mIn.readByte() };
byte orientation = mIn.readByte();
byte touchscreen = mIn.readByte();
@ -252,13 +250,13 @@ public class ARSCDecoder {
byte keyboard = mIn.readByte();
byte navigation = mIn.readByte();
byte inputFlags = mIn.readByte();
/*inputPad0*/ mIn.skipBytes(1);
/* inputPad0 */mIn.skipBytes(1);
short screenWidth = mIn.readShort();
short screenHeight = mIn.readShort();
short sdkVersion = mIn.readShort();
/*minorVersion, now must always be 0*/ mIn.skipBytes(2);
/* minorVersion, now must always be 0 */mIn.skipBytes(2);
byte screenLayout = 0;
byte uiMode = 0;
@ -278,7 +276,8 @@ public class ARSCDecoder {
}
short layoutDirection = 0;
if (size >= 38 && sdkVersion >= 17 && !this.mPkg.getName().equalsIgnoreCase("com.htc")) {
if (size >= 38 && sdkVersion >= 17
&& !this.mPkg.getName().equalsIgnoreCase("com.htc")) {
layoutDirection = mIn.readShort();
}
@ -289,8 +288,8 @@ public class ARSCDecoder {
BigInteger exceedingBI = new BigInteger(1, buf);
if (exceedingBI.equals(BigInteger.ZERO)) {
LOGGER.fine(String.format(
"Config flags size > %d, but exceeding bytes are all zero, so it should be ok.",
LOGGER.fine(String
.format("Config flags size > %d, but exceeding bytes are all zero, so it should be ok.",
KNOWN_CONFIG_BYTES));
} else {
LOGGER.warning(String.format(
@ -300,17 +299,18 @@ public class ARSCDecoder {
}
}
return new ResConfigFlags(mcc, mnc, language, country, layoutDirection, orientation,
touchscreen, density, keyboard, navigation, inputFlags,
screenWidth, screenHeight, sdkVersion, screenLayout, uiMode,
smallestScreenWidthDp, screenWidthDp, screenHeightDp, isInvalid);
return new ResConfigFlags(mcc, mnc, language, country, layoutDirection,
orientation, touchscreen, density, keyboard, navigation,
inputFlags, screenWidth, screenHeight, sdkVersion,
screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp,
screenHeightDp, isInvalid);
}
private void addMissingResSpecs() throws AndrolibException {
int resId = mResId & 0xffff0000;
for (int i = 0; i < mMissingResSpecs.length; i++) {
if (! mMissingResSpecs[i]) {
if (!mMissingResSpecs[i]) {
continue;
}
@ -340,8 +340,8 @@ public class ARSCDecoder {
}
}
private void nextChunkCheckType(int expectedType)
throws IOException, AndrolibException {
private void nextChunkCheckType(int expectedType) throws IOException,
AndrolibException {
nextChunk();
checkChunkType(expectedType);
}
@ -362,10 +362,8 @@ public class ARSCDecoder {
private int mResId;
private boolean[] mMissingResSpecs;
private final static short ENTRY_FLAG_COMPLEX = 0x0001;
public static class Header {
public final short type;
public final int chunkSize;
@ -386,11 +384,8 @@ public class ARSCDecoder {
return new Header(type, in.readInt());
}
public final static short
TYPE_NONE = -1,
TYPE_TABLE = 0x0002,
TYPE_PACKAGE = 0x0200,
TYPE_TYPE = 0x0202,
public final static short TYPE_NONE = -1, TYPE_TABLE = 0x0002,
TYPE_PACKAGE = 0x0200, TYPE_TYPE = 0x0202,
TYPE_CONFIG = 0x0201;
}
@ -404,11 +399,10 @@ public class ARSCDecoder {
}
}
private static final Logger LOGGER =
Logger.getLogger(ARSCDecoder.class.getName());
private static final Logger LOGGER = Logger.getLogger(ARSCDecoder.class
.getName());
private static final int KNOWN_CONFIG_BYTES = 36;
public static class ARSCData {
public ARSCData(ResPackage[] packages, FlagsOffset[] flagsOffsets,

View File

@ -34,11 +34,11 @@ import org.xmlpull.v1.XmlPullParserException;
*
* Binary xml files parser.
*
* Parser has only two states: (1) Operational state, which parser obtains after
* first successful call to next() and retains until open(), close(), or failed
* call to next(). (2) Closed state, which parser obtains after open(), close(),
* or failed call to next(). In this state methods return invalid values or
* throw exceptions.
* Parser has only two states: (1) Operational state, which parser
* obtains after first successful call to next() and retains until
* open(), close(), or failed call to next(). (2) Closed state, which
* parser obtains after open(), close(), or failed call to next(). In
* this state methods return invalid values or throw exceptions.
*
* TODO: * check all methods in closed state
*
@ -69,17 +69,17 @@ public class AXmlResourceParser implements XmlResourceParser {
public void open(InputStream stream) {
close();
if (stream != null) {
m_reader = new ExtDataInput(
new LEDataInputStream(stream));
m_reader = new ExtDataInput(new LEDataInputStream(stream));
}
}
@Override
public void close() {
if (!m_operational) {
return;
}
m_operational = false;
// m_reader.close();
// m_reader.close();
m_reader = null;
m_strings = null;
m_resourceIDs = null;
@ -87,10 +87,12 @@ public class AXmlResourceParser implements XmlResourceParser {
resetEventInfo();
}
/////////////////////////////////// iteration
// ///////////////////////////////// iteration
@Override
public int next() throws XmlPullParserException, IOException {
if (m_reader == null) {
throw new XmlPullParserException("Parser is not opened.", this, null);
throw new XmlPullParserException("Parser is not opened.", this,
null);
}
try {
doNext();
@ -101,60 +103,77 @@ public class AXmlResourceParser implements XmlResourceParser {
}
}
@Override
public int nextToken() throws XmlPullParserException, IOException {
return next();
}
@Override
public int nextTag() throws XmlPullParserException, IOException {
int eventType = next();
if (eventType == TEXT && isWhitespace()) {
eventType = next();
}
if (eventType != START_TAG && eventType != END_TAG) {
throw new XmlPullParserException("Expected start or end tag.", this, null);
throw new XmlPullParserException("Expected start or end tag.",
this, null);
}
return eventType;
}
@Override
public String nextText() throws XmlPullParserException, IOException {
if (getEventType() != START_TAG) {
throw new XmlPullParserException("Parser must be on START_TAG to read next text.", this, null);
throw new XmlPullParserException(
"Parser must be on START_TAG to read next text.", this,
null);
}
int eventType = next();
if (eventType == TEXT) {
String result = getText();
eventType = next();
if (eventType != END_TAG) {
throw new XmlPullParserException("Event TEXT must be immediately followed by END_TAG.", this, null);
throw new XmlPullParserException(
"Event TEXT must be immediately followed by END_TAG.",
this, null);
}
return result;
} else if (eventType == END_TAG) {
return "";
} else {
throw new XmlPullParserException("Parser must be on START_TAG or TEXT to read text.", this, null);
throw new XmlPullParserException(
"Parser must be on START_TAG or TEXT to read text.", this,
null);
}
}
public void require(int type, String namespace, String name) throws XmlPullParserException, IOException {
@Override
public void require(int type, String namespace, String name)
throws XmlPullParserException, IOException {
if (type != getEventType()
|| (namespace != null && !namespace.equals(getNamespace()))
|| (name != null && !name.equals(getName()))) {
throw new XmlPullParserException(TYPES[type] + " is expected.", this, null);
throw new XmlPullParserException(TYPES[type] + " is expected.",
this, null);
}
}
@Override
public int getDepth() {
return m_namespaces.getDepth() - 1;
}
@Override
public int getEventType() throws XmlPullParserException {
return m_event;
}
@Override
public int getLineNumber() {
return m_lineNumber;
}
@Override
public String getName() {
if (m_name == -1 || (m_event != START_TAG && m_event != END_TAG)) {
return null;
@ -162,6 +181,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(m_name);
}
@Override
public String getText() {
if (m_name == -1 || m_event != TEXT) {
return null;
@ -169,6 +189,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(m_name);
}
@Override
public char[] getTextCharacters(int[] holderForStartAndLength) {
String text = getText();
if (text == null) {
@ -181,34 +202,41 @@ public class AXmlResourceParser implements XmlResourceParser {
return chars;
}
@Override
public String getNamespace() {
return m_strings.getString(m_namespaceUri);
}
@Override
public String getPrefix() {
int prefix = m_namespaces.findPrefix(m_namespaceUri);
return m_strings.getString(prefix);
}
@Override
public String getPositionDescription() {
return "XML line #" + getLineNumber();
}
@Override
public int getNamespaceCount(int depth) throws XmlPullParserException {
return m_namespaces.getAccumulatedCount(depth);
}
@Override
public String getNamespacePrefix(int pos) throws XmlPullParserException {
int prefix = m_namespaces.getPrefix(pos);
return m_strings.getString(prefix);
}
@Override
public String getNamespaceUri(int pos) throws XmlPullParserException {
int uri = m_namespaces.getUri(pos);
return m_strings.getString(uri);
}
/////////////////////////////////// attributes
// ///////////////////////////////// attributes
@Override
public String getClassAttribute() {
if (m_classAttribute == -1) {
return null;
@ -218,6 +246,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(value);
}
@Override
public String getIdAttribute() {
if (m_idAttribute == -1) {
return null;
@ -227,6 +256,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(value);
}
@Override
public int getIdAttributeResourceValue(int defaultValue) {
if (m_idAttribute == -1) {
return defaultValue;
@ -239,6 +269,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
}
@Override
public int getStyleAttribute() {
if (m_styleAttribute == -1) {
return 0;
@ -247,6 +278,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
}
@Override
public int getAttributeCount() {
if (m_event != START_TAG) {
return -1;
@ -254,6 +286,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_attributes.length / ATTRIBUTE_LENGHT;
}
@Override
public String getAttributeNamespace(int index) {
int offset = getAttributeOffset(index);
int namespace = m_attributes[offset + ATTRIBUTE_IX_NAMESPACE_URI];
@ -263,6 +296,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(namespace);
}
@Override
public String getAttributePrefix(int index) {
int offset = getAttributeOffset(index);
int uri = m_attributes[offset + ATTRIBUTE_IX_NAMESPACE_URI];
@ -273,6 +307,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(prefix);
}
@Override
public String getAttributeName(int index) {
int offset = getAttributeOffset(index);
int name = m_attributes[offset + ATTRIBUTE_IX_NAME];
@ -282,26 +317,29 @@ public class AXmlResourceParser implements XmlResourceParser {
return m_strings.getString(name);
}
@Override
public int getAttributeNameResource(int index) {
int offset = getAttributeOffset(index);
int name = m_attributes[offset + ATTRIBUTE_IX_NAME];
if (m_resourceIDs == null
|| name < 0 || name >= m_resourceIDs.length) {
if (m_resourceIDs == null || name < 0 || name >= m_resourceIDs.length) {
return 0;
}
return m_resourceIDs[name];
}
@Override
public int getAttributeValueType(int index) {
int offset = getAttributeOffset(index);
return m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
}
@Override
public int getAttributeValueData(int index) {
int offset = getAttributeOffset(index);
return m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA];
}
@Override
public String getAttributeValue(int index) {
int offset = getAttributeOffset(index);
int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
@ -310,9 +348,11 @@ public class AXmlResourceParser implements XmlResourceParser {
if (mAttrDecoder != null) {
try {
return mAttrDecoder.decode(valueType, valueData,
valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(
m_strings.getString(valueRaw)),
return mAttrDecoder.decode(
valueType,
valueData,
valueRaw == -1 ? null : ResXmlEncoders
.escapeXmlChars(m_strings.getString(valueRaw)),
getAttributeNameResource(index));
} catch (AndrolibException ex) {
setFirstError(ex);
@ -324,17 +364,20 @@ public class AXmlResourceParser implements XmlResourceParser {
}
} else {
if (valueType == TypedValue.TYPE_STRING) {
return ResXmlEncoders.escapeXmlChars(m_strings.getString(valueRaw));
return ResXmlEncoders.escapeXmlChars(m_strings
.getString(valueRaw));
}
}
return TypedValue.coerceToString(valueType, valueData);
}
@Override
public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
return getAttributeIntValue(index, defaultValue ? 1 : 0) != 0;
}
@Override
public float getAttributeFloatValue(int index, float defaultValue) {
int offset = getAttributeOffset(index);
int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
@ -345,6 +388,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return defaultValue;
}
@Override
public int getAttributeIntValue(int index, int defaultValue) {
int offset = getAttributeOffset(index);
int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
@ -355,10 +399,12 @@ public class AXmlResourceParser implements XmlResourceParser {
return defaultValue;
}
@Override
public int getAttributeUnsignedIntValue(int index, int defaultValue) {
return getAttributeIntValue(index, defaultValue);
}
@Override
public int getAttributeResourceValue(int index, int defaultValue) {
int offset = getAttributeOffset(index);
int valueType = m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE];
@ -368,6 +414,7 @@ public class AXmlResourceParser implements XmlResourceParser {
return defaultValue;
}
@Override
public String getAttributeValue(String namespace, String attribute) {
int index = findAttribute(namespace, attribute);
if (index == -1) {
@ -376,7 +423,9 @@ public class AXmlResourceParser implements XmlResourceParser {
return getAttributeValue(index);
}
public boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue) {
@Override
public boolean getAttributeBooleanValue(String namespace, String attribute,
boolean defaultValue) {
int index = findAttribute(namespace, attribute);
if (index == -1) {
return defaultValue;
@ -384,7 +433,9 @@ public class AXmlResourceParser implements XmlResourceParser {
return getAttributeBooleanValue(index, defaultValue);
}
public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
@Override
public float getAttributeFloatValue(String namespace, String attribute,
float defaultValue) {
int index = findAttribute(namespace, attribute);
if (index == -1) {
return defaultValue;
@ -392,7 +443,9 @@ public class AXmlResourceParser implements XmlResourceParser {
return getAttributeFloatValue(index, defaultValue);
}
public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
@Override
public int getAttributeIntValue(String namespace, String attribute,
int defaultValue) {
int index = findAttribute(namespace, attribute);
if (index == -1) {
return defaultValue;
@ -400,7 +453,9 @@ public class AXmlResourceParser implements XmlResourceParser {
return getAttributeIntValue(index, defaultValue);
}
public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) {
@Override
public int getAttributeUnsignedIntValue(String namespace, String attribute,
int defaultValue) {
int index = findAttribute(namespace, attribute);
if (index == -1) {
return defaultValue;
@ -408,7 +463,9 @@ public class AXmlResourceParser implements XmlResourceParser {
return getAttributeUnsignedIntValue(index, defaultValue);
}
public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
@Override
public int getAttributeResourceValue(String namespace, String attribute,
int defaultValue) {
int index = findAttribute(namespace, attribute);
if (index == -1) {
return defaultValue;
@ -416,74 +473,96 @@ public class AXmlResourceParser implements XmlResourceParser {
return getAttributeResourceValue(index, defaultValue);
}
public int getAttributeListValue(int index, String[] options, int defaultValue) {
@Override
public int getAttributeListValue(int index, String[] options,
int defaultValue) {
// TODO implement
return 0;
}
public int getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue) {
@Override
public int getAttributeListValue(String namespace, String attribute,
String[] options, int defaultValue) {
// TODO implement
return 0;
}
@Override
public String getAttributeType(int index) {
return "CDATA";
}
@Override
public boolean isAttributeDefault(int index) {
return false;
}
/////////////////////////////////// dummies
public void setInput(InputStream stream, String inputEncoding) throws XmlPullParserException {
// ///////////////////////////////// dummies
@Override
public void setInput(InputStream stream, String inputEncoding)
throws XmlPullParserException {
open(stream);
}
@Override
public void setInput(Reader reader) throws XmlPullParserException {
throw new XmlPullParserException(E_NOT_SUPPORTED);
}
@Override
public String getInputEncoding() {
return null;
}
@Override
public int getColumnNumber() {
return -1;
}
@Override
public boolean isEmptyElementTag() throws XmlPullParserException {
return false;
}
@Override
public boolean isWhitespace() throws XmlPullParserException {
return false;
}
public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException {
@Override
public void defineEntityReplacementText(String entityName,
String replacementText) throws XmlPullParserException {
throw new XmlPullParserException(E_NOT_SUPPORTED);
}
@Override
public String getNamespace(String prefix) {
throw new RuntimeException(E_NOT_SUPPORTED);
}
@Override
public Object getProperty(String name) {
return null;
}
public void setProperty(String name, Object value) throws XmlPullParserException {
@Override
public void setProperty(String name, Object value)
throws XmlPullParserException {
throw new XmlPullParserException(E_NOT_SUPPORTED);
}
@Override
public boolean getFeature(String feature) {
return false;
}
public void setFeature(String name, boolean value) throws XmlPullParserException {
@Override
public void setFeature(String name, boolean value)
throws XmlPullParserException {
throw new XmlPullParserException(E_NOT_SUPPORTED);
}
///////////////////////////////////////////// implementation
// /////////////////////////////////////////// implementation
/**
* Namespace stack, holds prefix+uri pairs, as well as depth information.
* All information is stored in one int[] array. Array consists of depth
@ -574,10 +653,7 @@ public class AXmlResourceParser implements XmlResourceParser {
m_data[offset] = count;
offset -= (1 + 2 + count * 2);
m_data[offset] = count;
System.arraycopy(
m_data, o + 2,
m_data, o,
m_dataLength - o);
System.arraycopy(m_data, o + 2, m_data, o, m_dataLength - o);
}
m_dataLength -= 2;
m_count -= 1;
@ -703,58 +779,61 @@ public class AXmlResourceParser implements XmlResourceParser {
}
return -1;
}
private int[] m_data;
private int m_dataLength;
private int m_count;
private int m_depth;
}
/////////////////////////////////// package-visible
// final void fetchAttributes(int[] styleableIDs,TypedArray result) {
// result.resetIndices();
// if (m_attributes==null || m_resourceIDs==null) {
// return;
// }
// boolean needStrings=false;
// for (int i=0,e=styleableIDs.length;i!=e;++i) {
// int id=styleableIDs[i];
// for (int o=0;o!=m_attributes.length;o+=ATTRIBUTE_LENGHT) {
// int name=m_attributes[o+ATTRIBUTE_IX_NAME];
// if (name>=m_resourceIDs.length ||
// m_resourceIDs[name]!=id)
// {
// continue;
// }
// int valueType=m_attributes[o+ATTRIBUTE_IX_VALUE_TYPE];
// int valueData;
// int assetCookie;
// if (valueType==TypedValue.TYPE_STRING) {
// valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_STRING];
// assetCookie=-1;
// needStrings=true;
// } else {
// valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_DATA];
// assetCookie=0;
// }
// result.addValue(i,valueType,valueData,assetCookie,id,0);
// }
// }
// if (needStrings) {
// result.setStrings(m_strings);
// }
// }
// ///////////////////////////////// package-visible
// final void fetchAttributes(int[] styleableIDs,TypedArray result) {
// result.resetIndices();
// if (m_attributes==null || m_resourceIDs==null) {
// return;
// }
// boolean needStrings=false;
// for (int i=0,e=styleableIDs.length;i!=e;++i) {
// int id=styleableIDs[i];
// for (int o=0;o!=m_attributes.length;o+=ATTRIBUTE_LENGHT) {
// int name=m_attributes[o+ATTRIBUTE_IX_NAME];
// if (name>=m_resourceIDs.length ||
// m_resourceIDs[name]!=id)
// {
// continue;
// }
// int valueType=m_attributes[o+ATTRIBUTE_IX_VALUE_TYPE];
// int valueData;
// int assetCookie;
// if (valueType==TypedValue.TYPE_STRING) {
// valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_STRING];
// assetCookie=-1;
// needStrings=true;
// } else {
// valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_DATA];
// assetCookie=0;
// }
// result.addValue(i,valueType,valueData,assetCookie,id,0);
// }
// }
// if (needStrings) {
// result.setStrings(m_strings);
// }
// }
final StringBlock getStrings() {
return m_strings;
}
///////////////////////////////////
// /////////////////////////////////
private final int getAttributeOffset(int index) {
if (m_event != START_TAG) {
throw new IndexOutOfBoundsException("Current event is not START_TAG.");
throw new IndexOutOfBoundsException(
"Current event is not START_TAG.");
}
int offset = index * ATTRIBUTE_LENGHT;
if (offset >= m_attributes.length) {
throw new IndexOutOfBoundsException("Invalid attribute index (" + index + ").");
throw new IndexOutOfBoundsException("Invalid attribute index ("
+ index + ").");
}
return offset;
}
@ -767,12 +846,11 @@ public class AXmlResourceParser implements XmlResourceParser {
if (name == -1) {
return -1;
}
int uri = (namespace != null)
? m_strings.find(namespace)
: -1;
for (int o = 0; o != m_attributes.length; o+=ATTRIBUTE_LENGHT) {
int uri = (namespace != null) ? m_strings.find(namespace) : -1;
for (int o = 0; o != m_attributes.length; o += ATTRIBUTE_LENGHT) {
if (name == m_attributes[o + ATTRIBUTE_IX_NAME]
&& (uri == -1 || uri == m_attributes[o + ATTRIBUTE_IX_NAMESPACE_URI])) {
&& (uri == -1 || uri == m_attributes[o
+ ATTRIBUTE_IX_NAMESPACE_URI])) {
return o / ATTRIBUTE_LENGHT;
}
}
@ -796,7 +874,7 @@ public class AXmlResourceParser implements XmlResourceParser {
m_reader.skipCheckInt(CHUNK_AXML_FILE);
/*
* chunkSize
*/ m_reader.skipInt();
*/m_reader.skipInt();
m_strings = StringBlock.read(m_reader);
m_namespaces.increaseDepth();
m_operational = true;
@ -816,8 +894,7 @@ public class AXmlResourceParser implements XmlResourceParser {
}
// Fake END_DOCUMENT event.
if (event == END_TAG
&& m_namespaces.getDepth() == 1
if (event == END_TAG && m_namespaces.getDepth() == 1
&& m_namespaces.getCurrentCount() == 0) {
m_event = END_DOCUMENT;
break;
@ -834,7 +911,8 @@ public class AXmlResourceParser implements XmlResourceParser {
if (chunkType == CHUNK_RESOURCEIDS) {
int chunkSize = m_reader.readInt();
if (chunkSize < 8 || (chunkSize % 4) != 0) {
throw new IOException("Invalid resource ids size (" + chunkSize + ").");
throw new IOException("Invalid resource ids size ("
+ chunkSize + ").");
}
m_resourceIDs = m_reader.readIntArray(chunkSize / 4 - 2);
continue;
@ -851,9 +929,9 @@ public class AXmlResourceParser implements XmlResourceParser {
}
// Common header.
/*chunkSize*/ m_reader.skipInt();
/* chunkSize */m_reader.skipInt();
int lineNumber = m_reader.readInt();
/*0xFFFFFFFF*/ m_reader.skipInt();
/* 0xFFFFFFFF */m_reader.skipInt();
if (chunkType == CHUNK_XML_START_NAMESPACE
|| chunkType == CHUNK_XML_END_NAMESPACE) {
@ -862,8 +940,8 @@ public class AXmlResourceParser implements XmlResourceParser {
int uri = m_reader.readInt();
m_namespaces.push(prefix, uri);
} else {
/*prefix*/ m_reader.skipInt();
/*uri*/ m_reader.skipInt();
/* prefix */m_reader.skipInt();
/* uri */m_reader.skipInt();
m_namespaces.pop();
}
continue;
@ -874,14 +952,15 @@ public class AXmlResourceParser implements XmlResourceParser {
if (chunkType == CHUNK_XML_START_TAG) {
m_namespaceUri = m_reader.readInt();
m_name = m_reader.readInt();
/*flags?*/ m_reader.skipInt();
/* flags? */m_reader.skipInt();
int attributeCount = m_reader.readInt();
m_idAttribute = (attributeCount >>> 16) - 1;
attributeCount &= 0xFFFF;
m_classAttribute = m_reader.readInt();
m_styleAttribute = (m_classAttribute >>> 16) - 1;
m_classAttribute = (m_classAttribute & 0xFFFF) - 1;
m_attributes = m_reader.readIntArray(attributeCount * ATTRIBUTE_LENGHT);
m_attributes = m_reader.readIntArray(attributeCount
* ATTRIBUTE_LENGHT);
for (int i = ATTRIBUTE_IX_VALUE_TYPE; i < m_attributes.length;) {
m_attributes[i] = (m_attributes[i] >>> 24);
i += ATTRIBUTE_LENGHT;
@ -901,8 +980,8 @@ public class AXmlResourceParser implements XmlResourceParser {
if (chunkType == CHUNK_XML_TEXT) {
m_name = m_reader.readInt();
/*?*/ m_reader.skipInt();
/*?*/ m_reader.skipInt();
/* ? */m_reader.skipInt();
/* ? */m_reader.skipInt();
m_event = TEXT;
break;
}
@ -932,44 +1011,49 @@ public class AXmlResourceParser implements XmlResourceParser {
}
private boolean compareAttr(int[] attr1, int[] attr2) {
//TODO: sort Attrs
// TODO: sort Attrs
/*
* ATTRIBUTE_IX_VALUE_TYPE == TYPE_STRING : ATTRIBUTE_IX_VALUE_STRING :
* ATTRIBUTE_IX_NAMESPACE_URI ATTRIBUTE_IX_NAMESPACE_URI :
* ATTRIBUTE_IX_NAME id
*
*/
if (attr1[ATTRIBUTE_IX_VALUE_TYPE] == TypedValue.TYPE_STRING
&& attr1[ATTRIBUTE_IX_VALUE_TYPE] == attr2[ATTRIBUTE_IX_VALUE_TYPE]
&& //(m_strings.touch(attr1[ATTRIBUTE_IX_VALUE_STRING], m_name) ||
// m_strings.touch(attr2[ATTRIBUTE_IX_VALUE_STRING], m_name)) &&
//m_strings.touch(attr1[ATTRIBUTE_IX_VALUE_STRING], m_name) &&
&& // (m_strings.touch(attr1[ATTRIBUTE_IX_VALUE_STRING], m_name)
// ||
// m_strings.touch(attr2[ATTRIBUTE_IX_VALUE_STRING],
// m_name)) &&
// m_strings.touch(attr1[ATTRIBUTE_IX_VALUE_STRING], m_name)
// &&
attr1[ATTRIBUTE_IX_VALUE_STRING] != attr2[ATTRIBUTE_IX_VALUE_STRING]) {
return (attr1[ATTRIBUTE_IX_VALUE_STRING] < attr2[ATTRIBUTE_IX_VALUE_STRING]);
} else if ((attr1[ATTRIBUTE_IX_NAMESPACE_URI] == attr2[ATTRIBUTE_IX_NAMESPACE_URI]) && (attr1[ATTRIBUTE_IX_NAMESPACE_URI] != -1)
&& //(m_strings.touch(attr1[ATTRIBUTE_IX_NAME], m_name) ||
// m_strings.touch(attr2[ATTRIBUTE_IX_NAME], m_name)) &&
//m_strings.touch(attr1[ATTRIBUTE_IX_NAME], m_name) &&
} else if ((attr1[ATTRIBUTE_IX_NAMESPACE_URI] == attr2[ATTRIBUTE_IX_NAMESPACE_URI])
&& (attr1[ATTRIBUTE_IX_NAMESPACE_URI] != -1) && // (m_strings.touch(attr1[ATTRIBUTE_IX_NAME],
// m_name) ||
// m_strings.touch(attr2[ATTRIBUTE_IX_NAME],
// m_name)) &&
// m_strings.touch(attr1[ATTRIBUTE_IX_NAME],
// m_name) &&
(attr1[ATTRIBUTE_IX_NAME] != attr2[ATTRIBUTE_IX_NAME])) {
return (attr1[ATTRIBUTE_IX_NAME] < attr2[ATTRIBUTE_IX_NAME]);
//} else if (attr1[ATTRIBUTE_IX_NAMESPACE_URI] < attr2[ATTRIBUTE_IX_NAMESPACE_URI]) {
// } else if (attr1[ATTRIBUTE_IX_NAMESPACE_URI] <
// attr2[ATTRIBUTE_IX_NAMESPACE_URI]) {
// return true;
} else {
return false;
}
}
private void setFirstError(AndrolibException error) {
if (mFirstError == null) {
mFirstError = error;
}
}
/////////////////////////////////// data
// ///////////////////////////////// data
/*
* All values are essentially indices, e.g. m_name is
* an index of name in m_strings.
* All values are essentially indices, e.g. m_name is an index of name in
* m_strings.
*/
private ExtDataInput m_reader;
private ResAttrDecoder mAttrDecoder;
@ -989,25 +1073,18 @@ public class AXmlResourceParser implements XmlResourceParser {
private int m_classAttribute;
private int m_styleAttribute;
private final static Logger LOGGER =
Logger.getLogger(AXmlResourceParser.class.getName());
private final static Logger LOGGER = Logger
.getLogger(AXmlResourceParser.class.getName());
private static final String E_NOT_SUPPORTED = "Method is not supported.";
private static final int
ATTRIBUTE_IX_NAMESPACE_URI = 0,
ATTRIBUTE_IX_NAME = 1,
ATTRIBUTE_IX_VALUE_STRING = 2,
ATTRIBUTE_IX_VALUE_TYPE = 3,
ATTRIBUTE_IX_VALUE_DATA = 4,
private static final int ATTRIBUTE_IX_NAMESPACE_URI = 0,
ATTRIBUTE_IX_NAME = 1, ATTRIBUTE_IX_VALUE_STRING = 2,
ATTRIBUTE_IX_VALUE_TYPE = 3, ATTRIBUTE_IX_VALUE_DATA = 4,
ATTRIBUTE_LENGHT = 5;
private static final int
CHUNK_AXML_FILE = 0x00080003,
CHUNK_RESOURCEIDS = 0x00080180,
CHUNK_XML_FIRST = 0x00100100,
private static final int CHUNK_AXML_FILE = 0x00080003,
CHUNK_RESOURCEIDS = 0x00080180, CHUNK_XML_FIRST = 0x00100100,
CHUNK_XML_START_NAMESPACE = 0x00100100,
CHUNK_XML_END_NAMESPACE = 0x00100101,
CHUNK_XML_START_TAG = 0x00100102,
CHUNK_XML_END_TAG = 0x00100103,
CHUNK_XML_TEXT = 0x00100104,
CHUNK_XML_LAST = 0x00100104;
CHUNK_XML_START_TAG = 0x00100102, CHUNK_XML_END_TAG = 0x00100103,
CHUNK_XML_TEXT = 0x00100104, CHUNK_XML_LAST = 0x00100104;
}

View File

@ -28,6 +28,7 @@ import org.apache.commons.io.IOUtils;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class Res9patchStreamDecoder implements ResStreamDecoder {
@Override
public void decode(InputStream in, OutputStream out)
throws AndrolibException {
try {
@ -36,8 +37,8 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
BufferedImage im = ImageIO.read(new ByteArrayInputStream(data));
int w = im.getWidth(), h = im.getHeight();
BufferedImage im2 = new BufferedImage(
w + 2, h + 2, BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage im2 = new BufferedImage(w + 2, h + 2,
BufferedImage.TYPE_4BYTE_ABGR);
if (im.getType() == BufferedImage.TYPE_4BYTE_ABGR) {
im2.getRaster().setRect(1, 1, im.getRaster());
} else {
@ -64,15 +65,15 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
}
}
private NinePatch getNinePatch(byte[] data)
throws AndrolibException, IOException {
private NinePatch getNinePatch(byte[] data) throws AndrolibException,
IOException {
ExtDataInput di = new ExtDataInput(new ByteArrayInputStream(data));
find9patchChunk(di);
return NinePatch.decode(di);
}
private void find9patchChunk(DataInput di)
throws AndrolibException, IOException {
private void find9patchChunk(DataInput di) throws AndrolibException,
IOException {
di.skipBytes(8);
while (true) {
int size;
@ -103,7 +104,6 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
private static final int NP_CHUNK_TYPE = 0x6e705463; // npTc
private static final int NP_COLOR = 0xff000000;
private static class NinePatch {
public final int padLeft, padRight, padTop, padBottom;
public final int[] xDivs, yDivs;
@ -132,8 +132,8 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
int[] xDivs = di.readIntArray(numXDivs);
int[] yDivs = di.readIntArray(numYDivs);
return new NinePatch(padLeft, padRight, padTop, padBottom,
xDivs, yDivs);
return new NinePatch(padLeft, padRight, padTop, padBottom, xDivs,
yDivs);
}
}
}

View File

@ -27,8 +27,8 @@ import brut.androlib.res.data.value.ResScalarValue;
public class ResAttrDecoder {
public String decode(int type, int value, String rawValue, int attrResId)
throws AndrolibException {
ResScalarValue resValue = mCurrentPackage.getValueFactory()
.factory(type, value, rawValue);
ResScalarValue resValue = mCurrentPackage.getValueFactory().factory(
type, value, rawValue);
String decoded = null;
if (attrResId != 0) {

View File

@ -70,19 +70,19 @@ public class ResFileDecoder {
}
try {
decode(
inDir, inFileName, outDir, outFileName, "9patch");
decode(inDir, inFileName, outDir, outFileName, "9patch");
return;
} catch (CantFind9PatchChunk ex) {
LOGGER.log(Level.WARNING, String.format(
LOGGER.log(
Level.WARNING,
String.format(
"Cant find 9patch chunk in file: \"%s\". Renaming it to *.png.",
inFileName
), ex);
inFileName), ex);
outDir.removeFile(outFileName);
outFileName = outResName + ext;
}
}
if (! ".xml".equals(ext)) {
if (!".xml".equals(ext)) {
decode(inDir, inFileName, outDir, outFileName, "raw");
return;
}
@ -108,7 +108,7 @@ public class ResFileDecoder {
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
} finally {
try{
try {
if (in != null) {
in.close();
}
@ -121,18 +121,19 @@ public class ResFileDecoder {
}
}
public void decodeManifest(Directory inDir, String inFileName, Directory outDir,
String outFileName) throws AndrolibException {
public void decodeManifest(Directory inDir, String inFileName,
Directory outDir, String outFileName) throws AndrolibException {
InputStream in = null;
OutputStream out = null;
try {
in = inDir.getFileInput(inFileName);
out = outDir.getFileOutput(outFileName);
((XmlPullStreamDecoder)mDecoders.getDecoder("xml")).decodeManifest(in, out);
((XmlPullStreamDecoder) mDecoders.getDecoder("xml"))
.decodeManifest(in, out);
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
} finally {
try{
try {
if (in != null) {
in.close();
}
@ -145,6 +146,6 @@ public class ResFileDecoder {
}
}
private final static Logger LOGGER =
Logger.getLogger(ResFileDecoder.class.getName());
private final static Logger LOGGER = Logger.getLogger(ResFileDecoder.class
.getName());
}

View File

@ -26,6 +26,7 @@ import org.apache.commons.io.IOUtils;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResRawStreamDecoder implements ResStreamDecoder {
@Override
public void decode(InputStream in, OutputStream out)
throws AndrolibException {
try {

View File

@ -26,8 +26,7 @@ import java.util.Map;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResStreamDecoderContainer {
private final Map<String, ResStreamDecoder> mDecoders =
new HashMap<String, ResStreamDecoder>();
private final Map<String, ResStreamDecoder> mDecoders = new HashMap<String, ResStreamDecoder>();
public void decode(InputStream in, OutputStream out, String decoderName)
throws AndrolibException {

View File

@ -30,15 +30,14 @@ import java.util.logging.Logger;
*
* Block of strings, used in binary xml and arsc.
*
* TODO:
* - implement get()
* TODO: - implement get()
*
*/
public class StringBlock {
/**
* Reads whole (including chunk type) string block from stream.
* Stream must be at the chunk type.
* Reads whole (including chunk type) string block from stream. Stream must
* be at the chunk type.
*/
public static StringBlock read(ExtDataInput reader) throws IOException {
reader.skipCheckInt(CHUNK_TYPE);
@ -53,16 +52,18 @@ public class StringBlock {
block.m_isUTF8 = (flags & UTF8_FLAG) != 0;
block.m_stringOffsets = reader.readIntArray(stringCount);
block.m_stringOwns = new int[stringCount];
for (int i=0;i<stringCount;i++) {
for (int i = 0; i < stringCount; i++) {
block.m_stringOwns[i] = -1;
}
if (styleOffsetCount != 0) {
block.m_styleOffsets = reader.readIntArray(styleOffsetCount);
}
{
int size = ((stylesOffset == 0) ? chunkSize : stylesOffset) - stringsOffset;
int size = ((stylesOffset == 0) ? chunkSize : stylesOffset)
- stringsOffset;
if ((size % 4) != 0) {
throw new IOException("String data size is not multiple of 4 (" + size + ").");
throw new IOException("String data size is not multiple of 4 ("
+ size + ").");
}
block.m_strings = new byte[size];
reader.readFully(block.m_strings);
@ -70,7 +71,8 @@ public class StringBlock {
if (stylesOffset != 0) {
int size = (chunkSize - stylesOffset);
if ((size % 4) != 0) {
throw new IOException("Style data size is not multiple of 4 (" + size + ").");
throw new IOException("Style data size is not multiple of 4 ("
+ size + ").");
}
block.m_styles = reader.readIntArray(size / 4);
}
@ -82,24 +84,21 @@ public class StringBlock {
* Returns number of strings in block.
*/
public int getCount() {
return m_stringOffsets != null
? m_stringOffsets.length
: 0;
return m_stringOffsets != null ? m_stringOffsets.length : 0;
}
/**
* Returns raw string (without any styling information) at specified index.
*/
public String getString(int index) {
if (index < 0
|| m_stringOffsets == null
if (index < 0 || m_stringOffsets == null
|| index >= m_stringOffsets.length) {
return null;
}
int offset = m_stringOffsets[index];
int length;
if (! m_isUTF8) {
if (!m_isUTF8) {
length = getShort(m_strings, offset) * 2;
offset += 2;
} else {
@ -153,16 +152,16 @@ public class StringBlock {
break;
}
if (offset <= end) {
html.append(ResXmlEncoders.escapeXmlChars(
raw.substring(offset, end + 1)));
html.append(ResXmlEncoders.escapeXmlChars(raw.substring(
offset, end + 1)));
offset = end + 1;
}
outputStyleTag(getString(style[last]), html, true);
}
depth = j + 1;
if (offset < start) {
html.append(ResXmlEncoders.escapeXmlChars(
raw.substring(offset, start)));
html.append(ResXmlEncoders.escapeXmlChars(raw.substring(offset,
start)));
offset = start;
}
if (i == -1) {
@ -175,8 +174,7 @@ public class StringBlock {
return html.toString();
}
private void outputStyleTag(String tag, StringBuilder builder,
boolean close) {
private void outputStyleTag(String tag, StringBuilder builder, boolean close) {
builder.append('<');
if (close) {
builder.append('/');
@ -187,7 +185,7 @@ public class StringBlock {
builder.append(tag);
} else {
builder.append(tag.substring(0, pos));
if (! close) {
if (!close) {
boolean loop = true;
while (loop) {
int pos2 = tag.indexOf('=', pos + 1);
@ -203,8 +201,8 @@ public class StringBlock {
val = tag.substring(pos2 + 1);
}
builder.append(ResXmlEncoders.escapeXmlChars(val))
.append('"');
builder.append(ResXmlEncoders.escapeXmlChars(val)).append(
'"');
}
}
}
@ -212,8 +210,7 @@ public class StringBlock {
}
/**
* Finds index of the string.
* Returns -1 if the string was not found.
* Finds index of the string. Returns -1 if the string was not found.
*/
public int find(String string) {
if (string == null) {
@ -239,16 +236,14 @@ public class StringBlock {
return -1;
}
///////////////////////////////////////////// implementation
// /////////////////////////////////////////// implementation
private StringBlock() {
}
/**
* Returns style information - array of int triplets,
* where in each triplet:
* * first int is index of tag name ('b','i', etc.)
* * second int is tag start index in string
* * third int is tag end index in string
* Returns style information - array of int triplets, where in each triplet:
* * first int is index of tag name ('b','i', etc.) * second int is tag
* start index in string * third int is tag end index in string
*/
private int[] getStyle(int index) {
if (m_styleOffsets == null || m_styles == null
@ -307,20 +302,18 @@ public class StringBlock {
boolean more = (val & 0x80) != 0;
val &= 0x7f;
if (! more) {
return new int[]{val, 1};
if (!more) {
return new int[] { val, 1 };
} else {
return new int[]{val << 8 | array[offset + 1] & 0xff, 2};
return new int[] { val << 8 | array[offset + 1] & 0xff, 2 };
}
}
public boolean touch(int index, int own) {
if (index < 0
|| m_stringOwns == null
|| index >= m_stringOwns.length) {
if (index < 0 || m_stringOwns == null || index >= m_stringOwns.length) {
return false;
}
if(m_stringOwns[index] == -1) {
if (m_stringOwns[index] == -1) {
m_stringOwns[index] = own;
return true;
} else if (m_stringOwns[index] == own) {
@ -336,12 +329,12 @@ public class StringBlock {
private int[] m_styles;
private boolean m_isUTF8;
private int[] m_stringOwns;
private static final CharsetDecoder UTF16LE_DECODER =
Charset.forName("UTF-16LE").newDecoder();
private static final CharsetDecoder UTF8_DECODER =
Charset.forName("UTF-8").newDecoder();
private static final Logger LOGGER =
Logger.getLogger(StringBlock.class.getName());
private static final CharsetDecoder UTF16LE_DECODER = Charset.forName(
"UTF-16LE").newDecoder();
private static final CharsetDecoder UTF8_DECODER = Charset.forName("UTF-8")
.newDecoder();
private static final Logger LOGGER = Logger.getLogger(StringBlock.class
.getName());
private static final int CHUNK_TYPE = 0x001C0001;
private static final int UTF8_FLAG = 0x00000100;
}

View File

@ -42,80 +42,91 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
this.mSerial = serializer;
}
@Override
public void decode(InputStream in, OutputStream out)
throws AndrolibException {
try {
XmlPullWrapperFactory factory = XmlPullWrapperFactory.newInstance();
XmlPullParserWrapper par = factory.newPullParserWrapper(mParser);
final ResTable resTable = ((AXmlResourceParser)mParser).getAttrDecoder().getCurrentPackage().getResTable();
final ResTable resTable = ((AXmlResourceParser) mParser)
.getAttrDecoder().getCurrentPackage().getResTable();
XmlSerializerWrapper ser = new StaticXmlSerializerWrapper(mSerial, factory){
XmlSerializerWrapper ser = new StaticXmlSerializerWrapper(mSerial,
factory) {
boolean hideSdkInfo = false;
boolean hidePackageInfo = false;
@Override
public void event(XmlPullParser pp) throws XmlPullParserException, IOException {
public void event(XmlPullParser pp)
throws XmlPullParserException, IOException {
int type = pp.getEventType();
if (type == XmlPullParser.START_TAG) {
if ("manifest".equalsIgnoreCase(pp.getName())) {
try {
hidePackageInfo = parseManifest(pp);
} catch (AndrolibException e) {}
}else if ("uses-sdk".equalsIgnoreCase(pp.getName())) {
} catch (AndrolibException e) {
}
} else if ("uses-sdk".equalsIgnoreCase(pp.getName())) {
try {
hideSdkInfo = parseAttr(pp);
if(hideSdkInfo) {
if (hideSdkInfo) {
return;
}
} catch (AndrolibException e) {}
} catch (AndrolibException e) {
}
} else if (hideSdkInfo && type == XmlPullParser.END_TAG &&
"uses-sdk".equalsIgnoreCase(pp.getName())) {
}
} else if (hideSdkInfo && type == XmlPullParser.END_TAG
&& "uses-sdk".equalsIgnoreCase(pp.getName())) {
return;
} else if (hidePackageInfo && type == XmlPullParser.END_TAG &&
"manifest".equalsIgnoreCase(pp.getName())) {
} else if (hidePackageInfo && type == XmlPullParser.END_TAG
&& "manifest".equalsIgnoreCase(pp.getName())) {
super.event(pp);
return;
}
super.event(pp);
}
private boolean parseManifest(XmlPullParser pp) throws AndrolibException {
private boolean parseManifest(XmlPullParser pp)
throws AndrolibException {
ResTable restable = resTable;
// read <manifest> for package:
for (int i = 0; i < pp.getAttributeCount(); i++) {
if (pp.getAttributeName(i).equalsIgnoreCase(("package"))) {
restable.addPackageInfo("orig_package", pp.getAttributeValue(i));
if (pp.getAttributeName(i)
.equalsIgnoreCase(("package"))) {
restable.addPackageInfo("orig_package",
pp.getAttributeValue(i));
}
}
return true;
}
private boolean parseAttr(XmlPullParser pp) throws AndrolibException {
private boolean parseAttr(XmlPullParser pp)
throws AndrolibException {
ResTable restable = resTable;
for (int i = 0; i < pp.getAttributeCount(); i++) {
final String a_ns = "http://schemas.android.com/apk/res/android";
String ns = pp.getAttributeNamespace (i);
String ns = pp.getAttributeNamespace(i);
if (a_ns.equalsIgnoreCase(ns)) {
String name = pp.getAttributeName (i);
String value = pp.getAttributeValue (i);
String name = pp.getAttributeName(i);
String value = pp.getAttributeValue(i);
if (name != null && value != null) {
if (name.equalsIgnoreCase("minSdkVersion") ||
name.equalsIgnoreCase("targetSdkVersion") ||
name.equalsIgnoreCase("maxSdkVersion")) {
if (name.equalsIgnoreCase("minSdkVersion")
|| name.equalsIgnoreCase("targetSdkVersion")
|| name.equalsIgnoreCase("maxSdkVersion")) {
restable.addSdkInfo(name, value);
} else {
restable.clearSdkInfo();
return false;//Found unknown flags
return false;// Found unknown flags
}
}
} else {
resTable.clearSdkInfo();
if (i >= pp.getAttributeCount()) {
return false;//Found unknown flags
return false;// Found unknown flags
}
}
}
@ -152,6 +163,6 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
private boolean mOptimizeForManifest = false;
private final static Logger LOGGER =
Logger.getLogger(XmlPullStreamDecoder.class.getName());
private final static Logger LOGGER = Logger
.getLogger(XmlPullStreamDecoder.class.getName());
}

View File

@ -58,6 +58,5 @@ public class ExtFile extends File {
return mDirectory;
}
private Directory mDirectory;
}

View File

@ -24,8 +24,8 @@ import org.xmlpull.mxp1_serializer.MXSerializer;
*/
public class ExtMXSerializer extends MXSerializer implements ExtXmlSerializer {
@Override
public void startDocument(String encoding, Boolean standalone) throws
IOException, IllegalArgumentException, IllegalStateException {
public void startDocument(String encoding, Boolean standalone)
throws IOException, IllegalArgumentException, IllegalStateException {
super.startDocument(encoding != null ? encoding : mDefaultEncoding,
standalone);
this.newLine();
@ -64,11 +64,13 @@ public class ExtMXSerializer extends MXSerializer implements ExtXmlSerializer {
}
}
@Override
public ExtXmlSerializer newLine() throws IOException {
super.out.write(lineSeparator);
return this;
}
@Override
public void setDisabledAttrEscape(boolean disabled) {
mIsDisabledAttrEscape = disabled;
}

View File

@ -25,11 +25,10 @@ import org.xmlpull.v1.XmlSerializer;
public interface ExtXmlSerializer extends XmlSerializer {
public ExtXmlSerializer newLine() throws IOException;
public void setDisabledAttrEscape(boolean disabled);
public static final String PROPERTY_SERIALIZER_INDENTATION =
"http://xmlpull.org/v1/doc/properties.html#serializer-indentation";
public static final String PROPERTY_SERIALIZER_LINE_SEPARATOR =
"http://xmlpull.org/v1/doc/properties.html#serializer-line-separator";
public static final String PROPERTY_SERIALIZER_INDENTATION = "http://xmlpull.org/v1/doc/properties.html#serializer-indentation";
public static final String PROPERTY_SERIALIZER_LINE_SEPARATOR = "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator";
public static final String PROPERTY_DEFAULT_ENCODING = "DEFAULT_ENCODING";
}

View File

@ -25,6 +25,6 @@ import org.xmlpull.v1.XmlSerializer;
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public interface ResValuesXmlSerializable {
public void serializeToResValuesXml(XmlSerializer serializer, ResResource res)
throws IOException, AndrolibException;
public void serializeToResValuesXml(XmlSerializer serializer,
ResResource res) throws IOException, AndrolibException;
}

View File

@ -23,5 +23,6 @@ import brut.androlib.AndrolibException;
*/
public interface ResXmlEncodable {
public String encodeAsResXmlAttr() throws AndrolibException;
public String encodeAsResXmlValue() throws AndrolibException;
}

View File

@ -166,7 +166,7 @@ public final class ResXmlEncoders {
int count = 0;
int length = str.length();
List<Integer> ret = new ArrayList<Integer>();
while((pos2 = (pos = str.indexOf('%', pos2)) + 1) != 0) {
while ((pos2 = (pos = str.indexOf('%', pos2)) + 1) != 0) {
if (pos2 == length) {
break;
}
@ -194,9 +194,7 @@ public final class ResXmlEncoders {
private static boolean isPrintableChar(char c) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
return !Character.isISOControl(c)
&& c != KeyEvent.CHAR_UNDEFINED
&& block != null
&& block != Character.UnicodeBlock.SPECIALS;
return !Character.isISOControl(c) && c != KeyEvent.CHAR_UNDEFINED
&& block != null && block != Character.UnicodeBlock.SPECIALS;
}
}

View File

@ -21,7 +21,6 @@ import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jf.dexlib.Code.Analysis.RegisterType;
import org.jf.dexlib.Code.Opcode;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
@ -40,10 +39,8 @@ public class DebugInjector {
private void inject() throws AndrolibException {
String definition = nextAndAppend();
if (
definition.contains(" abstract ") ||
definition.contains(" native ")
) {
if (definition.contains(" abstract ")
|| definition.contains(" native ")) {
nextAndAppend();
return;
}
@ -68,7 +65,7 @@ public class DebugInjector {
int i = definition.contains(" static ") ? 0 : 1;
int argc = TypeName.listFromInternalName(params).size() + i;
while(i < argc) {
while (i < argc) {
mOut.append(".parameter \"p").append(i).append("\"\n");
i++;
}
@ -121,8 +118,7 @@ public class DebugInjector {
case Uninit:
case Conflicted:
if (mInitializedRegisters.remove(localName)) {
mOut.append(".end local ").append(localName)
.append('\n');
mOut.append(".end local ").append(localName).append('\n');
}
continue;
case Short:
@ -153,7 +149,8 @@ public class DebugInjector {
mInitializedRegisters.add(localName);
mOut.append(".local ").append(localName).append(", ")
.append(localName).append(':').append(localType).append('\n');
.append(localName).append(':').append(localType)
.append('\n');
}
return false;
@ -161,13 +158,9 @@ public class DebugInjector {
private boolean processDirective(String line) {
String line2 = line.substring(1);
if (
line2.startsWith("line ") ||
line2.equals("prologue") ||
line2.startsWith("parameter") ||
line2.startsWith("local ") ||
line2.startsWith("end local ")
) {
if (line2.startsWith("line ") || line2.equals("prologue")
|| line2.startsWith("parameter") || line2.startsWith("local ")
|| line2.startsWith("end local ")) {
return false;
}
@ -175,13 +168,10 @@ public class DebugInjector {
if (line2.equals("end method")) {
return true;
}
if (
line2.startsWith("annotation ") ||
line2.equals("sparse-switch") ||
line2.startsWith("packed-switch ") ||
line2.startsWith("array-data ")
) {
while(true) {
if (line2.startsWith("annotation ") || line2.equals("sparse-switch")
|| line2.startsWith("packed-switch ")
|| line2.startsWith("array-data ")) {
while (true) {
line2 = nextAndAppend();
if (line2.startsWith(".end ")) {
break;
@ -196,8 +186,8 @@ public class DebugInjector {
mOut.append(".prologue\n");
mFirstInstruction = false;
}
mOut.append(".line ").append(mIt.nextIndex()).append('\n')
.append(line).append('\n');
mOut.append(".line ").append(mIt.nextIndex()).append('\n').append(line)
.append('\n');
return false;
}
@ -222,6 +212,6 @@ public class DebugInjector {
private boolean mFirstInstruction = true;
private final Set<String> mInitializedRegisters = new HashSet<String>();
private static final Pattern REGISTER_INFO_PATTERN =
Pattern.compile("((?:p|v)\\d+)=\\(([^)]+)\\);");
private static final Pattern REGISTER_INFO_PATTERN = Pattern
.compile("((?:p|v)\\d+)=\\(([^)]+)\\);");
}

View File

@ -40,10 +40,9 @@ public class DexFileBuilder {
public void addSmaliFile(InputStream smaliStream, String name)
throws AndrolibException {
try {
if (! SmaliMod.assembleSmaliFile(
smaliStream, name, mDexFile, false, false, false)) {
throw new AndrolibException(
"Could not smali file: " + name);
if (!SmaliMod.assembleSmaliFile(smaliStream, name, mDexFile, false,
false, false)) {
throw new AndrolibException("Could not smali file: " + name);
}
} catch (IOException ex) {
throw new AndrolibException(ex);
@ -58,14 +57,14 @@ public class DexFileBuilder {
out.write(getAsByteArray());
out.close();
} catch (IOException ex) {
throw new AndrolibException(
"Could not write dex to file: " + dexFile, ex);
throw new AndrolibException("Could not write dex to file: "
+ dexFile, ex);
}
}
public byte[] getAsByteArray() {
mDexFile.place();
for (CodeItem codeItem: mDexFile.CodeItemsSection.getItems()) {
for (CodeItem codeItem : mDexFile.CodeItemsSection.getItems()) {
codeItem.fixInstructions(true, true);
}

View File

@ -32,12 +32,12 @@ import org.apache.commons.io.IOUtils;
public class SmaliBuilder {
public static void build(ExtFile smaliDir, File dexFile,
HashMap<String, Boolean> flags)
throws AndrolibException {
HashMap<String, Boolean> flags) throws AndrolibException {
new SmaliBuilder(smaliDir, dexFile, flags).build();
}
private SmaliBuilder(ExtFile smaliDir, File dexFile, HashMap<String, Boolean> flags) {
private SmaliBuilder(ExtFile smaliDir, File dexFile,
HashMap<String, Boolean> flags) {
mSmaliDir = smaliDir;
mDexFile = dexFile;
mFlags = flags;
@ -66,7 +66,7 @@ public class SmaliBuilder {
mDexBuilder.addSmaliFile(inFile);
return;
}
if (! fileName.endsWith(".java")) {
if (!fileName.endsWith(".java")) {
LOGGER.warning("Unknown file type, ignoring: " + inFile);
return;
}
@ -87,8 +87,8 @@ public class SmaliBuilder {
out.append(".source \"").append(inFile.getName()).append("\"\n");
while (it.hasNext()) {
String line = it.next().trim();
if (line.isEmpty() || line.charAt(0) == '#' ||
line.startsWith(".source")) {
if (line.isEmpty() || line.charAt(0) == '#'
|| line.startsWith(".source")) {
continue;
}
if (line.startsWith(".method ")) {
@ -100,8 +100,8 @@ public class SmaliBuilder {
out.append(line).append('\n');
}
}
mDexBuilder.addSmaliFile(
IOUtils.toInputStream(out.toString()), fileName);
mDexBuilder.addSmaliFile(IOUtils.toInputStream(out.toString()),
fileName);
}
private final ExtFile mSmaliDir;
@ -110,7 +110,6 @@ public class SmaliBuilder {
private DexFileBuilder mDexBuilder;
private final static Logger LOGGER =
Logger.getLogger(SmaliBuilder.class.getName());
private final static Logger LOGGER = Logger.getLogger(SmaliBuilder.class
.getName());
}

View File

@ -29,12 +29,13 @@ import org.jf.dexlib.DexFile;
*/
public class SmaliDecoder {
public static void decode(File apkFile, File outDir, boolean debug, boolean bakdeb)
throws AndrolibException {
public static void decode(File apkFile, File outDir, boolean debug,
boolean bakdeb) throws AndrolibException {
new SmaliDecoder(apkFile, outDir, debug, bakdeb).decode();
}
private SmaliDecoder(File apkFile, File outDir, boolean debug, boolean bakdeb) {
private SmaliDecoder(File apkFile, File outDir, boolean debug,
boolean bakdeb) {
mApkFile = apkFile;
mOutDir = outDir;
mDebug = debug;
@ -47,9 +48,9 @@ public class SmaliDecoder {
}
try {
baksmali.disassembleDexFile(mApkFile.getAbsolutePath(),
new DexFile(mApkFile), false, mOutDir.getAbsolutePath(), null,
null, null, false, true, true, mBakDeb, false, false,
mDebug ? main.DIFFPRE: 0, false, false, null, false);
new DexFile(mApkFile), false, mOutDir.getAbsolutePath(),
null, null, null, false, true, true, mBakDeb, false, false,
mDebug ? main.DIFFPRE : 0, false, false, null, false);
} catch (IOException ex) {
throw new AndrolibException(ex);
}

View File

@ -51,10 +51,10 @@ public class TypeName {
}
public String getName(boolean excludePackage, boolean separateInner) {
String name =
(package_ == null || excludePackage ? "" : package_ + '.') +
type +
(innerType != null ? (separateInner ? '$' : '.') + innerType : "");
String name = (package_ == null || excludePackage ? "" : package_ + '.')
+ type
+ (innerType != null ? (separateInner ? '$' : '.') + innerType
: "");
for (int i = 0; i < array; i++) {
name += "[]";
}
@ -104,8 +104,7 @@ public class TypeName {
throws AndrolibException {
Duo<TypeName, Integer> duo = fetchFromInternalName(internal);
if (duo.m2 != internal.length()) {
throw new AndrolibException(
"Invalid internal name: " + internal);
throw new AndrolibException("Invalid internal name: " + internal);
}
return duo.m1;
}
@ -113,7 +112,7 @@ public class TypeName {
public static List<TypeName> listFromInternalName(String internal)
throws AndrolibException {
List<TypeName> types = new ArrayList<TypeName>();
while (! internal.isEmpty()) {
while (!internal.isEmpty()) {
Duo<TypeName, Integer> duo = fetchFromInternalName(internal);
types.add(duo.m1);
internal = internal.substring(duo.m2);
@ -129,8 +128,8 @@ public class TypeName {
boolean isArray = false;
do {
if (internal.isEmpty()) {
throw new AndrolibException(
"Invalid internal name: " + origInternal);
throw new AndrolibException("Invalid internal name: "
+ origInternal);
}
isArray = internal.charAt(0) == '[';
if (isArray) {
@ -174,8 +173,8 @@ public class TypeName {
case 'L':
int pos = internal.indexOf(';');
if (pos == -1) {
throw new AndrolibException(
"Invalid internal name: " + origInternal);
throw new AndrolibException("Invalid internal name: "
+ origInternal);
}
length += pos;
internal = internal.substring(1, pos);
@ -196,14 +195,13 @@ public class TypeName {
}
break;
default:
throw new AndrolibException(
"Invalid internal name: " + origInternal);
throw new AndrolibException("Invalid internal name: "
+ origInternal);
}
return new Duo<TypeName, Integer>(
new TypeName(package_, type, innerType, array), length);
return new Duo<TypeName, Integer>(new TypeName(package_, type,
innerType, array), length);
}
private Boolean mIsFileOwner;
}

View File

@ -25,18 +25,17 @@ import java.io.InputStream;
/**
* Little-Endian version of DataInputStream.
* <p/>
* Very similar to DataInputStream except it reads
* little-endian instead of big-endian binary data. We can't extend
* DataInputStream directly since it has only final methods, though
* DataInputStream itself is not final. This forces us implement
* LEDataInputStream with a DataInputStream object, and use wrapper methods.
* Very similar to DataInputStream except it reads little-endian instead of
* big-endian binary data. We can't extend DataInputStream directly since it has
* only final methods, though DataInputStream itself is not final. This forces
* us implement LEDataInputStream with a DataInputStream object, and use wrapper
* methods.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.8 2007-05-24
* @since 1998
*/
public final class LEDataInputStream implements DataInput
{
public final class LEDataInputStream implements DataInput {
// ------------------------------ CONSTANTS ------------------------------
/**
@ -44,8 +43,7 @@ public final class LEDataInputStream implements DataInput
*
* @noinspection UnusedDeclaration
*/
private static final String EMBEDDED_COPYRIGHT =
"copyright (c) 1999-2010 Roedy Green, Canadian Mind Products, http://mindprod.com";
private static final String EMBEDDED_COPYRIGHT = "copyright (c) 1999-2010 Roedy Green, Canadian Mind Products, http://mindprod.com";
// ------------------------------ FIELDS ------------------------------
@ -69,70 +67,78 @@ public final class LEDataInputStream implements DataInput
* @noinspection WeakerAccess
*/
protected final byte[] work;
// -------------------------- PUBLIC STATIC METHODS --------------------------
// -------------------------- PUBLIC STATIC METHODS
// --------------------------
/**
* Note. This is a STATIC method!
*
* @param in stream to read UTF chars from (endian irrelevant)
* @param in
* stream to read UTF chars from (endian irrelevant)
*
* @return string from stream
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public static String readUTF( DataInput in ) throws IOException
{
return DataInputStream.readUTF( in );
public static String readUTF(DataInput in) throws IOException {
return DataInputStream.readUTF(in);
}
// -------------------------- PUBLIC INSTANCE METHODS --------------------------
// -------------------------- PUBLIC INSTANCE METHODS
// --------------------------
/**
* constructor.
*
* @param in binary inputstream of little-endian data.
* @param in
* binary inputstream of little-endian data.
*/
public LEDataInputStream( InputStream in )
{
public LEDataInputStream(InputStream in) {
this.is = in;
this.dis = new DataInputStream( in );
this.dis = new DataInputStream(in);
work = new byte[8];
}
/**
* close.
*
* @throws IOException if close fails.
* @throws IOException
* if close fails.
*/
public final void close() throws IOException
{
public final void close() throws IOException {
dis.close();
}
/**
* Read bytes. Watch out, read may return fewer bytes than requested.
*
* @param ba where the bytes go.
* @param off offset in buffer, not offset in file.
* @param len count of bytes to read.
* @param ba
* where the bytes go.
* @param off
* offset in buffer, not offset in file.
* @param len
* count of bytes to read.
*
* @return how many bytes read.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public final int read( byte ba[], int off, int len ) throws IOException
{
public final int read(byte ba[], int off, int len) throws IOException {
// For efficiency, we avoid one layer of wrapper
return is.read( ba, off, len );
return is.read(ba, off, len);
}
/**
* read only a one-byte boolean.
*
* @return true or false.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
* @see java.io.DataInput#readBoolean()
*/
public final boolean readBoolean() throws IOException
{
@Override
public final boolean readBoolean() throws IOException {
return dis.readBoolean();
}
@ -140,11 +146,12 @@ public final class LEDataInputStream implements DataInput
* read byte.
*
* @return the byte read.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
* @see java.io.DataInput#readByte()
*/
public final byte readByte() throws IOException
{
@Override
public final byte readByte() throws IOException {
return dis.readByte();
}
@ -152,12 +159,13 @@ public final class LEDataInputStream implements DataInput
* Read on char. like DataInputStream.readChar except little endian.
*
* @return little endian 16-bit unicode char from the stream.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public final char readChar() throws IOException
{
dis.readFully( work, 0, 2 );
return ( char ) ( ( work[ 1 ] & 0xff ) << 8 | ( work[ 0 ] & 0xff ) );
@Override
public final char readChar() throws IOException {
dis.readFully(work, 0, 2);
return (char) ((work[1] & 0xff) << 8 | (work[0] & 0xff));
}
/**
@ -166,20 +174,21 @@ public final class LEDataInputStream implements DataInput
* @return little endian IEEE double from the datastream.
* @throws IOException
*/
public final double readDouble() throws IOException
{
return Double.longBitsToDouble( readLong() );
@Override
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
/**
* Read one float. Like DataInputStream.readFloat except little endian.
*
* @return little endian IEEE float from the datastream.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public final float readFloat() throws IOException
{
return Float.intBitsToFloat( readInt() );
@Override
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
/**
@ -187,50 +196,50 @@ public final class LEDataInputStream implements DataInput
*
* @see java.io.DataInput#readFully(byte[])
*/
public final void readFully( byte ba[] ) throws IOException
{
dis.readFully( ba, 0, ba.length );
@Override
public final void readFully(byte ba[]) throws IOException {
dis.readFully(ba, 0, ba.length);
}
/**
* Read bytes until the count is satisfied.
*
* @throws IOException if read fails.
* @throws IOException
* if read fails.
* @see java.io.DataInput#readFully(byte[],int,int)
*/
public final void readFully( byte ba[],
int off,
int len ) throws IOException
{
dis.readFully( ba, off, len );
@Override
public final void readFully(byte ba[], int off, int len) throws IOException {
dis.readFully(ba, off, len);
}
/**
* Read an int, 32-bits. Like DataInputStream.readInt except little endian.
*
* @return little-endian binary int from the datastream
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public final int readInt() throws IOException
{
dis.readFully( work, 0, 4 );
return ( work[ 3 ] ) << 24
| ( work[ 2 ] & 0xff ) << 16
| ( work[ 1 ] & 0xff ) << 8
| ( work[ 0 ] & 0xff );
@Override
public final int readInt() throws IOException {
dis.readFully(work, 0, 4);
return (work[3]) << 24 | (work[2] & 0xff) << 16 | (work[1] & 0xff) << 8
| (work[0] & 0xff);
}
/**
* Read a line.
*
* @return a rough approximation of the 8-bit stream as a 16-bit unicode string
* @return a rough approximation of the 8-bit stream as a 16-bit unicode
* string
* @throws IOException
* @noinspection deprecation
* @deprecated This method does not properly convert bytes to characters. Use a Reader instead with a little-endian
* encoding.
* @deprecated This method does not properly convert bytes to characters.
* Use a Reader instead with a little-endian encoding.
*/
public final String readLine() throws IOException
{
@Deprecated
@Override
public final String readLine() throws IOException {
return dis.readLine();
}
@ -240,31 +249,28 @@ public final class LEDataInputStream implements DataInput
* @return little-endian binary long from the datastream.
* @throws IOException
*/
public final long readLong() throws IOException
{
dis.readFully( work, 0, 8 );
return ( long ) ( work[ 7 ] ) << 56
|
@Override
public final long readLong() throws IOException {
dis.readFully(work, 0, 8);
return (long) (work[7]) << 56 |
/* long cast needed or shift done modulo 32 */
( long ) ( work[ 6 ] & 0xff ) << 48
| ( long ) ( work[ 5 ] & 0xff ) << 40
| ( long ) ( work[ 4 ] & 0xff ) << 32
| ( long ) ( work[ 3 ] & 0xff ) << 24
| ( long ) ( work[ 2 ] & 0xff ) << 16
| ( long ) ( work[ 1 ] & 0xff ) << 8
| ( long ) ( work[ 0 ] & 0xff );
(long) (work[6] & 0xff) << 48 | (long) (work[5] & 0xff) << 40
| (long) (work[4] & 0xff) << 32 | (long) (work[3] & 0xff) << 24
| (long) (work[2] & 0xff) << 16 | (long) (work[1] & 0xff) << 8
| work[0] & 0xff;
}
/**
* Read short, 16-bits. Like DataInputStream.readShort except little endian.
*
* @return little endian binary short from stream.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public final short readShort() throws IOException
{
dis.readFully( work, 0, 2 );
return ( short ) ( ( work[ 1 ] & 0xff ) << 8 | ( work[ 0 ] & 0xff ) );
@Override
public final short readShort() throws IOException {
dis.readFully(work, 0, 2);
return (short) ((work[1] & 0xff) << 8 | (work[0] & 0xff));
}
/**
@ -272,48 +278,53 @@ public final class LEDataInputStream implements DataInput
*
* @return String read.
*/
public final String readUTF() throws IOException
{
@Override
public final String readUTF() throws IOException {
return dis.readUTF();
}
/**
* Read an unsigned byte. Note: returns an int, even though says Byte (non-Javadoc)
* Read an unsigned byte. Note: returns an int, even though says Byte
* (non-Javadoc)
*
* @throws IOException if read fails.
* @throws IOException
* if read fails.
* @see java.io.DataInput#readUnsignedByte()
*/
public final int readUnsignedByte() throws IOException
{
@Override
public final int readUnsignedByte() throws IOException {
return dis.readUnsignedByte();
}
/**
* Read an unsigned short, 16 bits. Like DataInputStream.readUnsignedShort except little endian. Note, returns int
* even though it reads a short.
* Read an unsigned short, 16 bits. Like DataInputStream.readUnsignedShort
* except little endian. Note, returns int even though it reads a short.
*
* @return little-endian int from the stream.
* @throws IOException if read fails.
* @throws IOException
* if read fails.
*/
public final int readUnsignedShort() throws IOException
{
dis.readFully( work, 0, 2 );
return ( ( work[ 1 ] & 0xff ) << 8 | ( work[ 0 ] & 0xff ) );
@Override
public final int readUnsignedShort() throws IOException {
dis.readFully(work, 0, 2);
return ((work[1] & 0xff) << 8 | (work[0] & 0xff));
}
/**
* Skip over bytes in the stream. See the general contract of the <code>skipBytes</code> method of
* <code>DataInput</code>.
* Skip over bytes in the stream. See the general contract of the
* <code>skipBytes</code> method of <code>DataInput</code>.
* <p/>
* Bytes for this operation are read from the contained input stream.
*
* @param n the number of bytes to be skipped.
* @param n
* the number of bytes to be skipped.
*
* @return the actual number of bytes skipped.
* @throws IOException if an I/O error occurs.
* @throws IOException
* if an I/O error occurs.
*/
public final int skipBytes( int n ) throws IOException
{
return dis.skipBytes( n );
}
@Override
public final int skipBytes(int n) throws IOException {
return dis.skipBytes(n);
}
}

View File

@ -26,7 +26,6 @@ import org.junit.*;
import static org.junit.Assert.*;
import org.xml.sax.SAXException;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
@ -52,14 +51,14 @@ public class BuildAndDecodeTest {
assertEquals(true, isAaptPresent());
}
@Test
public void encodeAndDecodeTest() throws BrutException, IOException {
LOGGER.info("Building testapp.apk...");
File testApk = new File(sTmpDir, "testapp.apk");
ExtFile blank = null;
new Androlib().build(sTestOrigDir, testApk, BuildAndDecodeTest.returnStock(),blank,"");
new Androlib().build(sTestOrigDir, testApk,
BuildAndDecodeTest.returnStock(), blank, "");
LOGGER.info("Decoding testapp.apk...");
ApkDecoder apkDecoder = new ApkDecoder(testApk);
@ -67,7 +66,6 @@ public class BuildAndDecodeTest {
apkDecoder.decode();
}
@Test
public void valuesArraysTest() throws BrutException {
compareValuesFiles("values-mcc001/arrays.xml");
@ -128,40 +126,40 @@ public class BuildAndDecodeTest {
@Test
public void qualifiersTest() throws BrutException {
compareValuesFiles("values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp" +
"-xlarge-long-land-desk-night-xhdpi-finger-keyssoft-12key" +
"-navhidden-dpad/strings.xml");
compareValuesFiles("values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp"
+ "-xlarge-long-land-desk-night-xhdpi-finger-keyssoft-12key"
+ "-navhidden-dpad/strings.xml");
}
private static boolean isAaptPresent() throws Exception {
boolean result = true;
try
{
try {
Process proc = Runtime.getRuntime().exec("aapt");
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(
proc.getErrorStream()));
String line = null;
while ( (line = br.readLine()) != null){}
} catch (Exception ex){
while ((line = br.readLine()) != null) {
}
} catch (Exception ex) {
result = false;
}
return result;
}
private void compareValuesFiles(String path) throws BrutException {
compareXmlFiles("res/" + path,
new ElementNameAndAttributeQualifier("name"));
compareXmlFiles("res/" + path, new ElementNameAndAttributeQualifier(
"name"));
}
private void compareXmlFiles(String path) throws BrutException {
compareXmlFiles(path, null);
}
private void compareXmlFiles(String path,
ElementQualifier qualifier) throws BrutException {
private void compareXmlFiles(String path, ElementQualifier qualifier)
throws BrutException {
DetailedDiff diff;
try {
Reader control = new FileReader(
new File(sTestOrigDir, path));
Reader control = new FileReader(new File(sTestOrigDir, path));
Reader test = new FileReader(new File(sTestNewDir, path));
diff = new DetailedDiff(new Diff(control, test));
@ -175,8 +173,8 @@ public class BuildAndDecodeTest {
diff.overrideElementQualifier(qualifier);
}
assertTrue(path + ": " +
diff.getAllDifferences().toString(), diff.similar());
assertTrue(path + ": " + diff.getAllDifferences().toString(),
diff.similar());
}
private static HashMap<String, Boolean> returnStock() throws BrutException {
@ -195,6 +193,6 @@ public class BuildAndDecodeTest {
private static ExtFile sTestOrigDir;
private static ExtFile sTestNewDir;
private final static Logger LOGGER =
Logger.getLogger(BuildAndDecodeTest.class.getName());
private final static Logger LOGGER = Logger
.getLogger(BuildAndDecodeTest.class.getName());
}

View File

@ -1,4 +1,4 @@
/**
/**
* Copyright 2011 Ryszard Wiśniewski <brut.alll@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -35,7 +35,8 @@ public abstract class TestUtils {
public static Map<String, String> parseStringsXml(File file)
throws BrutException {
try {
XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser();
XmlPullParser xpp = XmlPullParserFactory.newInstance()
.newPullParser();
xpp.setInput(new FileReader(file));
int eventType;
@ -75,13 +76,14 @@ public abstract class TestUtils {
}
}
/* TODO: move to brut.util.Jar - it's not possible for now, because below
/*
* TODO: move to brut.util.Jar - it's not possible for now, because below
* implementation uses brut.dir. I think I should merge all my projects to
* single brut.common .
*/
public static void copyResourceDir(Class class_, String dirPath, File out)
throws BrutException {
if (! out.exists()) {
if (!out.exists()) {
out.mkdirs();
}
copyResourceDir(class_, dirPath, new FileDirectory(out));
@ -104,12 +106,12 @@ public abstract class TestUtils {
dirURL = class_.getClassLoader().getResource(className);
}
if (dirURL.getProtocol().equals("jar")) {
String jarPath;
try {
jarPath = URLDecoder.decode(dirURL.getPath().substring(
5, dirURL.getPath().indexOf("!")), "UTF-8");
jarPath = URLDecoder.decode(
dirURL.getPath().substring(5,
dirURL.getPath().indexOf("!")), "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new BrutException(ex);
}
@ -117,9 +119,9 @@ public abstract class TestUtils {
}
}
public static class ResValueElementQualifier implements ElementQualifier {
@Override
public boolean qualifyForComparison(Element control, Element test) {
String controlType = control.getTagName();
if ("item".equals(controlType)) {
@ -131,8 +133,9 @@ public abstract class TestUtils {
testType = test.getAttribute("type");
}
return controlType.equals(testType) && control.getAttribute("name")
.equals(test.getAttribute("name"));
return controlType.equals(testType)
&& control.getAttribute("name").equals(
test.getAttribute("name"));
}
}
}