com.tencent.tinker.build.aapt.AaptResourceCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tinker-patch-lib Show documentation
Show all versions of tinker-patch-lib Show documentation
Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstalling apk.
/*
* Copyright 2014-present Facebook, Inc.
*
* 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 com.tencent.tinker.build.aapt;
import com.google.common.base.Joiner;
import com.tencent.tinker.build.aapt.RDotTxtEntry.IdType;
import com.tencent.tinker.build.aapt.RDotTxtEntry.RType;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class AaptResourceCollector {
private final Map>> rTypeResourceDirectoryMap;
// private final Map> rTypeIncreaseResourceDirectoryListMap;
// private final Map> rTypeIncreaseResourceDirectoryMap;
private final Map rTypeEnumeratorMap;
private final Map originalResourceMap;
private final Map> rTypeResourceMap;
private final Map> rTypeIncreaseResourceMap;
private final Map> duplicateResourceMap;
private final Map> sanitizeTypeMap;
private final Set ignoreIdSet;
private int currentTypeId;
public AaptResourceCollector() {
this.rTypeResourceDirectoryMap = new HashMap>>();
// this.rTypeIncreaseResourceDirectoryListMap = new HashMap>();
// this.rTypeIncreaseResourceDirectoryMap = new HashMap>();
this.rTypeEnumeratorMap = new HashMap();
this.rTypeResourceMap = new HashMap>();
this.rTypeIncreaseResourceMap = new HashMap>();
this.duplicateResourceMap = new HashMap>();
this.sanitizeTypeMap = new HashMap>();
this.originalResourceMap = new HashMap();
this.ignoreIdSet = new HashSet();
// attr type must 1
this.currentTypeId = 2;
}
public AaptResourceCollector(Map> rTypeResourceMap) {
this();
if (rTypeResourceMap != null) {
Iterator>> iterator = rTypeResourceMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry> entry = iterator.next();
RType rType = entry.getKey();
Set set = entry.getValue();
// this.rTypeResourceMap.put(rType, new HashSet(set));
for (RDotTxtEntry rDotTxtEntry : set) {
originalResourceMap.put(rDotTxtEntry, rDotTxtEntry);
ResourceIdEnumerator resourceIdEnumerator = null;
if (!rDotTxtEntry.idType.equals(IdType.INT_ARRAY)) {
int resourceId = Integer.decode(rDotTxtEntry.idValue.trim()).intValue();
int typeId = ((resourceId & 0x00FF0000) / 0x00010000);
if (typeId >= currentTypeId) {
currentTypeId = typeId + 1;
}
if (this.rTypeEnumeratorMap.containsKey(rType)) {
resourceIdEnumerator = this.rTypeEnumeratorMap.get(rType);
if (resourceIdEnumerator.currentId < resourceId) {
resourceIdEnumerator.currentId = resourceId;
}
} else {
resourceIdEnumerator = new ResourceIdEnumerator();
resourceIdEnumerator.currentId = resourceId;
this.rTypeEnumeratorMap.put(rType, resourceIdEnumerator);
}
}
}
}
}
}
public void addIntResourceIfNotPresent(RType rType, String name) { //, ResourceDirectory resourceDirectory) {
if (!rTypeEnumeratorMap.containsKey(rType)) {
if (rType.equals(RType.ATTR)) {
rTypeEnumeratorMap.put(rType, new ResourceIdEnumerator(1));
} else {
rTypeEnumeratorMap.put(rType, new ResourceIdEnumerator(currentTypeId++));
}
}
RDotTxtEntry entry = new FakeRDotTxtEntry(IdType.INT, rType, name);
Set resourceSet = null;
if (this.rTypeResourceMap.containsKey(rType)) {
resourceSet = this.rTypeResourceMap.get(rType);
} else {
resourceSet = new HashSet();
this.rTypeResourceMap.put(rType, resourceSet);
}
if (!resourceSet.contains(entry)) {
String idValue = String.format("0x%08x", rTypeEnumeratorMap.get(rType).next());
addResource(rType, IdType.INT, name, idValue); //, resourceDirectory);
}
}
public void addIntArrayResourceIfNotPresent(RType rType, String name, int numValues) {
// Robolectric expects the array to be populated with the right number
// of values, irrespective
// of what the values are.
String idValue = String.format("{ %s }", Joiner.on(",").join(Collections.nCopies(numValues, "0x7f000000")));
addResource(rType, IdType.INT_ARRAY, name, idValue);
}
/**
* add resource
*
* @param rType
* @param idType
* @param name
* @param idValue
*/
public void addResource(RType rType, IdType idType, String name, String idValue) {
Set resourceSet = null;
if (this.rTypeResourceMap.containsKey(rType)) {
resourceSet = this.rTypeResourceMap.get(rType);
} else {
resourceSet = new HashSet();
this.rTypeResourceMap.put(rType, resourceSet);
}
RDotTxtEntry rDotTxtEntry = new RDotTxtEntry(idType, rType, name, idValue);
boolean increaseResource = false;
if (!resourceSet.contains(rDotTxtEntry)) {
if (this.originalResourceMap.containsKey(rDotTxtEntry)) {
this.rTypeEnumeratorMap.get(rType).previous();
rDotTxtEntry = this.originalResourceMap.get(rDotTxtEntry);
} else {
increaseResource = true;
}
resourceSet.add(rDotTxtEntry);
}
Set increaseResourceSet = null;
//new r dot txt entry
if (this.rTypeIncreaseResourceMap.containsKey(rType)) {
increaseResourceSet = this.rTypeIncreaseResourceMap.get(rType);
} else {
increaseResourceSet = new HashSet();
this.rTypeIncreaseResourceMap.put(rType, increaseResourceSet);
}
if (increaseResource) {
increaseResourceSet.add(rDotTxtEntry);
// addResourceDirectory(rType, name, resourceDirectory);
}
}
// private void addResourceDirectory(RType rType, String name, ResourceDirectory resourceDirectory) {
// if (resourceDirectory != null) {
// Map resourceDirectoryMap = null;
// List resourceDirectoryList = null;
// if (this.rTypeIncreaseResourceDirectoryMap.containsKey(rType)) {
// resourceDirectoryMap = this.rTypeIncreaseResourceDirectoryMap.get(rType);
// resourceDirectoryList = this.rTypeIncreaseResourceDirectoryListMap.get(rType);
// } else {
// resourceDirectoryMap = new HashMap();
// this.rTypeIncreaseResourceDirectoryMap.put(rType, resourceDirectoryMap);
// resourceDirectoryList = new ArrayList();
// this.rTypeIncreaseResourceDirectoryListMap.put(rType, resourceDirectoryList);
// }
// ResourceDirectory existResourceDirectory = null;
// if (resourceDirectoryMap.containsKey(resourceDirectory)) {
// existResourceDirectory = resourceDirectoryMap.get(resourceDirectory);
// } else {
// existResourceDirectory = resourceDirectory;
// resourceDirectoryMap.put(resourceDirectory, resourceDirectory);
// resourceDirectoryList.add(existResourceDirectory);
// }
// existResourceDirectory.resourceEntrySet.add(new ResourceEntry(name, null));
// }
// }
/**
* is contain resource
*
* @param rType
* @param idType
* @param name
* @return boolean
*/
public boolean isContainResource(RType rType, IdType idType, String name) {
boolean result = false;
if (this.rTypeResourceMap.containsKey(rType)) {
Set resourceSet = this.rTypeResourceMap.get(rType);
if (resourceSet.contains(new RDotTxtEntry(idType, rType, name, "0x7f000000"))) {
result = true;
}
}
return result;
}
/**
* add r type resource name
*
* @param rType
* @param resourceName
* @param resourceDirectory
*/
void addRTypeResourceName(RType rType, String resourceName, String resourceValue, ResourceDirectory resourceDirectory) {
Map> directoryResourceDirectoryMap = null;
if (this.rTypeResourceDirectoryMap.containsKey(rType)) {
directoryResourceDirectoryMap = this.rTypeResourceDirectoryMap.get(rType);
} else {
directoryResourceDirectoryMap = new HashMap>();
this.rTypeResourceDirectoryMap.put(rType, directoryResourceDirectoryMap);
}
Set resourceDirectorySet = null;
if (directoryResourceDirectoryMap.containsKey(resourceDirectory.directoryName)) {
resourceDirectorySet = directoryResourceDirectoryMap.get(resourceDirectory.directoryName);
} else {
resourceDirectorySet = new HashSet();
directoryResourceDirectoryMap.put(resourceDirectory.directoryName, resourceDirectorySet);
}
boolean find = false;
ResourceDirectory newResourceDirectory = new ResourceDirectory(resourceDirectory.directoryName, resourceDirectory.resourceFullFilename);
if (!resourceDirectorySet.contains(newResourceDirectory)) {
resourceDirectorySet.add(newResourceDirectory);
}
for (ResourceDirectory oldResourceDirectory : resourceDirectorySet) {
if (oldResourceDirectory.resourceEntrySet.contains(new ResourceEntry(resourceName, resourceValue))) {
find = true;
String resourceKey = rType + "/" + resourceDirectory.directoryName + "/" + resourceName;
Set fullFilenameSet = null;
if (!this.duplicateResourceMap.containsKey(resourceKey)) {
fullFilenameSet = new HashSet();
fullFilenameSet.add(oldResourceDirectory.resourceFullFilename);
this.duplicateResourceMap.put(resourceKey, fullFilenameSet);
} else {
fullFilenameSet = this.duplicateResourceMap.get(resourceKey);
}
fullFilenameSet.add(resourceDirectory.resourceFullFilename);
}
}
if (!find) {
for (ResourceDirectory oldResourceDirectory : resourceDirectorySet) {
if (oldResourceDirectory.equals(newResourceDirectory)) {
if (!oldResourceDirectory.resourceEntrySet.contains(new ResourceEntry(resourceName, resourceValue))) {
oldResourceDirectory.resourceEntrySet.add(new ResourceEntry(resourceName, resourceValue));
}
}
}
}
}
void putSanitizeName(RType rType, String sanitizeName, String rawName) {
HashMap sanitizeNameMap;
if (!sanitizeTypeMap.containsKey(rType)) {
sanitizeNameMap = new HashMap<>();
sanitizeTypeMap.put(rType, sanitizeNameMap);
} else {
sanitizeNameMap = sanitizeTypeMap.get(rType);
}
if (!sanitizeNameMap.containsKey(sanitizeName)) {
sanitizeNameMap.put(sanitizeName, rawName);
}
}
/**
* get raw name
*
* @param sanitizeName
* @return String
*/
public String getRawName(RType rType, String sanitizeName) {
if (!sanitizeTypeMap.containsKey(rType)) {
return null;
}
return this.sanitizeTypeMap.get(rType).get(sanitizeName);
}
/**
* get r type resource map
*
* @return Map>
*/
public Map> getRTypeResourceMap() {
return this.rTypeResourceMap;
}
/**
* @return the duplicateResourceMap
*/
public Map> getDuplicateResourceMap() {
return duplicateResourceMap;
}
/**
* @return the rTypeIncreaseResourceMap
*/
public Map> getRTypeIncreaseResourceMap() {
return rTypeIncreaseResourceMap;
}
/**
* @return the rTypeResourceDirectoryMap
*/
public Map>> getRTypeResourceDirectoryMap() {
return rTypeResourceDirectoryMap;
}
// /**
// * @return the rTypeIncreaseResourceDirectoryListMap
// */
// public Map> getRTypeIncreaseResourceDirectoryListMap() {
// return rTypeIncreaseResourceDirectoryListMap;
// }
void addIgnoreId(String name) {
ignoreIdSet.add(name);
}
/**
* @return the ignoreIdSet
*/
public Set getIgnoreIdSet() {
return ignoreIdSet;
}
private static class ResourceIdEnumerator {
private int currentId = 0;
ResourceIdEnumerator() {
}
ResourceIdEnumerator(int typeId) {
this.currentId = 0x7f000000 + 0x10000 * typeId + -1;
}
int previous() {
return --currentId;
}
int next() {
return ++currentId;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy