soul-browser/sources/java/androidx/mediarouter/media/PlatformMediaRouter1RouteProvider.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

422 lines
16 KiB
Java

package androidx.mediarouter.media;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentFilter;
import android.media.MediaRouter;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import androidx.annotation.RequiresApi;
import androidx.mediarouter.R;
import androidx.mediarouter.media.MediaRouteDescriptor;
import androidx.mediarouter.media.MediaRouteProvider;
import androidx.mediarouter.media.MediaRouteProviderDescriptor;
import androidx.mediarouter.media.MediaRouter;
import androidx.mediarouter.media.MediaRouterUtils;
import com.google.android.gms.ads.RequestConfiguration;
import java.util.ArrayList;
import java.util.Locale;
/* loaded from: classes.dex */
abstract class PlatformMediaRouter1RouteProvider extends MediaRouteProvider {
@RequiresApi
/* loaded from: classes.dex */
public static class Api24Impl extends JellybeanMr2Impl {
@Override // androidx.mediarouter.media.PlatformMediaRouter1RouteProvider.JellybeanMr2Impl
public final void n(JellybeanMr2Impl.SystemRouteRecord systemRouteRecord, MediaRouteDescriptor.Builder builder) {
super.n(systemRouteRecord, builder);
builder.f1359a.putInt("deviceType", systemRouteRecord.f1398a.getDeviceType());
}
}
/* loaded from: classes.dex */
public static class JellybeanMr2Impl extends PlatformMediaRouter1RouteProvider implements MediaRouterUtils.Callback, MediaRouterUtils.VolumeCallback {
public static final ArrayList w;
public static final ArrayList x;
public final SyncCallback m;
public final android.media.MediaRouter n;
public final MediaRouter.Callback o;
public final MediaRouter.VolumeCallback p;
public final MediaRouter.RouteCategory q;
public int r;
public boolean s;
public boolean t;
public final ArrayList u;
public final ArrayList v;
/* loaded from: classes.dex */
public static final class SystemRouteController extends MediaRouteProvider.RouteController {
/* renamed from: a, reason: collision with root package name */
public final MediaRouter.RouteInfo f1397a;
public SystemRouteController(MediaRouter.RouteInfo routeInfo) {
this.f1397a = routeInfo;
}
@Override // androidx.mediarouter.media.MediaRouteProvider.RouteController
public final void f(int i) {
this.f1397a.requestSetVolume(i);
}
@Override // androidx.mediarouter.media.MediaRouteProvider.RouteController
public final void i(int i) {
this.f1397a.requestUpdateVolume(i);
}
}
/* loaded from: classes.dex */
public static final class SystemRouteRecord {
/* renamed from: a, reason: collision with root package name */
public final MediaRouter.RouteInfo f1398a;
public final String b;
/* renamed from: c, reason: collision with root package name */
public MediaRouteDescriptor f1399c;
public SystemRouteRecord(MediaRouter.RouteInfo routeInfo, String str) {
this.f1398a = routeInfo;
this.b = str;
}
}
/* loaded from: classes.dex */
public static final class UserRouteRecord {
/* renamed from: a, reason: collision with root package name */
public final MediaRouter.RouteInfo f1400a;
public final MediaRouter.UserRouteInfo b;
public UserRouteRecord(MediaRouter.RouteInfo routeInfo, MediaRouter.UserRouteInfo userRouteInfo) {
this.f1400a = routeInfo;
this.b = userRouteInfo;
}
}
static {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addCategory("android.media.intent.category.LIVE_AUDIO");
ArrayList arrayList = new ArrayList();
w = arrayList;
arrayList.add(intentFilter);
IntentFilter intentFilter2 = new IntentFilter();
intentFilter2.addCategory("android.media.intent.category.LIVE_VIDEO");
ArrayList arrayList2 = new ArrayList();
x = arrayList2;
arrayList2.add(intentFilter2);
}
public JellybeanMr2Impl(Context context, SyncCallback syncCallback) {
super(context, new MediaRouteProvider.ProviderMetadata(new ComponentName("android", PlatformMediaRouter1RouteProvider.class.getName())));
this.u = new ArrayList();
this.v = new ArrayList();
this.m = syncCallback;
android.media.MediaRouter mediaRouter = (android.media.MediaRouter) context.getSystemService("media_router");
this.n = mediaRouter;
this.o = new MediaRouterUtils.CallbackProxy(this);
this.p = new MediaRouterUtils.VolumeCallbackProxy(this);
this.q = mediaRouter.createRouteCategory((CharSequence) context.getResources().getString(R.string.mr_user_route_category_name), false);
s();
}
public static UserRouteRecord m(MediaRouter.RouteInfo routeInfo) {
Object tag = routeInfo.getTag();
if (tag instanceof UserRouteRecord) {
return (UserRouteRecord) tag;
}
return null;
}
public static void t(UserRouteRecord userRouteRecord) {
int i;
MediaRouter.UserRouteInfo userRouteInfo = userRouteRecord.b;
MediaRouter.RouteInfo routeInfo = userRouteRecord.f1400a;
userRouteInfo.setName(routeInfo.d);
userRouteInfo.setPlaybackType(routeInfo.l);
userRouteInfo.setPlaybackStream(routeInfo.m);
userRouteInfo.setVolume(routeInfo.p);
userRouteInfo.setVolumeMax(routeInfo.q);
if (routeInfo.f() && !MediaRouter.m()) {
i = 0;
} else {
i = routeInfo.o;
}
userRouteInfo.setVolumeHandling(i);
userRouteInfo.setDescription(routeInfo.e);
}
@Override // androidx.mediarouter.media.MediaRouteProvider
public final MediaRouteProvider.RouteController b(String str) {
int j = j(str);
if (j >= 0) {
return new SystemRouteController(((SystemRouteRecord) this.u.get(j)).f1398a);
}
return null;
}
@Override // androidx.mediarouter.media.MediaRouteProvider
public final void e(MediaRouteDiscoveryRequest mediaRouteDiscoveryRequest) {
boolean z;
int i = 0;
if (mediaRouteDiscoveryRequest != null) {
mediaRouteDiscoveryRequest.a();
ArrayList c2 = mediaRouteDiscoveryRequest.b.c();
int size = c2.size();
int i2 = 0;
while (i < size) {
String str = (String) c2.get(i);
if (str.equals("android.media.intent.category.LIVE_AUDIO")) {
i2 |= 1;
} else if (str.equals("android.media.intent.category.LIVE_VIDEO")) {
i2 |= 2;
} else {
i2 |= 8388608;
}
i++;
}
z = mediaRouteDiscoveryRequest.b();
i = i2;
} else {
z = false;
}
if (this.r == i && this.s == z) {
return;
}
this.r = i;
this.s = z;
s();
}
public final boolean h(MediaRouter.RouteInfo routeInfo) {
String format;
String str;
if (m(routeInfo) != null || i(routeInfo) >= 0) {
return false;
}
if (this.n.getDefaultRoute() == routeInfo) {
format = "DEFAULT_ROUTE";
} else {
format = String.format(Locale.US, "ROUTE_%08x", Integer.valueOf(l(routeInfo).hashCode()));
}
if (j(format) >= 0) {
int i = 2;
while (true) {
Locale locale = Locale.US;
str = format + "_" + i;
if (j(str) < 0) {
break;
}
i++;
}
format = str;
}
SystemRouteRecord systemRouteRecord = new SystemRouteRecord(routeInfo, format);
MediaRouteDescriptor.Builder builder = new MediaRouteDescriptor.Builder(format, l(routeInfo));
n(systemRouteRecord, builder);
systemRouteRecord.f1399c = builder.c();
this.u.add(systemRouteRecord);
return true;
}
public final int i(MediaRouter.RouteInfo routeInfo) {
ArrayList arrayList = this.u;
int size = arrayList.size();
for (int i = 0; i < size; i++) {
if (((SystemRouteRecord) arrayList.get(i)).f1398a == routeInfo) {
return i;
}
}
return -1;
}
public final int j(String str) {
ArrayList arrayList = this.u;
int size = arrayList.size();
for (int i = 0; i < size; i++) {
if (((SystemRouteRecord) arrayList.get(i)).b.equals(str)) {
return i;
}
}
return -1;
}
public final int k(MediaRouter.RouteInfo routeInfo) {
ArrayList arrayList = this.v;
int size = arrayList.size();
for (int i = 0; i < size; i++) {
if (((UserRouteRecord) arrayList.get(i)).f1400a == routeInfo) {
return i;
}
}
return -1;
}
public final String l(MediaRouter.RouteInfo routeInfo) {
int i;
int i2;
Context context = this.f1362c;
CharSequence name = routeInfo.getName(context);
if (!TextUtils.isEmpty(name)) {
return name.toString();
}
if ((routeInfo.getSupportedTypes() & 8388608) == 0) {
if (Build.VERSION.SDK_INT >= 24) {
i = routeInfo.getDeviceType();
} else {
i = 0;
}
if (i != 1) {
if (i != 2) {
if (i != 3) {
i2 = R.string.mr_route_name_unknown;
} else {
i2 = R.string.mr_route_name_bluetooth;
}
} else {
i2 = R.string.mr_route_name_speaker;
}
} else {
i2 = R.string.mr_route_name_tv;
}
return context.getString(i2);
}
return RequestConfiguration.MAX_AD_CONTENT_RATING_UNSPECIFIED;
}
public void n(SystemRouteRecord systemRouteRecord, MediaRouteDescriptor.Builder builder) {
boolean z;
Bundle bundle = builder.f1359a;
MediaRouter.RouteInfo routeInfo = systemRouteRecord.f1398a;
int supportedTypes = routeInfo.getSupportedTypes();
if ((supportedTypes & 1) != 0) {
builder.a(w);
}
if ((supportedTypes & 2) != 0) {
builder.a(x);
}
bundle.putInt("playbackType", routeInfo.getPlaybackType());
bundle.putInt("playbackStream", routeInfo.getPlaybackStream());
bundle.putInt("volume", routeInfo.getVolume());
bundle.putInt("volumeMax", routeInfo.getVolumeMax());
bundle.putInt("volumeHandling", routeInfo.getVolumeHandling());
if ((8388608 & supportedTypes) == 0) {
z = true;
} else {
z = false;
}
bundle.putBoolean("isSystemRoute", z);
if (!routeInfo.isEnabled()) {
bundle.putBoolean("enabled", false);
}
if (routeInfo.isConnecting()) {
bundle.putInt("connectionState", 1);
}
Display presentationDisplay = routeInfo.getPresentationDisplay();
if (presentationDisplay != null) {
bundle.putInt("presentationDisplayId", presentationDisplay.getDisplayId());
}
CharSequence description = routeInfo.getDescription();
if (description != null) {
bundle.putString("status", description.toString());
}
}
public final void o(MediaRouter.RouteInfo routeInfo) {
MediaRouteProvider d = routeInfo.d();
android.media.MediaRouter mediaRouter = this.n;
if (d != this) {
MediaRouter.UserRouteInfo createUserRoute = mediaRouter.createUserRoute(this.q);
UserRouteRecord userRouteRecord = new UserRouteRecord(routeInfo, createUserRoute);
createUserRoute.setTag(userRouteRecord);
createUserRoute.setVolumeCallback(this.p);
t(userRouteRecord);
this.v.add(userRouteRecord);
mediaRouter.addUserRoute(createUserRoute);
return;
}
int i = i(mediaRouter.getSelectedRoute(8388611));
if (i >= 0 && ((SystemRouteRecord) this.u.get(i)).b.equals(routeInfo.b)) {
routeInfo.m(false);
}
}
public final void p(MediaRouter.RouteInfo routeInfo) {
int k;
if (routeInfo.d() != this && (k = k(routeInfo)) >= 0) {
MediaRouter.UserRouteInfo userRouteInfo = ((UserRouteRecord) this.v.remove(k)).b;
userRouteInfo.setTag(null);
userRouteInfo.setVolumeCallback(null);
try {
this.n.removeUserRoute(userRouteInfo);
} catch (IllegalArgumentException e) {
Log.w("AxSysMediaRouteProvider", "Failed to remove user route", e);
}
}
}
public final void q(MediaRouter.RouteInfo routeInfo) {
if (routeInfo.h()) {
MediaRouteProvider d = routeInfo.d();
android.media.MediaRouter mediaRouter = this.n;
if (d != this) {
int k = k(routeInfo);
if (k >= 0) {
mediaRouter.selectRoute(8388611, ((UserRouteRecord) this.v.get(k)).b);
return;
}
return;
}
int j = j(routeInfo.b);
if (j >= 0) {
mediaRouter.selectRoute(8388611, ((SystemRouteRecord) this.u.get(j)).f1398a);
}
}
}
public final void r() {
MediaRouteProviderDescriptor.Builder builder = new MediaRouteProviderDescriptor.Builder();
ArrayList arrayList = this.u;
int size = arrayList.size();
for (int i = 0; i < size; i++) {
builder.a(((SystemRouteRecord) arrayList.get(i)).f1399c);
}
f(new MediaRouteProviderDescriptor(builder.f1373a, builder.b));
}
public final void s() {
boolean z = this.t;
MediaRouter.Callback callback = this.o;
android.media.MediaRouter mediaRouter = this.n;
if (z) {
mediaRouter.removeCallback(callback);
}
this.t = true;
mediaRouter.addCallback(this.r, callback, (this.s ? 1 : 0) | 2);
int routeCount = mediaRouter.getRouteCount();
ArrayList arrayList = new ArrayList(routeCount);
boolean z2 = false;
for (int i = 0; i < routeCount; i++) {
arrayList.add(mediaRouter.getRouteAt(i));
}
int size = arrayList.size();
int i2 = 0;
while (i2 < size) {
Object obj = arrayList.get(i2);
i2++;
z2 |= h((MediaRouter.RouteInfo) obj);
}
if (z2) {
r();
}
}
}
/* loaded from: classes.dex */
public interface SyncCallback {
}
}