soul-browser/sources/java/com/bumptech/glide/integration/webp/WebpBitmapFactory.java
KaKi87 550ddb0413
Decompile and recreate Soul Browser v1.4.85 with APK CI builds (#1)
* Decompile and recreate Soul Browser v1.4.85 with APK CI builds

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix CI build: include bundled google.jks and remove PR trigger

The apktool build failed in CI because app/unknown/.../google.jks was
excluded by the *.jks gitignore rule. Whitelist app-bundled JKS files
and commit the missing resource.

Also remove the redundant pull_request workflow trigger.

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Change package ID to com.github.kaki87.soulbrowser

Rename the application ID so the rebuilt APK can be installed
alongside the original Soul Browser from Google Play.

- Update AndroidManifest package, permissions, providers, and actions
- Update R class references in smali (com/github/kaki87/soulbrowser/R)
- Update shortcuts.xml targetPackage
- Rename app label to "Soul Rebuild" for easy identification

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix install compatibility: remove split APK metadata and bundle native libs

The rebuilt APK still declared requiredSplitTypes and Play Store split
metadata, causing Android to reject standalone installs as incompatible.

- Remove requiredSplitTypes and split-related manifest meta-data
- Merge native libs from all ABI splits with uncompressed storage
- Page-align before signing for extractNativeLibs=false
- Add .so to apktool doNotCompress list

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix install failure: use apksigner v2/v3 and bundle arm64 native libs

Target SDK 36 requires APK Signature Scheme v2+, but jarsigner only
produces v1 signatures, causing Android to reject the install.

- Sign with apksigner (v1+v2+v3) instead of jarsigner
- Add arm64-v8a native libraries from universal Soul Browser 1.4.79
- Set extractNativeLibs=true for reliable sideload installs
- Commit stable debug keystore for consistent signatures across builds

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Add committed debug keystore for consistent APK signatures

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix startup crash: use original classes2.dex desugar libraries

Apktool recompiles smali_classes2 into a broken classes2.dex, causing
ClassNotFoundException for j$.com.android.tools.r8.a at ML Kit init.

Inject the original classes2.dex (Java 8+ desugar libs) after apktool
build instead of using the recompiled version.

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix missing drawable resources from density split APKs

The base APK is an app bundle module; density-specific drawables like
seek_thumb_nor_b live in config.xhdpi.apk and were missing after rebuild,
causing Resources$NotFoundException at runtime.

- Merge non-9-patch resources from split APKs before apktool build
- Sync public.xml IDs from R smali only when backing files exist
- Add 713 density-specific resource IDs to public.xml

Co-authored-by: KaKi87 <KaKi87@pm.me>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-08-10 16:07:14 +02:00

368 lines
14 KiB
Java

package com.bumptech.glide.integration.webp;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.util.TypedValue;
import androidx.annotation.Keep;
import com.bumptech.glide.integration.webp.WebpHeaderParser;
import java.io.BufferedInputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@Keep
/* loaded from: classes.dex */
public class WebpBitmapFactory {
private static final int IN_TEMP_BUFFER_SIZE = 8192;
private static final int MAX_WEBP_HEADER_SIZE = 21;
public static boolean sUseSystemDecoder = true;
static {
System.loadLibrary("glide-webp");
}
@Keep
private static Bitmap createBitmap(int i, int i2, BitmapFactory.Options options) {
Bitmap bitmap;
if (options != null && (bitmap = options.inBitmap) != null && bitmap.isMutable()) {
Bitmap bitmap2 = options.inBitmap;
if (bitmap2.getWidth() == i && bitmap2.getHeight() == i2 && bitmap2.getConfig() == options.inPreferredConfig) {
bitmap2.setHasAlpha(true);
bitmap2.eraseColor(0);
return bitmap2;
}
}
Bitmap createBitmap = Bitmap.createBitmap(i, i2, Bitmap.Config.ARGB_8888);
createBitmap.setHasAlpha(true);
createBitmap.eraseColor(0);
return createBitmap;
}
public static Bitmap decodeByteArray(byte[] bArr, int i, int i2) {
return decodeByteArray(bArr, i, i2, null);
}
public static Bitmap decodeFile(String str) {
return decodeFile(str, null);
}
public static Bitmap decodeFileDescriptor(FileDescriptor fileDescriptor) {
return decodeFileDescriptor(fileDescriptor, null, null);
}
public static Bitmap decodeResource(Resources resources, int i) {
return decodeResource(resources, i, null);
}
public static Bitmap decodeResourceStream(Resources resources, TypedValue typedValue, InputStream inputStream, Rect rect, BitmapFactory.Options options) {
if (options == null) {
options = new BitmapFactory.Options();
}
if (options.inDensity == 0 && typedValue != null) {
int i = typedValue.density;
if (i == 0) {
options.inDensity = 160;
} else if (i != 65535) {
options.inDensity = i;
}
}
if (options.inTargetDensity == 0 && resources != null) {
options.inTargetDensity = resources.getDisplayMetrics().densityDpi;
}
return decodeStream(inputStream, rect, options);
}
public static Bitmap decodeStream(InputStream inputStream) {
return decodeStream(inputStream, null, null);
}
private static byte[] getImageHeader(InputStream inputStream) {
if (!inputStream.markSupported()) {
inputStream = new BufferedInputStream(inputStream, 21);
}
inputStream.mark(21);
byte[] bArr = new byte[21];
try {
inputStream.read(bArr, 0, 21);
inputStream.reset();
return bArr;
} catch (IOException unused) {
return null;
}
}
private static byte[] getInTempStorageFromOptions(BitmapFactory.Options options) {
byte[] bArr;
if (options != null && (bArr = options.inTempStorage) != null) {
return bArr;
}
return new byte[8192];
}
private static float getScaleFromOptions(BitmapFactory.Options options) {
float f = 1.0f;
if (options != null) {
int i = options.inSampleSize;
if (i > 1) {
f = 1.0f / i;
}
if (options.inScaled) {
int i2 = options.inDensity;
int i3 = options.inTargetDensity;
int i4 = options.inScreenDensity;
if (i2 != 0 && i3 != 0 && i2 != i4) {
return (i3 / i2) * f;
}
}
}
return f;
}
private static native Bitmap nativeDecodeByteArray(byte[] bArr, int i, int i2, BitmapFactory.Options options, float f, byte[] bArr2);
private static native Bitmap nativeDecodeStream(InputStream inputStream, BitmapFactory.Options options, float f, byte[] bArr);
private static void setDefaultPadding(Rect rect) {
if (rect != null) {
rect.top = -1;
rect.left = -1;
rect.bottom = -1;
rect.right = -1;
}
}
private static void setDensityFromOptions(Bitmap bitmap, BitmapFactory.Options options) {
if (bitmap != null && options != null) {
int i = options.inDensity;
if (i != 0) {
bitmap.setDensity(i);
int i2 = options.inTargetDensity;
if (i2 != 0 && i != i2 && i != options.inScreenDensity && options.inScaled) {
bitmap.setDensity(i2);
return;
}
return;
}
if (options.inBitmap != null) {
bitmap.setDensity(160);
}
}
}
@Keep
private static boolean setOutDimensions(BitmapFactory.Options options, int i, int i2) {
if (options != null) {
options.outWidth = i;
options.outHeight = i2;
return options.inJustDecodeBounds;
}
return false;
}
private static void setWebpBitmapOptions(Bitmap bitmap, BitmapFactory.Options options) {
setDensityFromOptions(bitmap, options);
if (options != null) {
options.outMimeType = "image/webp";
}
}
public static boolean webpSupportRequired(byte[] bArr, int i, int i2) {
WebpHeaderParser.WebpImageType webpImageType;
try {
webpImageType = WebpHeaderParser.a(new WebpHeaderParser.ByteArrayReader(bArr, i, i2));
} catch (IOException unused) {
webpImageType = WebpHeaderParser.WebpImageType.k;
}
if (sUseSystemDecoder) {
return false;
}
return WebpHeaderParser.d(webpImageType);
}
private static InputStream wrapToMarkSupportedStream(InputStream inputStream) {
if (!inputStream.markSupported()) {
return new BufferedInputStream(inputStream, 8192);
}
return inputStream;
}
public static Bitmap decodeByteArray(byte[] bArr, int i, int i2, BitmapFactory.Options options) {
if ((i | i2) >= 0 && bArr.length >= i + i2) {
if (webpSupportRequired(bArr, i, i2)) {
Bitmap nativeDecodeByteArray = nativeDecodeByteArray(bArr, i, i2, options, getScaleFromOptions(options), getInTempStorageFromOptions(options));
setWebpBitmapOptions(nativeDecodeByteArray, options);
return nativeDecodeByteArray;
}
return BitmapFactory.decodeByteArray(bArr, i, i2, options);
}
throw new ArrayIndexOutOfBoundsException();
}
/* JADX WARN: Code restructure failed: missing block: B:15:0x002a, code lost:
if (r2 == null) goto L18;
*/
/* JADX WARN: Removed duplicated region for block: B:21:0x0030 A[EXC_TOP_SPLITTER, SYNTHETIC] */
/*
Code decompiled incorrectly, please refer to instructions dump.
To view partially-correct add '--show-bad-code' argument
*/
public static android.graphics.Bitmap decodeFile(java.lang.String r4, android.graphics.BitmapFactory.Options r5) {
/*
java.lang.String r0 = "Unable to decode stream: "
r1 = 0
java.io.FileInputStream r2 = new java.io.FileInputStream // Catch: java.lang.Throwable -> L15 java.lang.Exception -> L17
r2.<init>(r4) // Catch: java.lang.Throwable -> L15 java.lang.Exception -> L17
android.graphics.Bitmap r1 = decodeStream(r2, r1, r5) // Catch: java.lang.Throwable -> L10 java.lang.Exception -> L13
Lc:
r2.close() // Catch: java.io.IOException -> L2d
goto L2d
L10:
r4 = move-exception
r1 = r2
goto L2e
L13:
r4 = move-exception
goto L19
L15:
r4 = move-exception
goto L2e
L17:
r4 = move-exception
r2 = r1
L19:
java.lang.String r5 = "WebpBitmapFactory"
java.lang.StringBuilder r3 = new java.lang.StringBuilder // Catch: java.lang.Throwable -> L10
r3.<init>(r0) // Catch: java.lang.Throwable -> L10
r3.append(r4) // Catch: java.lang.Throwable -> L10
java.lang.String r4 = r3.toString() // Catch: java.lang.Throwable -> L10
android.util.Log.e(r5, r4) // Catch: java.lang.Throwable -> L10
if (r2 == 0) goto L2d
goto Lc
L2d:
return r1
L2e:
if (r1 == 0) goto L33
r1.close() // Catch: java.io.IOException -> L33
L33:
throw r4
*/
throw new UnsupportedOperationException("Method not decompiled: com.bumptech.glide.integration.webp.WebpBitmapFactory.decodeFile(java.lang.String, android.graphics.BitmapFactory$Options):android.graphics.Bitmap");
}
public static Bitmap decodeFileDescriptor(FileDescriptor fileDescriptor, Rect rect, BitmapFactory.Options options) {
Bitmap decodeFileDescriptor;
InputStream wrapToMarkSupportedStream = wrapToMarkSupportedStream(new FileInputStream(fileDescriptor));
try {
if (webpSupportRequired(getImageHeader(wrapToMarkSupportedStream), 0, 21)) {
decodeFileDescriptor = nativeDecodeStream(wrapToMarkSupportedStream, options, getScaleFromOptions(options), getInTempStorageFromOptions(options));
setWebpBitmapOptions(decodeFileDescriptor, options);
setDefaultPadding(rect);
} else {
decodeFileDescriptor = BitmapFactory.decodeFileDescriptor(fileDescriptor, rect, options);
}
try {
wrapToMarkSupportedStream.close();
} catch (Throwable unused) {
}
return decodeFileDescriptor;
} catch (Throwable th) {
try {
wrapToMarkSupportedStream.close();
} catch (Throwable unused2) {
}
throw th;
}
}
/* JADX WARN: Code restructure failed: missing block: B:12:0x0034, code lost:
throw new java.lang.IllegalArgumentException("Problem decoding into existing bitmap");
*/
/* JADX WARN: Code restructure failed: missing block: B:14:0x0035, code lost:
return r0;
*/
/* JADX WARN: Code restructure failed: missing block: B:16:0x0010, code lost:
r3.close();
*/
/* JADX WARN: Code restructure failed: missing block: B:21:0x0021, code lost:
if (r3 == null) goto L18;
*/
/* JADX WARN: Code restructure failed: missing block: B:6:0x000e, code lost:
if (r3 != null) goto L29;
*/
/* JADX WARN: Code restructure failed: missing block: B:7:0x0024, code lost:
if (r0 != null) goto L25;
*/
/*
Code decompiled incorrectly, please refer to instructions dump.
To view partially-correct add '--show-bad-code' argument
*/
public static android.graphics.Bitmap decodeResource(android.content.res.Resources r2, int r3, android.graphics.BitmapFactory.Options r4) {
/*
r0 = 0
android.util.TypedValue r1 = new android.util.TypedValue // Catch: java.lang.Throwable -> L17 java.lang.Exception -> L19
r1.<init>() // Catch: java.lang.Throwable -> L17 java.lang.Exception -> L19
java.io.InputStream r3 = r2.openRawResource(r3, r1) // Catch: java.lang.Throwable -> L17 java.lang.Exception -> L19
android.graphics.Bitmap r0 = decodeResourceStream(r2, r1, r3, r0, r4) // Catch: java.lang.Throwable -> L14 java.lang.Exception -> L21
if (r3 == 0) goto L24
L10:
r3.close() // Catch: java.io.IOException -> L24
goto L24
L14:
r2 = move-exception
r0 = r3
goto L1b
L17:
r2 = move-exception
goto L1b
L19:
r3 = r0
goto L21
L1b:
if (r0 == 0) goto L20
r0.close() // Catch: java.io.IOException -> L20
L20:
throw r2
L21:
if (r3 == 0) goto L24
goto L10
L24:
if (r0 != 0) goto L35
if (r4 == 0) goto L35
android.graphics.Bitmap r2 = r4.inBitmap
if (r2 != 0) goto L2d
goto L35
L2d:
java.lang.IllegalArgumentException r2 = new java.lang.IllegalArgumentException
java.lang.String r3 = "Problem decoding into existing bitmap"
r2.<init>(r3)
throw r2
L35:
return r0
*/
throw new UnsupportedOperationException("Method not decompiled: com.bumptech.glide.integration.webp.WebpBitmapFactory.decodeResource(android.content.res.Resources, int, android.graphics.BitmapFactory$Options):android.graphics.Bitmap");
}
public static Bitmap decodeStream(InputStream inputStream, Rect rect, BitmapFactory.Options options) {
if (inputStream == null) {
return null;
}
InputStream wrapToMarkSupportedStream = wrapToMarkSupportedStream(inputStream);
if (webpSupportRequired(getImageHeader(wrapToMarkSupportedStream), 0, 21)) {
Bitmap nativeDecodeStream = nativeDecodeStream(wrapToMarkSupportedStream, options, getScaleFromOptions(options), getInTempStorageFromOptions(options));
setWebpBitmapOptions(nativeDecodeStream, options);
setDefaultPadding(rect);
return nativeDecodeStream;
}
return BitmapFactory.decodeStream(wrapToMarkSupportedStream, rect, options);
}
}