Skip to content

Commit

Permalink
[GRAPH] Full apk build resources with dex
Browse files Browse the repository at this point in the history
  • Loading branch information
REAndroid committed May 31, 2024
1 parent 22d41f8 commit f41a663
Show file tree
Hide file tree
Showing 40 changed files with 1,630 additions and 618 deletions.
23 changes: 16 additions & 7 deletions src/main/java/com/reandroid/arsc/refactor/ResourceBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.reandroid.utils.collection.FilterIterator;

import java.util.*;
import java.util.function.Predicate;

public class ResourceBuilder {

Expand Down Expand Up @@ -70,6 +71,7 @@ public void rebuild() {
resultModule.setTableBlock(resultTable);
initializeTable();
mergePackages();
resultTable.refreshFull();
}

public int applyIdChanges(Iterator<IntegerReference> iterator) {
Expand Down Expand Up @@ -145,7 +147,7 @@ private void transferResFiles(ApkModule apkModule) {
zipEntryMap.remove(path);
}
}
private void rebuildManifest(ApkModule apkModule) {
public void rebuildManifest(ApkModule apkModule) {
AndroidManifestBlock moduleManifest = apkModule.getAndroidManifest();
if(moduleManifest == null){
return;
Expand All @@ -165,6 +167,7 @@ private void rebuildManifest(ApkModule apkModule) {
resultManifest.mergeWithName(getMergeOption(), moduleManifest);

apkModule.setManifest(resultManifest);
apkModule.keepManifestChanges();
}

private void mergePackages(){
Expand All @@ -179,12 +182,14 @@ private void mergePackages(){
}
private void mergePackage(PackageBlock sourcePackage, PackageBlock resultPackage) {
ResourceMergeOption mergeOption = this.getMergeOption();
Iterator<ResourceEntry> iterator = sourcePackage.iterator();
Predicate<? super ResourceEntry> keepEntries = mergeOption.getKeepEntries();
Iterator<ResourceEntry> iterator = FilterIterator.of(sourcePackage.iterator(), keepEntries);
while (iterator.hasNext()){
ResourceEntry sourceEntry = iterator.next();
if(sourceEntry.isEmpty()) {
continue;
}

ResourceEntry resultEntry = resultPackage.mergeWithName(mergeOption, sourceEntry);
addIdMap(sourceEntry.getResourceId(), resultEntry.getResourceId());
}
Expand All @@ -194,7 +199,7 @@ private void initializeTable(){
sourceTable.refresh();
TableBlock resultTable = this.getResultTable();

resultTable.addFrameworks(resultTable.frameworks());
resultTable.addFrameworks(sourceTable.frameworks());

for(PackageBlock sourcePackage : sourceTable) {
resultTable.newPackage(sourcePackage.getId(), sourcePackage.getName());
Expand All @@ -219,19 +224,20 @@ private void initializePackage(PackageBlock sourcePackage, PackageBlock resultPa
initializeEntries(sourcePackage, resultPackage);
}
private void initializeTypeString(PackageBlock sourcePackage, PackageBlock resultPackage) {
Predicate<? super ResourceEntry> keepEntries = getMergeOption().getKeepEntries();
TypeStringPool sourcePool = sourcePackage.getTypeStringPool();
Set<String> typeSet = new HashSet<>(sourcePool.size());
for(TypeString typeString : sourcePool) {
String typeName = typeString.get();
Iterator<ResourceEntry> iterator = FilterIterator.of(sourcePackage.iterator(typeName),
ResourceEntry::isDeclared);
keepEntries);
if(iterator.hasNext()){
typeSet.add(typeName);
}
}
List<String> typeList = new ArrayCollection<>(typeSet);
typeList.sort(CompareUtil.getComparableComparator());
resultPackage.getTypeStringPool().addStrings(typeSet);
resultPackage.getTypeStringPool().addStrings(typeList);
}
private void initializeSpecString(PackageBlock sourcePackage, PackageBlock resultPackage) {
resultPackage.getSpecStringPool().merge(sourcePackage.getSpecStringPool());
Expand All @@ -244,9 +250,12 @@ private void initializeEntries(PackageBlock sourcePackage, PackageBlock resultPa
}
}
private void initializeEntries(String typeName, PackageBlock sourcePackage, PackageBlock resultPackage) {
Predicate<? super ResourceEntry> keepEntries = getMergeOption().getKeepEntries();
ArrayCollection<ResourceEntry> sourceEntryList = new ArrayCollection<>();
Iterator<ResourceEntry> iterator = FilterIterator.of(sourcePackage.iterator(typeName),
ResourceEntry::isDeclared);
Iterator<ResourceEntry> iterator = FilterIterator.of(
sourcePackage.iterator(typeName),
resourceEntry -> resourceEntry.isDeclared() &&
keepEntries.test(resourceEntry));
sourceEntryList.addAll(iterator);

sourceEntryList.sort(this::compareEntryNames);
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/com/reandroid/arsc/refactor/ResourceMergeOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,77 @@
import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
import com.reandroid.arsc.model.ResourceEntry;
import com.reandroid.arsc.model.ResourceName;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResConfig;
import com.reandroid.arsc.value.ResValue;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.common.BytesOutputStream;
import com.reandroid.utils.collection.CollectionUtil;

import java.io.IOException;
import java.util.function.Predicate;

public class ResourceMergeOption {

private Predicate<? super ResourceEntry> keepEntries;
private Predicate<? super ResourceName> keepResourceNames;
private Predicate<? super ResConfig> keepConfigs;

public ResourceMergeOption(){
}

public Predicate<? super Entry> getKeepEntryConfigs() {
Predicate<? super ResConfig> keepConfigs = this.getKeepConfigs();
return (Predicate<Entry>) entry -> keepConfigs.test(entry.getResConfig());
}
public Predicate<? super ResConfig> getKeepConfigs() {
Predicate<? super ResConfig> keepConfigs = this.keepConfigs;
if(keepConfigs == null) {
keepConfigs = CollectionUtil.getAcceptAll();
}
return keepConfigs;
}
public void setKeepConfigs(Predicate<? super ResConfig> keepConfigs) {
this.keepConfigs = keepConfigs;
}
public Predicate<? super ResourceEntry> getKeepEntries() {
Predicate<? super ResourceEntry> keepEntries = this.getKeepEntriesInternal();
Predicate<? super ResourceName> keepResourceNames = this.getKeepResourceNames();
Predicate<? super ResourceEntry> result = keepEntries;
if(keepResourceNames != null) {
result = (Predicate<ResourceEntry>) resourceEntry -> {
if(keepEntries.test(resourceEntry)) {
return true;
}
ResourceName resourceName = resourceEntry.toResourceName();
if(resourceName != null) {
return keepResourceNames.test(resourceName);
}
return false;
};
}
return result;
}
private Predicate<? super ResourceEntry> getKeepEntriesInternal() {
Predicate<? super ResourceEntry> keepEntries = this.keepEntries;
if(keepEntries == null) {
keepEntries = resourceEntry -> !resourceEntry.isEmpty();
this.keepEntries = keepEntries;
}
return keepEntries;
}
public void setKeepEntries(Predicate<? super ResourceEntry> keepEntries) {
this.keepEntries = keepEntries;
}

public Predicate<? super ResourceName> getKeepResourceNames() {
return keepResourceNames;
}
public void setKeepResourceNames(Predicate<? super ResourceName> keepResourceNames) {
this.keepResourceNames = keepResourceNames;
}

public ResourceEntry resolveUndeclared(PackageBlock currentContext, ResourceEntry undeclared) {
ResourceEntry entry = undeclared.getLast();
String name = entry.getName();
Expand Down
100 changes: 100 additions & 0 deletions src/main/java/com/reandroid/common/DiagnosticMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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.reandroid.common;

public interface DiagnosticMessage {
Type type();
default String getTag() {
return null;
}
default DiagnosticSource getSource() {
return null;
}

class StringMessage implements DiagnosticMessage {

private final Type type;
private final DiagnosticSource source;
private final String tag;
private final String message;

public StringMessage(Type type, DiagnosticSource source, String tag, String message) {
this.type = type;
this.source = source;
this.tag = tag;
this.message = message;
}
public StringMessage(Type type, String tag, String message) {
this(type, null, tag, message);
}
public StringMessage(Type type, String message) {
this(type, null, null, message);
}
@Override
public Type type() {
return type;
}
@Override
public DiagnosticSource getSource() {
return source;
}
@Override
public String getTag() {
return tag;
}

public String getMessage() {
return message;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(type().getName());
builder.append(": ");
String tag = getTag();
if(tag != null) {
builder.append(tag);
builder.append(" : ");
}
DiagnosticSource source = getSource();
if(source != null) {
builder.append(source);
builder.append(", ");
}
builder.append(getMessage());
return builder.toString();
}
}

enum Type {

INFO("I"),
WARN("W"),
ERROR("E"),
VERBOSE("V"),
DEBUG("D");

String simpleName;

Type(String simpleName) {
this.simpleName = simpleName;
}
public String getName() {
return simpleName;
}
}
}
95 changes: 95 additions & 0 deletions src/main/java/com/reandroid/common/DiagnosticSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* 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.reandroid.common;

import com.reandroid.utils.StringsUtil;

public class DiagnosticSource {

private DiagnosticSource parent;
private final String name;
private String separator = ":";

public DiagnosticSource(DiagnosticSource parent, String name) {
this.parent = parent;
this.name = name;
}

public String getName() {
return name;
}
public DiagnosticSource getParent() {
return parent;
}
public void setParent(DiagnosticSource parent) {
this.parent = parent;
}

public void setSeparator(String separator) {
this.separator = separator;
}
public String getSeparator() {
String separator = this.separator;
if(separator == null) {
separator = StringsUtil.EMPTY;
}
return separator;
}

public boolean isRoot() {
return getParent() == null;
}
public DiagnosticSource[] toArray() {
int count = 0;
DiagnosticSource source = this;
while (!source.isRoot()) {
count ++;
source = source.getParent();
}
DiagnosticSource[] result = new DiagnosticSource[count];
count = count - 1;
source = this;
while (count >= 0) {
result[count] = source;
source = source.getParent();
count --;
}
return result;
}

public DiagnosticSource createChild(String name) {
return new DiagnosticSource(this, name);
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
DiagnosticSource[] sources = toArray();
int length = sources.length;
for(int i = 0; i < length; i++) {
DiagnosticSource source = sources[i];
if(i != 0) {
builder.append(source.getSeparator());
}
builder.append(source.getName());
}
return builder.toString();
}

public static DiagnosticSource newRoot() {
return new DiagnosticSource(null, StringsUtil.EMPTY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,12 @@
*/
package com.reandroid.common;

public class IntegerArrayConverter<T> implements ArraySupplier<T>{
private final IntegerArray integerArray;
private final ArraySupplier<? extends T> supplier;

public IntegerArrayConverter(IntegerArray integerArray, ArraySupplier<? extends T> supplier){
this.integerArray = integerArray;
this.supplier = supplier;
}

@Override
public T get(int i){
return supplier.get(integerArray.get(i));
public interface DiagnosticsReporter {
void report(DiagnosticMessage message);
default boolean isVerboseEnabled() {
return false;
}
@Override
public int getCount(){
return integerArray.size();
default boolean isDebugEnabled() {
return false;
}
}
Loading

0 comments on commit f41a663

Please sign in to comment.