All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tencent.tinker.build.aapt.AaptResourceCollector Maven / Gradle / Ivy

Go to download

Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstalling apk.

There is a newer version: 1.9.15.1
Show newest version
/*
 * 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