mirror of
https://github.com/revanced/Apktool.git
synced 2024-12-12 05:47:46 +01:00
Fixes #1099
- 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:
parent
1e5dc3006e
commit
6c4167fba4
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
@ -96,10 +96,10 @@ public class ARSCDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String name = mIn.readNullEndedString(128, true);
|
String name = mIn.readNullEndedString(128, true);
|
||||||
/* typeStrings */mIn.skipInt();
|
/* typeStrings */mIn.skipInt();
|
||||||
/* lastPublicType */mIn.skipInt();
|
/* lastPublicType */mIn.skipInt();
|
||||||
/* keyStrings */mIn.skipInt();
|
/* keyStrings */mIn.skipInt();
|
||||||
/* lastPublicKey */mIn.skipInt();
|
/* lastPublicKey */mIn.skipInt();
|
||||||
|
|
||||||
mTypeNames = StringBlock.read(mIn);
|
mTypeNames = StringBlock.read(mIn);
|
||||||
mSpecNames = StringBlock.read(mIn);
|
mSpecNames = StringBlock.read(mIn);
|
||||||
@ -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,29 +152,30 @@ 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();
|
||||||
|
|
||||||
ResConfigFlags flags = readConfigFlags();
|
ResConfigFlags flags = readConfigFlags();
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user