- Moves Config --> Type
 - Moves Type -> TypeSpec
 - ResType -> ResTypeSpec
 - ResConfig -> ResType

 This is to match AOSP and ease the transitions/updates of new AOSP drops
This commit is contained in:
Connor Tumbleson 2015-12-07 20:48:57 -06:00
parent 1e5dc3006e
commit 6c4167fba4
8 changed files with 173 additions and 179 deletions

View File

@ -1,72 +0,0 @@
/**
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.res.data;
import brut.androlib.AndrolibException;
import brut.androlib.err.UndefinedResObject;
import java.util.*;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public class ResConfig {
private final ResConfigFlags mFlags;
private final Map<ResResSpec, ResResource> mResources = new LinkedHashMap<ResResSpec, ResResource>();
public ResConfig(ResConfigFlags flags) {
this.mFlags = flags;
}
public Set<ResResource> listResources() {
return new LinkedHashSet<ResResource>(mResources.values());
}
public ResResource getResource(ResResSpec spec) throws AndrolibException {
ResResource res = mResources.get(spec);
if (res == null) {
throw new UndefinedResObject(String.format(
"resource: spec=%s, config=%s", spec, this));
}
return res;
}
public Set<ResResSpec> listResSpecs() {
return mResources.keySet();
}
public ResConfigFlags getFlags() {
return mFlags;
}
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) {
throw new AndrolibException(String.format(
"Multiple resources: spec=%s, config=%s", spec, this));
}
}
@Override
public String toString() {
return mFlags.toString();
}
}

View File

@ -33,8 +33,8 @@ public class ResPackage {
private final int mId; private final int mId;
private final String mName; private final String mName;
private final Map<ResID, ResResSpec> mResSpecs = new LinkedHashMap<ResID, ResResSpec>(); private final Map<ResID, ResResSpec> mResSpecs = new LinkedHashMap<ResID, ResResSpec>();
private final Map<ResConfigFlags, ResConfig> mConfigs = new LinkedHashMap<ResConfigFlags, ResConfig>(); private final Map<ResConfigFlags, ResType> mConfigs = new LinkedHashMap<ResConfigFlags, ResType>();
private final Map<String, ResType> mTypes = new LinkedHashMap<String, ResType>(); private final Map<String, ResTypeSpec> mTypes = new LinkedHashMap<String, ResTypeSpec>();
private final Set<ResID> mSynthesizedRes = new HashSet<ResID>(); private final Set<ResID> mSynthesizedRes = new HashSet<ResID>();
private ResValueFactory mValueFactory; private ResValueFactory mValueFactory;
@ -61,16 +61,16 @@ public class ResPackage {
return spec; return spec;
} }
public List<ResConfig> getConfigs() { public List<ResType> getConfigs() {
return new ArrayList<ResConfig>(mConfigs.values()); return new ArrayList<ResType>(mConfigs.values());
} }
public boolean hasConfig(ResConfigFlags flags) { public boolean hasConfig(ResConfigFlags flags) {
return mConfigs.containsKey(flags); return mConfigs.containsKey(flags);
} }
public ResConfig getConfig(ResConfigFlags flags) throws AndrolibException { public ResType getConfig(ResConfigFlags flags) throws AndrolibException {
ResConfig config = mConfigs.get(flags); ResType config = mConfigs.get(flags);
if (config == null) { if (config == null) {
throw new UndefinedResObject("config: " + flags); throw new UndefinedResObject("config: " + flags);
} }
@ -81,26 +81,26 @@ public class ResPackage {
return mResSpecs.size(); return mResSpecs.size();
} }
public ResConfig getOrCreateConfig(ResConfigFlags flags) public ResType getOrCreateConfig(ResConfigFlags flags)
throws AndrolibException { throws AndrolibException {
ResConfig config = mConfigs.get(flags); ResType config = mConfigs.get(flags);
if (config == null) { if (config == null) {
config = new ResConfig(flags); config = new ResType(flags);
mConfigs.put(flags, config); mConfigs.put(flags, config);
} }
return config; return config;
} }
public List<ResType> listTypes() { public List<ResTypeSpec> listTypes() {
return new ArrayList<ResType>(mTypes.values()); return new ArrayList<ResTypeSpec>(mTypes.values());
} }
public boolean hasType(String typeName) { public boolean hasType(String typeName) {
return mTypes.containsKey(typeName); return mTypes.containsKey(typeName);
} }
public ResType getType(String typeName) throws AndrolibException { public ResTypeSpec getType(String typeName) throws AndrolibException {
ResType type = mTypes.get(typeName); ResTypeSpec type = mTypes.get(typeName);
if (type == null) { if (type == null) {
throw new UndefinedResObject("type: " + typeName); throw new UndefinedResObject("type: " + typeName);
} }
@ -120,13 +120,13 @@ public class ResPackage {
} }
public Collection<ResValuesFile> listValuesFiles() { public Collection<ResValuesFile> listValuesFiles() {
Map<Duo<ResType, ResConfig>, ResValuesFile> ret = new HashMap<Duo<ResType, ResConfig>, ResValuesFile>(); Map<Duo<ResTypeSpec, ResType>, ResValuesFile> ret = new HashMap<Duo<ResTypeSpec, ResType>, ResValuesFile>();
for (ResResSpec spec : mResSpecs.values()) { for (ResResSpec spec : mResSpecs.values()) {
for (ResResource res : spec.listResources()) { for (ResResource res : spec.listResources()) {
if (res.getValue() instanceof ResValuesXmlSerializable) { if (res.getValue() instanceof ResValuesXmlSerializable) {
ResType type = res.getResSpec().getType(); ResTypeSpec type = res.getResSpec().getType();
ResConfig config = res.getConfig(); ResType config = res.getConfig();
Duo<ResType, ResConfig> key = new Duo<ResType, ResConfig>( Duo<ResTypeSpec, ResType> key = new Duo<ResTypeSpec, ResType>(
type, config); type, config);
ResValuesFile values = ret.get(key); ResValuesFile values = ret.get(key);
if (values == null) { if (values == null) {
@ -162,13 +162,13 @@ public class ResPackage {
} }
} }
public void addConfig(ResConfig config) throws AndrolibException { public void addConfig(ResType config) throws AndrolibException {
if (mConfigs.put(config.getFlags(), config) != null) { if (mConfigs.put(config.getFlags(), config) != null) {
throw new AndrolibException("Multiple configs: " + config); throw new AndrolibException("Multiple configs: " + config);
} }
} }
public void addType(ResType type) throws AndrolibException { public void addType(ResTypeSpec type) throws AndrolibException {
if (mTypes.containsKey(type.getName())) { if (mTypes.containsKey(type.getName())) {
LOGGER.warning("Multiple types detected! " + type + " ignored!"); LOGGER.warning("Multiple types detected! " + type + " ignored!");
} else { } else {

View File

@ -28,10 +28,10 @@ public class ResResSpec {
private final ResID mId; private final ResID mId;
private final String mName; private final String mName;
private final ResPackage mPackage; private final ResPackage mPackage;
private final ResType mType; private final ResTypeSpec 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) { public ResResSpec(ResID id, String name, ResPackage pkg, ResTypeSpec type) {
this.mId = id; this.mId = id;
this.mName = name; this.mName = name;
this.mPackage = pkg; this.mPackage = pkg;
@ -42,7 +42,7 @@ public class ResResSpec {
return new LinkedHashSet<ResResource>(mResources.values()); return new LinkedHashSet<ResResource>(mResources.values());
} }
public ResResource getResource(ResConfig config) throws AndrolibException { public ResResource getResource(ResType config) throws AndrolibException {
return getResource(config.getFlags()); return getResource(config.getFlags());
} }
@ -56,7 +56,7 @@ public class ResResSpec {
return res; return res;
} }
public boolean hasResource(ResConfig config) { public boolean hasResource(ResType config) {
return hasResource(config.getFlags()); return hasResource(config.getFlags());
} }
@ -97,7 +97,7 @@ public class ResResSpec {
return mPackage; return mPackage;
} }
public ResType getType() { public ResTypeSpec getType() {
return mType; return mType;
} }

View File

@ -23,11 +23,11 @@ import brut.androlib.res.data.value.ResValue;
* @author Ryszard Wiśniewski <brut.alll@gmail.com> * @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/ */
public class ResResource { public class ResResource {
private final ResConfig mConfig; private final ResType mConfig;
private final ResResSpec mResSpec; private final ResResSpec mResSpec;
private final ResValue mValue; private final ResValue mValue;
public ResResource(ResConfig config, ResResSpec spec, ResValue value) { public ResResource(ResType config, ResResSpec spec, ResValue value) {
this.mConfig = config; this.mConfig = config;
this.mResSpec = spec; this.mResSpec = spec;
this.mValue = value; this.mValue = value;
@ -38,7 +38,7 @@ public class ResResource {
+ mConfig.getFlags().getQualifiers() + "/" + mResSpec.getName(); + mConfig.getFlags().getQualifiers() + "/" + mResSpec.getName();
} }
public ResConfig getConfig() { public ResType getConfig() {
return mConfig; return mConfig;
} }

View File

@ -23,49 +23,50 @@ import java.util.*;
/** /**
* @author Ryszard Wiśniewski <brut.alll@gmail.com> * @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/ */
public final class ResType { public class ResType {
private final String mName; private final ResConfigFlags mFlags;
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>(); private final Map<ResResSpec, ResResource> mResources = new LinkedHashMap<ResResSpec, ResResource>();
private final ResTable mResTable; public ResType(ResConfigFlags flags) {
private final ResPackage mPackage; this.mFlags = flags;
public ResType(String name, ResTable resTable, ResPackage package_) {
this.mName = name;
this.mResTable = resTable;
this.mPackage = package_;
} }
public String getName() { public Set<ResResource> listResources() {
return mName; return new LinkedHashSet<ResResource>(mResources.values());
} }
public boolean isString() { public ResResource getResource(ResResSpec spec) throws AndrolibException {
return mName.equalsIgnoreCase("string"); ResResource res = mResources.get(spec);
if (res == null) {
throw new UndefinedResObject(String.format(
"resource: spec=%s, config=%s", spec, this));
}
return res;
} }
public Set<ResResSpec> listResSpecs() { public Set<ResResSpec> listResSpecs() {
return new LinkedHashSet<ResResSpec>(mResSpecs.values()); return mResources.keySet();
} }
public ResResSpec getResSpec(String name) throws AndrolibException { public ResConfigFlags getFlags() {
ResResSpec spec = mResSpecs.get(name); return mFlags;
if (spec == null) {
throw new UndefinedResObject(String.format("resource spec: %s/%s",
getName(), name));
}
return spec;
} }
public void addResSpec(ResResSpec spec) throws AndrolibException { public void addResource(ResResource res) throws AndrolibException {
if (mResSpecs.put(spec.getName(), spec) != null) { addResource(res, false);
}
public void addResource(ResResource res, boolean overwrite)
throws AndrolibException {
ResResSpec spec = res.getResSpec();
if (mResources.put(spec, res) != null && !overwrite) {
throw new AndrolibException(String.format( throw new AndrolibException(String.format(
"Multiple res specs: %s/%s", getName(), spec.getName())); "Multiple resources: spec=%s, config=%s", spec, this));
} }
} }
@Override @Override
public String toString() { public String toString() {
return mName; return mFlags.toString();
} }
} }

View File

@ -0,0 +1,71 @@
/**
* Copyright 2014 Ryszard Wiśniewski <brut.alll@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package brut.androlib.res.data;
import brut.androlib.AndrolibException;
import brut.androlib.err.UndefinedResObject;
import java.util.*;
/**
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/
public final class ResTypeSpec {
private final String mName;
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>();
private final ResTable mResTable;
private final ResPackage mPackage;
public ResTypeSpec(String name, ResTable resTable, ResPackage package_) {
this.mName = name;
this.mResTable = resTable;
this.mPackage = package_;
}
public String getName() {
return mName;
}
public boolean isString() {
return mName.equalsIgnoreCase("string");
}
public Set<ResResSpec> listResSpecs() {
return new LinkedHashSet<ResResSpec>(mResSpecs.values());
}
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));
}
return spec;
}
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()));
}
}
@Override
public String toString() {
return mName;
}
}

View File

@ -24,11 +24,11 @@ import java.util.Set;
*/ */
public class ResValuesFile { public class ResValuesFile {
private final ResPackage mPackage; private final ResPackage mPackage;
private final ResType mType; private final ResTypeSpec mType;
private final ResConfig mConfig; private final ResType 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) { public ResValuesFile(ResPackage pkg, ResTypeSpec type, ResType config) {
this.mPackage = pkg; this.mPackage = pkg;
this.mType = type; this.mType = type;
this.mConfig = config; this.mConfig = config;
@ -44,11 +44,11 @@ public class ResValuesFile {
return mResources; return mResources;
} }
public ResType getType() { public ResTypeSpec getType() {
return mType; return mType;
} }
public ResConfig getConfig() { public ResType getConfig() {
return mConfig; return mConfig;
} }

View File

@ -44,7 +44,7 @@ public class ARSCDecoder {
throws AndrolibException { throws AndrolibException {
try { try {
ARSCDecoder decoder = new ARSCDecoder(arscStream, resTable, findFlagsOffsets, keepBroken); ARSCDecoder decoder = new ARSCDecoder(arscStream, resTable, findFlagsOffsets, keepBroken);
ResPackage[] pkgs = decoder.readTable(); ResPackage[] pkgs = decoder.readTableHeader();
return new ARSCData(pkgs, decoder.mFlagsOffsets == null return new ARSCData(pkgs, decoder.mFlagsOffsets == null
? null ? null
: decoder.mFlagsOffsets.toArray(new FlagsOffset[0]), resTable); : decoder.mFlagsOffsets.toArray(new FlagsOffset[0]), resTable);
@ -66,7 +66,7 @@ public class ARSCDecoder {
mKeepBroken = keepBroken; mKeepBroken = keepBroken;
} }
private ResPackage[] readTable() throws IOException, AndrolibException { private ResPackage[] readTableHeader() throws IOException, AndrolibException {
nextChunkCheckType(Header.TYPE_TABLE); nextChunkCheckType(Header.TYPE_TABLE);
int packageCount = mIn.readInt(); int packageCount = mIn.readInt();
@ -75,12 +75,12 @@ public class ARSCDecoder {
nextChunk(); nextChunk();
for (int i = 0; i < packageCount; i++) { for (int i = 0; i < packageCount; i++) {
packages[i] = readPackage(); packages[i] = readTablePackage();
} }
return packages; return packages;
} }
private ResPackage readPackage() throws IOException, AndrolibException { private ResPackage readTablePackage() throws IOException, AndrolibException {
checkChunkType(Header.TYPE_PACKAGE); checkChunkType(Header.TYPE_PACKAGE);
int id = (byte) mIn.readInt(); int id = (byte) mIn.readInt();
@ -112,8 +112,8 @@ public class ARSCDecoder {
readLibraryType(); readLibraryType();
} }
while (mHeader.type == Header.TYPE_TYPE) { while (mHeader.type == Header.TYPE_SPEC_TYPE) {
readType(); readTableTypeSpec();
} }
return mPkg; return mPkg;
@ -132,13 +132,13 @@ public class ARSCDecoder {
LOGGER.info(String.format("Decoding Shared Library (%s), pkgId: %d", packageName, packageId)); LOGGER.info(String.format("Decoding Shared Library (%s), pkgId: %d", packageName, packageId));
} }
while(nextChunk().type == Header.TYPE_CONFIG) { while(nextChunk().type == Header.TYPE_TYPE) {
readConfig(); readTableTypeSpec();
} }
} }
private ResType readType() throws AndrolibException, IOException { private ResTypeSpec readTableTypeSpec() throws AndrolibException, IOException {
checkChunkType(Header.TYPE_TYPE); checkChunkType(Header.TYPE_SPEC_TYPE);
byte id = mIn.readByte(); byte id = mIn.readByte();
mIn.skipBytes(3); mIn.skipBytes(3);
int entryCount = mIn.readInt(); int entryCount = mIn.readInt();
@ -152,21 +152,22 @@ public class ARSCDecoder {
/* flags */mIn.skipBytes(entryCount * 4); /* flags */mIn.skipBytes(entryCount * 4);
mResId = (0xff000000 & mResId) | id << 16; mResId = (0xff000000 & mResId) | id << 16;
mType = new ResType(mTypeNames.getString(id - 1), mResTable, mPkg); mTypeSpec = new ResTypeSpec(mTypeNames.getString(id - 1), mResTable, mPkg);
mPkg.addType(mType); mPkg.addType(mTypeSpec);
while (nextChunk().type == Header.TYPE_CONFIG) { while (nextChunk().type == Header.TYPE_TYPE) {
readConfig(); readTableType();
} }
addMissingResSpecs(); addMissingResSpecs();
return mType; return mTypeSpec;
} }
private ResConfig readConfig() throws IOException, AndrolibException { private ResType readTableType() throws IOException, AndrolibException {
checkChunkType(Header.TYPE_CONFIG); checkChunkType(Header.TYPE_TYPE);
/* typeId */mIn.skipInt(); /* typeId */mIn.skipBytes(1);
/* res0, res1 */mIn.skipBytes(3);
int entryCount = mIn.readInt(); int entryCount = mIn.readInt();
/* entriesStart */mIn.skipInt(); /* entriesStart */mIn.skipInt();
@ -174,7 +175,7 @@ public class ARSCDecoder {
int[] entryOffsets = mIn.readIntArray(entryCount); int[] entryOffsets = mIn.readIntArray(entryCount);
if (flags.isInvalid) { if (flags.isInvalid) {
String resName = mType.getName() + flags.getQualifiers(); String resName = mTypeSpec.getName() + flags.getQualifiers();
if (mKeepBroken) { if (mKeepBroken) {
LOGGER.warning("Invalid config flags detected: " + resName); LOGGER.warning("Invalid config flags detected: " + resName);
} else { } else {
@ -182,7 +183,7 @@ public class ARSCDecoder {
} }
} }
mConfig = flags.isInvalid && !mKeepBroken ? null : mPkg.getOrCreateConfig(flags); mType = flags.isInvalid && !mKeepBroken ? null : mPkg.getOrCreateConfig(flags);
for (int i = 0; i < entryOffsets.length; i++) { for (int i = 0; i < entryOffsets.length; i++) {
if (entryOffsets[i] != -1) { if (entryOffsets[i] != -1) {
@ -192,7 +193,7 @@ public class ARSCDecoder {
} }
} }
return mConfig; return mType;
} }
private void readEntry() throws IOException, AndrolibException { private void readEntry() throws IOException, AndrolibException {
@ -202,10 +203,10 @@ public class ARSCDecoder {
ResValue value = (flags & ENTRY_FLAG_COMPLEX) == 0 ? readValue() : readComplexEntry(); ResValue value = (flags & ENTRY_FLAG_COMPLEX) == 0 ? readValue() : readComplexEntry();
if (mType.isString() && value instanceof ResFileValue) { if (mTypeSpec.isString() && value instanceof ResFileValue) {
value = new ResStringValue(value.toString(), ((ResFileValue) value).getRawIntValue()); value = new ResStringValue(value.toString(), ((ResFileValue) value).getRawIntValue());
} }
if (mConfig == null) { if (mType == null) {
return; return;
} }
@ -214,19 +215,18 @@ public class ARSCDecoder {
if (mPkg.hasResSpec(resId)) { if (mPkg.hasResSpec(resId)) {
spec = mPkg.getResSpec(resId); spec = mPkg.getResSpec(resId);
} else { } else {
spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), mPkg, mType); spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), mPkg, mTypeSpec);
mPkg.addResSpec(spec); mPkg.addResSpec(spec);
mType.addResSpec(spec); mTypeSpec.addResSpec(spec);
} }
ResResource res = new ResResource(mConfig, spec, value); ResResource res = new ResResource(mType, spec, value);
mConfig.addResource(res); mType.addResource(res);
spec.addResource(res); spec.addResource(res);
mPkg.addResource(res); mPkg.addResource(res);
} }
private ResBagValue readComplexEntry() throws IOException, private ResBagValue readComplexEntry() throws IOException, AndrolibException {
AndrolibException {
int parent = mIn.readInt(); int parent = mIn.readInt();
int count = mIn.readInt(); int count = mIn.readInt();
@ -394,19 +394,19 @@ public class ARSCDecoder {
continue; continue;
} }
ResResSpec spec = new ResResSpec(new ResID(resId | i), String.format("APKTOOL_DUMMY_%04x", i), mPkg, mType); ResResSpec spec = new ResResSpec(new ResID(resId | i), String.format("APKTOOL_DUMMY_%04x", i), mPkg, mTypeSpec);
mPkg.addResSpec(spec); mPkg.addResSpec(spec);
mType.addResSpec(spec); mTypeSpec.addResSpec(spec);
if (mConfig == null) { if (mType == null) {
mConfig = mPkg.getOrCreateConfig(new ResConfigFlags()); mType = mPkg.getOrCreateConfig(new ResConfigFlags());
} }
ResValue value = new ResBoolValue(false, 0, null); ResValue value = new ResBoolValue(false, 0, null);
ResResource res = new ResResource(mConfig, spec, value); ResResource res = new ResResource(mType, spec, value);
mPkg.addResource(res); mPkg.addResource(res);
mConfig.addResource(res); mType.addResource(res);
spec.addResource(res); spec.addResource(res);
} }
} }
@ -439,8 +439,8 @@ public class ARSCDecoder {
private StringBlock mTypeNames; private StringBlock mTypeNames;
private StringBlock mSpecNames; private StringBlock mSpecNames;
private ResPackage mPkg; private ResPackage mPkg;
private ResTypeSpec mTypeSpec;
private ResType mType; private ResType mType;
private ResConfig mConfig;
private int mResId; private int mResId;
private boolean[] mMissingResSpecs; private boolean[] mMissingResSpecs;
@ -468,8 +468,7 @@ public class ARSCDecoder {
} }
public final static short TYPE_NONE = -1, TYPE_TABLE = 0x0002, public final static short TYPE_NONE = -1, TYPE_TABLE = 0x0002,
TYPE_PACKAGE = 0x0200, TYPE_TYPE = 0x0202, TYPE_LIBRARY = 0x0203, TYPE_PACKAGE = 0x0200, TYPE_TYPE = 0x0201, TYPE_SPEC_TYPE = 0x0202, TYPE_LIBRARY = 0x0203;
TYPE_CONFIG = 0x0201;
} }
public static class FlagsOffset { public static class FlagsOffset {
@ -515,20 +514,15 @@ public class ARSCDecoder {
} }
public int findPackageWithMostResSpecs() { public int findPackageWithMostResSpecs() {
int count = -1; int count = mPackages[0].getResSpecCount();
int id = 0; int id = 0;
// set starting point to package id 0.
count = mPackages[0].getResSpecCount();
// loop through packages looking for largest
for (int i = 0; i < mPackages.length; i++) { for (int i = 0; i < mPackages.length; i++) {
if (mPackages[i].getResSpecCount() >= count) { if (mPackages[i].getResSpecCount() >= count) {
count = mPackages[i].getResSpecCount(); count = mPackages[i].getResSpecCount();
id = i; id = i;
} }
} }
return id; return id;
} }