mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-29 22:04:25 +02:00
continent method for framework
This commit is contained in:
parent
17a9e18fd2
commit
f1f6300e64
@ -1,270 +1,279 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.apk;
|
package com.reandroid.apk;
|
||||||
|
|
||||||
import com.reandroid.archive.APKArchive;
|
import com.reandroid.archive.APKArchive;
|
||||||
import com.reandroid.archive.ByteInputSource;
|
import com.reandroid.archive.ByteInputSource;
|
||||||
import com.reandroid.archive.InputSource;
|
import com.reandroid.archive.InputSource;
|
||||||
import com.reandroid.archive.InputSourceUtil;
|
import com.reandroid.archive.InputSourceUtil;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.archive2.Archive;
|
||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.chunk.xml.ResXmlAttribute;
|
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||||
import com.reandroid.arsc.chunk.xml.ResXmlElement;
|
import com.reandroid.arsc.chunk.xml.ResXmlAttribute;
|
||||||
import com.reandroid.arsc.util.FrameworkTable;
|
import com.reandroid.arsc.chunk.xml.ResXmlElement;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.util.FrameworkTable;
|
||||||
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Produces compressed framework apk by removing irrelevant files and entries,
|
* Produces compressed framework apk by removing irrelevant files and entries,
|
||||||
* basically it keeps only resources.arsc and AndroidManifest.xml
|
* basically it keeps only resources.arsc and AndroidManifest.xml
|
||||||
*/
|
*/
|
||||||
public class FrameworkApk extends ApkModule{
|
public class FrameworkApk extends ApkModule{
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
private int versionCode;
|
private int versionCode;
|
||||||
private String versionName;
|
private String versionName;
|
||||||
private String packageName;
|
private String packageName;
|
||||||
private boolean mOptimizing;
|
private boolean mOptimizing;
|
||||||
private boolean mDestroyed;
|
private boolean mDestroyed;
|
||||||
public FrameworkApk(String moduleName, APKArchive apkArchive) {
|
public FrameworkApk(String moduleName, APKArchive apkArchive) {
|
||||||
super(moduleName, apkArchive);
|
super(moduleName, apkArchive);
|
||||||
super.setLoadDefaultFramework(false);
|
super.setLoadDefaultFramework(false);
|
||||||
}
|
}
|
||||||
public FrameworkApk(APKArchive apkArchive) {
|
public FrameworkApk(APKArchive apkArchive) {
|
||||||
this("framework", apkArchive);
|
this("framework", apkArchive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy(){
|
public void destroy(){
|
||||||
synchronized (mLock){
|
synchronized (mLock){
|
||||||
this.versionCode = -1;
|
this.versionCode = -1;
|
||||||
this.versionName = "-1";
|
this.versionName = "-1";
|
||||||
this.packageName = "destroyed";
|
this.packageName = "destroyed";
|
||||||
super.destroy();
|
super.destroy();
|
||||||
this.mDestroyed = true;
|
this.mDestroyed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public boolean isDestroyed() {
|
public boolean isDestroyed() {
|
||||||
synchronized (mLock){
|
synchronized (mLock){
|
||||||
if(!mDestroyed){
|
if(!mDestroyed){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(hasTableBlock()){
|
if(hasTableBlock()){
|
||||||
this.versionCode = 0;
|
this.versionCode = 0;
|
||||||
this.versionName = null;
|
this.versionName = null;
|
||||||
this.packageName = null;
|
this.packageName = null;
|
||||||
mDestroyed = false;
|
mDestroyed = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersionCode() {
|
public int getVersionCode() {
|
||||||
if(this.versionCode == 0){
|
if(this.versionCode == 0){
|
||||||
initValues();
|
initValues();
|
||||||
}
|
}
|
||||||
return this.versionCode;
|
return this.versionCode;
|
||||||
}
|
}
|
||||||
public String getVersionName() {
|
public String getVersionName() {
|
||||||
if(this.versionName == null){
|
if(this.versionName == null){
|
||||||
initValues();
|
initValues();
|
||||||
}
|
}
|
||||||
return this.versionName;
|
return this.versionName;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
if(this.packageName == null){
|
if(this.packageName == null){
|
||||||
initValues();
|
initValues();
|
||||||
}
|
}
|
||||||
return this.packageName;
|
return this.packageName;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setPackageName(String packageName) {
|
public void setPackageName(String packageName) {
|
||||||
super.setPackageName(packageName);
|
super.setPackageName(packageName);
|
||||||
this.packageName = null;
|
this.packageName = null;
|
||||||
}
|
}
|
||||||
private void initValues() {
|
private void initValues() {
|
||||||
if(hasAndroidManifestBlock()){
|
if(hasAndroidManifestBlock()){
|
||||||
AndroidManifestBlock manifest = getAndroidManifestBlock();
|
AndroidManifestBlock manifest = getAndroidManifestBlock();
|
||||||
Integer code = manifest.getVersionCode();
|
Integer code = manifest.getVersionCode();
|
||||||
if(code!=null){
|
if(code!=null){
|
||||||
this.versionCode = code;
|
this.versionCode = code;
|
||||||
}
|
}
|
||||||
if(this.versionName == null){
|
if(this.versionName == null){
|
||||||
this.versionName = manifest.getVersionName();
|
this.versionName = manifest.getVersionName();
|
||||||
}
|
}
|
||||||
if(this.packageName == null){
|
if(this.packageName == null){
|
||||||
this.packageName = manifest.getPackageName();
|
this.packageName = manifest.getPackageName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(hasTableBlock()){
|
if(hasTableBlock()){
|
||||||
FrameworkTable table = getTableBlock();
|
FrameworkTable table = getTableBlock();
|
||||||
if(this.versionCode == 0 && table.isOptimized()){
|
if(this.versionCode == 0 && table.isOptimized()){
|
||||||
int version = table.getVersionCode();
|
int version = table.getVersionCode();
|
||||||
if(version!=0){
|
if(version!=0){
|
||||||
versionCode = version;
|
versionCode = version;
|
||||||
if(this.versionName == null){
|
if(this.versionName == null){
|
||||||
this.versionName = String.valueOf(version);
|
this.versionName = String.valueOf(version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.packageName == null){
|
if(this.packageName == null){
|
||||||
PackageBlock packageBlock = table.pickOne();
|
PackageBlock packageBlock = table.pickOne();
|
||||||
if(packageBlock!=null){
|
if(packageBlock!=null){
|
||||||
this.packageName = packageBlock.getName();
|
this.packageName = packageBlock.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setManifest(AndroidManifestBlock manifestBlock){
|
public void setManifest(AndroidManifestBlock manifestBlock){
|
||||||
synchronized (mLock){
|
synchronized (mLock){
|
||||||
super.setManifest(manifestBlock);
|
super.setManifest(manifestBlock);
|
||||||
this.versionCode = 0;
|
this.versionCode = 0;
|
||||||
this.versionName = null;
|
this.versionName = null;
|
||||||
this.packageName = null;
|
this.packageName = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setTableBlock(TableBlock tableBlock){
|
public void setTableBlock(TableBlock tableBlock){
|
||||||
synchronized (mLock){
|
synchronized (mLock){
|
||||||
super.setTableBlock(tableBlock);
|
super.setTableBlock(tableBlock);
|
||||||
this.versionCode = 0;
|
this.versionCode = 0;
|
||||||
this.versionName = null;
|
this.versionName = null;
|
||||||
this.packageName = null;
|
this.packageName = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public FrameworkTable getTableBlock() {
|
public FrameworkTable getTableBlock() {
|
||||||
return (FrameworkTable) super.getTableBlock();
|
return (FrameworkTable) super.getTableBlock();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
FrameworkTable loadTableBlock() throws IOException {
|
FrameworkTable loadTableBlock() throws IOException {
|
||||||
APKArchive archive=getApkArchive();
|
APKArchive archive=getApkArchive();
|
||||||
InputSource inputSource = archive.getInputSource(TableBlock.FILE_NAME);
|
InputSource inputSource = archive.getInputSource(TableBlock.FILE_NAME);
|
||||||
if(inputSource==null){
|
if(inputSource==null){
|
||||||
throw new IOException("Entry not found: "+TableBlock.FILE_NAME);
|
throw new IOException("Entry not found: "+TableBlock.FILE_NAME);
|
||||||
}
|
}
|
||||||
InputStream inputStream = inputSource.openStream();
|
InputStream inputStream = inputSource.openStream();
|
||||||
FrameworkTable frameworkTable=FrameworkTable.load(inputStream);
|
FrameworkTable frameworkTable=FrameworkTable.load(inputStream);
|
||||||
frameworkTable.setApkFile(this);
|
frameworkTable.setApkFile(this);
|
||||||
|
|
||||||
BlockInputSource<FrameworkTable> blockInputSource=new BlockInputSource<>(inputSource.getName(), frameworkTable);
|
BlockInputSource<FrameworkTable> blockInputSource=new BlockInputSource<>(inputSource.getName(), frameworkTable);
|
||||||
blockInputSource.setMethod(inputSource.getMethod());
|
blockInputSource.setMethod(inputSource.getMethod());
|
||||||
blockInputSource.setSort(inputSource.getSort());
|
blockInputSource.setSort(inputSource.getSort());
|
||||||
archive.add(blockInputSource);
|
archive.add(blockInputSource);
|
||||||
return frameworkTable;
|
return frameworkTable;
|
||||||
}
|
}
|
||||||
public void optimize(){
|
public void optimize(){
|
||||||
synchronized (mLock){
|
synchronized (mLock){
|
||||||
if(mOptimizing){
|
if(mOptimizing){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!hasTableBlock()){
|
if(!hasTableBlock()){
|
||||||
mOptimizing = false;
|
mOptimizing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FrameworkTable frameworkTable = getTableBlock();
|
FrameworkTable frameworkTable = getTableBlock();
|
||||||
if(frameworkTable.isOptimized()){
|
if(frameworkTable.isOptimized()){
|
||||||
mOptimizing = false;
|
mOptimizing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FrameworkOptimizer optimizer = new FrameworkOptimizer(this);
|
FrameworkOptimizer optimizer = new FrameworkOptimizer(this);
|
||||||
optimizer.optimize();
|
optimizer.optimize();
|
||||||
mOptimizing = false;
|
mOptimizing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
if(isDestroyed()){
|
if(isDestroyed()){
|
||||||
return "destroyed";
|
return "destroyed";
|
||||||
}
|
}
|
||||||
String pkg = getPackageName();
|
String pkg = getPackageName();
|
||||||
if(pkg==null){
|
if(pkg==null){
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return pkg + "-" + getVersionCode();
|
return pkg + "-" + getVersionCode();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int hashCode(){
|
public int hashCode(){
|
||||||
return Objects.hash(getClass(), getName());
|
return Objects.hash(getClass(), getName());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj){
|
public boolean equals(Object obj){
|
||||||
if(obj==this){
|
if(obj==this){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(getClass()!=obj.getClass()){
|
if(getClass()!=obj.getClass()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
FrameworkApk other = (FrameworkApk) obj;
|
FrameworkApk other = (FrameworkApk) obj;
|
||||||
return getName().equals(other.getName());
|
return getName().equals(other.getName());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
public static FrameworkApk loadApkFile(File apkFile) throws IOException {
|
public static FrameworkApk loadApkFile(File apkFile) throws IOException {
|
||||||
APKArchive archive=APKArchive.loadZippedApk(apkFile);
|
Archive archive = new Archive(apkFile);
|
||||||
return new FrameworkApk(archive);
|
APKArchive apkArchive = new APKArchive(archive.mapEntrySource());
|
||||||
}
|
return new FrameworkApk(apkArchive);
|
||||||
public static FrameworkApk loadApkFile(File apkFile, String moduleName) throws IOException {
|
}
|
||||||
APKArchive archive=APKArchive.loadZippedApk(apkFile);
|
public static FrameworkApk loadApkFile(File apkFile, String moduleName) throws IOException {
|
||||||
return new FrameworkApk(moduleName, archive);
|
Archive archive = new Archive(apkFile);
|
||||||
}
|
APKArchive apkArchive = new APKArchive(archive.mapEntrySource());
|
||||||
public static boolean isFramework(ApkModule apkModule) {
|
return new FrameworkApk(moduleName, apkArchive);
|
||||||
if(!apkModule.hasAndroidManifestBlock()){
|
}
|
||||||
return false;
|
public static boolean isFramework(ApkModule apkModule) {
|
||||||
}
|
if(!apkModule.hasAndroidManifestBlock()){
|
||||||
return isFramework(apkModule.getAndroidManifestBlock());
|
return false;
|
||||||
}
|
}
|
||||||
public static boolean isFramework(AndroidManifestBlock manifestBlock){
|
return isFramework(apkModule.getAndroidManifestBlock());
|
||||||
ResXmlElement root = manifestBlock.getManifestElement();
|
}
|
||||||
ResXmlAttribute attribute = root.getStartElement()
|
public static boolean isFramework(AndroidManifestBlock manifestBlock){
|
||||||
.searchAttributeByName(AndroidManifestBlock.NAME_coreApp);
|
ResXmlElement root = manifestBlock.getManifestElement();
|
||||||
if(attribute==null || attribute.getValueType()!= ValueType.INT_BOOLEAN){
|
ResXmlAttribute attribute = root.getStartElement()
|
||||||
return false;
|
.searchAttributeByName(AndroidManifestBlock.NAME_coreApp);
|
||||||
}
|
if(attribute==null || attribute.getValueType()!= ValueType.INT_BOOLEAN){
|
||||||
return attribute.getValueAsBoolean();
|
return false;
|
||||||
}
|
}
|
||||||
public static FrameworkApk loadApkBuffer(InputStream inputStream) throws IOException{
|
return attribute.getValueAsBoolean();
|
||||||
return loadApkBuffer("framework", inputStream);
|
}
|
||||||
}
|
public static FrameworkApk loadApkBuffer(InputStream inputStream) throws IOException{
|
||||||
public static FrameworkApk loadApkBuffer(String moduleName, InputStream inputStream) throws IOException {
|
return loadApkBuffer("framework", inputStream);
|
||||||
APKArchive archive = new APKArchive();
|
}
|
||||||
FrameworkApk frameworkApk = new FrameworkApk(moduleName, archive);
|
public static FrameworkApk loadApkBuffer(String moduleName, InputStream inputStream) throws IOException {
|
||||||
Map<String, ByteInputSource> inputSourceMap = InputSourceUtil.mapInputStreamAsBuffer(inputStream);
|
APKArchive archive = new APKArchive();
|
||||||
ByteInputSource source = inputSourceMap.get(TableBlock.FILE_NAME);
|
FrameworkApk frameworkApk = new FrameworkApk(moduleName, archive);
|
||||||
FrameworkTable tableBlock = new FrameworkTable();
|
Map<String, ByteInputSource> inputSourceMap = InputSourceUtil.mapInputStreamAsBuffer(inputStream);
|
||||||
if(source!=null){
|
ByteInputSource source = inputSourceMap.get(TableBlock.FILE_NAME);
|
||||||
tableBlock.readBytes(source.openStream());
|
FrameworkTable tableBlock = new FrameworkTable();
|
||||||
}
|
if(source!=null){
|
||||||
frameworkApk.setTableBlock(tableBlock);
|
tableBlock.readBytes(source.openStream());
|
||||||
|
}
|
||||||
|
frameworkApk.setTableBlock(tableBlock);
|
||||||
|
|
||||||
AndroidManifestBlock manifestBlock = new AndroidManifestBlock();
|
AndroidManifestBlock manifestBlock = new AndroidManifestBlock();
|
||||||
source = inputSourceMap.get(AndroidManifestBlock.FILE_NAME);
|
source = inputSourceMap.get(AndroidManifestBlock.FILE_NAME);
|
||||||
if(source!=null){
|
if(source!=null){
|
||||||
manifestBlock.readBytes(source.openStream());
|
manifestBlock.readBytes(source.openStream());
|
||||||
}
|
}
|
||||||
frameworkApk.setManifest(manifestBlock);
|
frameworkApk.setManifest(manifestBlock);
|
||||||
archive.addAll(inputSourceMap.values());
|
archive.addAll(inputSourceMap.values());
|
||||||
return frameworkApk;
|
return frameworkApk;
|
||||||
}
|
}
|
||||||
}
|
public static void optimize(File in, File out, APKLogger apkLogger) throws IOException{
|
||||||
|
FrameworkApk frameworkApk = FrameworkApk.loadApkFile(in);
|
||||||
|
frameworkApk.setAPKLogger(apkLogger);
|
||||||
|
frameworkApk.optimize();
|
||||||
|
frameworkApk.writeApk(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -413,7 +413,7 @@ public class FrameworkTable extends TableBlock {
|
|||||||
if(headerBlock.getChunkType()!= ChunkType.TABLE){
|
if(headerBlock.getChunkType()!= ChunkType.TABLE){
|
||||||
return super.toString();
|
return super.toString();
|
||||||
}
|
}
|
||||||
if(!isOptimized()){
|
if(!mOptimized){
|
||||||
return "Unoptimized: "+super.toString();
|
return "Unoptimized: "+super.toString();
|
||||||
}
|
}
|
||||||
return getFrameworkName()+'-'+getVersionCode();
|
return getFrameworkName()+'-'+getVersionCode();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user