diff --git a/core/src/main/java/org/lsposed/lspd/util/ClassPathURLStreamHandler.java b/core/src/main/java/org/lsposed/lspd/util/ClassPathURLStreamHandler.java
index a1ccf8b4..9e434613 100644
--- a/core/src/main/java/org/lsposed/lspd/util/ClassPathURLStreamHandler.java
+++ b/core/src/main/java/org/lsposed/lspd/util/ClassPathURLStreamHandler.java
@@ -13,6 +13,7 @@ import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import sun.net.www.ParseUtil;
+import sun.net.www.protocol.jar.Handler;
final class ClassPathURLStreamHandler extends Handler {
private final String fileUri;
@@ -41,7 +42,7 @@ final class ClassPathURLStreamHandler extends Handler {
}
@Override
- protected void finalize() throws Throwable {
+ protected void finalize() throws IOException {
jarFile.close();
}
diff --git a/core/src/main/java/org/lsposed/lspd/util/Handler.java b/core/src/main/java/org/lsposed/lspd/util/Handler.java
deleted file mode 100644
index f5fec900..00000000
--- a/core/src/main/java/org/lsposed/lspd/util/Handler.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.lsposed.lspd.util;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-public abstract class Handler extends java.net.URLStreamHandler {
-
- private static final String separator = "!/";
-
- private static int indexOfBangSlash(String spec) {
- int indexOfBang = spec.length();
- while ((indexOfBang = spec.lastIndexOf('!', indexOfBang)) != -1) {
- if ((indexOfBang != (spec.length() - 1)) &&
- (spec.charAt(indexOfBang + 1) == '/')) {
- return indexOfBang + 1;
- } else {
- indexOfBang--;
- }
- }
- return -1;
- }
-
- @Override
- protected boolean sameFile(URL u1, URL u2) {
- if (!u1.getProtocol().equals("jar") || !u2.getProtocol().equals("jar"))
- return false;
-
- String file1 = u1.getFile();
- String file2 = u2.getFile();
- int sep1 = file1.indexOf(separator);
- int sep2 = file2.indexOf(separator);
-
- if (sep1 == -1 || sep2 == -1) {
- return super.sameFile(u1, u2);
- }
-
- String entry1 = file1.substring(sep1 + 2);
- String entry2 = file2.substring(sep2 + 2);
-
- if (!entry1.equals(entry2))
- return false;
-
- URL enclosedURL1, enclosedURL2;
- try {
- enclosedURL1 = new URL(file1.substring(0, sep1));
- enclosedURL2 = new URL(file2.substring(0, sep2));
- } catch (MalformedURLException unused) {
- return super.sameFile(u1, u2);
- }
-
- return super.sameFile(enclosedURL1, enclosedURL2);
- }
-
- @Override
- protected int hashCode(URL u) {
- int h = 0;
-
- String protocol = u.getProtocol();
- if (protocol != null)
- h += protocol.hashCode();
-
- String file = u.getFile();
- int sep = file.indexOf(separator);
-
- if (sep == -1)
- return h + file.hashCode();
-
- URL enclosedURL;
- String fileWithoutEntry = file.substring(0, sep);
- try {
- enclosedURL = new URL(fileWithoutEntry);
- h += enclosedURL.hashCode();
- } catch (MalformedURLException unused) {
- h += fileWithoutEntry.hashCode();
- }
-
- String entry = file.substring(sep + 2);
- h += entry.hashCode();
-
- return h;
- }
-
-
- @Override
- @SuppressWarnings("deprecation")
- protected void parseURL(URL url, String spec, int start, int limit) {
- String file = null;
- String ref = null;
- // first figure out if there is an anchor
- int refPos = spec.indexOf('#', limit);
- boolean refOnly = refPos == start;
- if (refPos > -1) {
- ref = spec.substring(refPos + 1);
- if (refOnly) {
- file = url.getFile();
- }
- }
- // then figure out if the spec is
- // 1. absolute (jar:)
- // 2. relative (i.e. url + foo/bar/baz.ext)
- // 3. anchor-only (i.e. url + #foo), which we already did (refOnly)
- boolean absoluteSpec = false;
- if (spec.length() >= 4) {
- absoluteSpec = spec.substring(0, 4).equalsIgnoreCase("jar:");
- }
- spec = spec.substring(start, limit);
-
- if (absoluteSpec) {
- file = parseAbsoluteSpec(spec);
- } else if (!refOnly) {
- file = parseContextSpec(url, spec);
-
- // Canonize the result after the bangslash
- int bangSlash = indexOfBangSlash(file);
- String toBangSlash = file.substring(0, bangSlash);
- String afterBangSlash = file.substring(bangSlash);
- afterBangSlash = canonizeString(afterBangSlash);
- file = toBangSlash + afterBangSlash;
- }
- setURL(url, "jar", "", -1, file, ref);
- }
-
- private String canonizeString(String file) {
- int i;
- int lim;
-
- // Remove embedded /../
- while ((i = file.indexOf("/../")) >= 0) {
- if ((lim = file.lastIndexOf('/', i - 1)) >= 0) {
- file = file.substring(0, lim) + file.substring(i + 3);
- } else {
- file = file.substring(i + 3);
- }
- }
- // Remove embedded /./
- while ((i = file.indexOf("/./")) >= 0) {
- file = file.substring(0, i) + file.substring(i + 2);
- }
- // Remove trailing ..
- while (file.endsWith("/..")) {
- i = file.indexOf("/..");
- if ((lim = file.lastIndexOf('/', i - 1)) >= 0) {
- file = file.substring(0, lim + 1);
- } else {
- file = file.substring(0, i);
- }
- }
- // Remove trailing .
- if (file.endsWith("/."))
- file = file.substring(0, file.length() - 1);
-
- return file;
- }
-
- private String parseAbsoluteSpec(String spec) {
- int index;
- // check for !/
- if ((index = indexOfBangSlash(spec)) == -1) {
- throw new NullPointerException("no !/ in spec");
- }
- // test the inner URL
- try {
- String innerSpec = spec.substring(0, index - 1);
- new URL(innerSpec);
- } catch (MalformedURLException e) {
- throw new NullPointerException("invalid url: " +
- spec + " (" + e + ")");
- }
- return spec;
- }
-
- private String parseContextSpec(URL url, String spec) {
- String ctxFile = url.getFile();
- // if the spec begins with /, chop up the jar back !/
- if (spec.startsWith("/")) {
- int bangSlash = indexOfBangSlash(ctxFile);
- if (bangSlash == -1) {
- throw new NullPointerException("malformed " + "context url:" + url + ": no !/");
- }
- ctxFile = ctxFile.substring(0, bangSlash);
- }
- if (!ctxFile.endsWith("/") && (!spec.startsWith("/"))) {
- // chop up the last component
- int lastSlash = ctxFile.lastIndexOf('/');
- if (lastSlash == -1) {
- throw new NullPointerException("malformed " + "context url:" + url);
- }
- ctxFile = ctxFile.substring(0, lastSlash + 1);
- }
- return (ctxFile + spec);
- }
-}
diff --git a/core/src/main/java/org/lsposed/lspd/util/InstallerVerifier.java b/core/src/main/java/org/lsposed/lspd/util/InstallerVerifier.java
deleted file mode 100644
index 507e2d89..00000000
--- a/core/src/main/java/org/lsposed/lspd/util/InstallerVerifier.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This file is part of LSPosed.
- *
- * LSPosed is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LSPosed is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with LSPosed. If not, see .
- *
- * Copyright (C) 2020 EdXposed Contributors
- * Copyright (C) 2021 LSPosed Contributors
- */
-
-package org.lsposed.lspd.util;
-
-import android.os.IBinder;
-
-import de.robv.android.xposed.XposedHelpers;
-
-public class InstallerVerifier {
-
- public static void sendBinderToManager(final ClassLoader classLoader, IBinder binder) {
- try {
- var clazz = XposedHelpers.findClass("org.lsposed.manager.Constants", classLoader);
- var ok = (boolean) XposedHelpers.callStaticMethod(clazz, "setBinder",
- new Class[]{IBinder.class}, binder);
- if (ok) return;
- throw new RuntimeException("setBinder: " + false);
- } catch (Throwable t) {
- Utils.logW("Could not send binder to LSPosed Manager", t);
- }
- }
-}
diff --git a/core/src/main/java/org/lsposed/lspd/util/LspModuleClassLoader.java b/core/src/main/java/org/lsposed/lspd/util/LspModuleClassLoader.java
index 3dd5b3ed..49def72b 100644
--- a/core/src/main/java/org/lsposed/lspd/util/LspModuleClassLoader.java
+++ b/core/src/main/java/org/lsposed/lspd/util/LspModuleClassLoader.java
@@ -23,10 +23,10 @@ import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarFile;
-import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import hidden.ByteBufferDexClassLoader;
+import sun.misc.CompoundEnumeration;
@SuppressWarnings("ConstantConditions")
public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
@@ -135,7 +135,12 @@ public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
protected URL findResource(String name) {
try {
var urlHandler = new ClassPathURLStreamHandler(apk);
- return urlHandler.getEntryUrlOrNull(name);
+ var url = urlHandler.getEntryUrlOrNull(name);
+ if (url == null) {
+ // noinspection FinalizeCalledExplicitly
+ urlHandler.finalize();
+ }
+ return url;
} catch (IOException e) {
return null;
}
@@ -171,16 +176,8 @@ public final class LspModuleClassLoader extends ByteBufferDexClassLoader {
@NonNull
@Override
public String toString() {
- if (apk == null) {
- return "LspModuleClassLoader[instantiating]";
- }
- var nativeLibraryDirsString = nativeLibraryDirs.stream()
- .map(File::getPath)
- .collect(Collectors.joining(", "));
- return "LspModuleClassLoader[" +
- "module=" + apk + ", " +
- "nativeLibraryDirs=" + nativeLibraryDirsString + ", " +
- super.toString() + "]";
+ if (apk == null) return "LspModuleClassLoader[instantiating]";
+ return "LspModuleClassLoader[module=" + apk + ", " + super.toString() + "]";
}
public static ClassLoader loadApk(String apk,
diff --git a/hiddenapi/stubs/build.gradle.kts b/hiddenapi/stubs/build.gradle.kts
index 87c63453..384caffc 100644
--- a/hiddenapi/stubs/build.gradle.kts
+++ b/hiddenapi/stubs/build.gradle.kts
@@ -20,3 +20,8 @@
plugins {
`java-library`
}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
diff --git a/hiddenapi/stubs/src/main/java/android/content/pm/IShortcutService.java b/hiddenapi/stubs/src/main/java/android/content/pm/IShortcutService.java
deleted file mode 100644
index 75d351fd..00000000
--- a/hiddenapi/stubs/src/main/java/android/content/pm/IShortcutService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package android.content.pm;
-
-import android.content.IntentSender;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.RemoteException;
-
-public interface IShortcutService extends IInterface {
- boolean isRequestPinItemSupported(int user, int requestType) throws RemoteException;
- ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId) throws RemoteException;
- ParceledListSlice getPinnedShortcuts(String packageName, int userId) throws RemoteException;
- boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
- IntentSender resultIntent, int userId) throws RemoteException;
-
- boolean updateShortcuts(String packageName, ParceledListSlice shortcuts, int userId) throws RemoteException;
-
- abstract class Stub extends Binder implements IShortcutService {
-
- public static IShortcutService asInterface(IBinder obj) {
- throw new RuntimeException("STUB");
- }
- }
-}
diff --git a/hiddenapi/stubs/src/main/java/android/content/pm/ShortcutInfo.java b/hiddenapi/stubs/src/main/java/android/content/pm/ShortcutInfo.java
deleted file mode 100644
index 24b8b062..00000000
--- a/hiddenapi/stubs/src/main/java/android/content/pm/ShortcutInfo.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class ShortcutInfo implements Parcelable {
- public static final Creator CREATOR = new Creator<>() {
- @Override
- public ShortcutInfo createFromParcel(Parcel in) {
- throw new IllegalArgumentException("STUB");
- }
-
- @Override
- public ShortcutInfo[] newArray(int size) {
- throw new IllegalArgumentException("STUB");
- }
- };
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- throw new IllegalArgumentException("STUB");
- }
-
- @Override
- public int describeContents() {
- throw new IllegalArgumentException("STUB");
- }
-}
diff --git a/hiddenapi/stubs/src/main/java/android/os/ShellCallback.java b/hiddenapi/stubs/src/main/java/android/os/ShellCallback.java
index b8a5771f..fe342213 100644
--- a/hiddenapi/stubs/src/main/java/android/os/ShellCallback.java
+++ b/hiddenapi/stubs/src/main/java/android/os/ShellCallback.java
@@ -1,7 +1,7 @@
package android.os;
public class ShellCallback implements Parcelable {
- public static final Parcelable.Creator CREATOR = new Creator<>() {
+ public static final Parcelable.Creator CREATOR = new Creator() {
@Override
public ShellCallback createFromParcel(Parcel source) {
throw new IllegalArgumentException("STUB");
diff --git a/core/src/main/java/org/lsposed/lspd/util/CompoundEnumeration.java b/hiddenapi/stubs/src/main/java/sun/misc/CompoundEnumeration.java
similarity index 96%
rename from core/src/main/java/org/lsposed/lspd/util/CompoundEnumeration.java
rename to hiddenapi/stubs/src/main/java/sun/misc/CompoundEnumeration.java
index 1f2d6cd9..26eeedc1 100644
--- a/core/src/main/java/org/lsposed/lspd/util/CompoundEnumeration.java
+++ b/hiddenapi/stubs/src/main/java/sun/misc/CompoundEnumeration.java
@@ -1,4 +1,4 @@
-package org.lsposed.lspd.util;
+package sun.misc;
import java.util.Enumeration;
import java.util.NoSuchElementException;
diff --git a/hiddenapi/stubs/src/main/java/sun/net/www/protocol/jar/Handler.java b/hiddenapi/stubs/src/main/java/sun/net/www/protocol/jar/Handler.java
new file mode 100644
index 00000000..838a47e5
--- /dev/null
+++ b/hiddenapi/stubs/src/main/java/sun/net/www/protocol/jar/Handler.java
@@ -0,0 +1,4 @@
+package sun.net.www.protocol.jar;
+
+public abstract class Handler extends java.net.URLStreamHandler {
+}
diff --git a/magisk-loader/src/main/java/org/lsposed/lspd/util/ParasiticManagerHooker.java b/magisk-loader/src/main/java/org/lsposed/lspd/util/ParasiticManagerHooker.java
index e2d6fa93..560382d1 100644
--- a/magisk-loader/src/main/java/org/lsposed/lspd/util/ParasiticManagerHooker.java
+++ b/magisk-loader/src/main/java/org/lsposed/lspd/util/ParasiticManagerHooker.java
@@ -89,6 +89,18 @@ public class ParasiticManagerHooker {
return managerPkgInfo;
}
+ private static void sendBinderToManager(final ClassLoader classLoader, IBinder binder) {
+ try {
+ var clazz = XposedHelpers.findClass("org.lsposed.manager.Constants", classLoader);
+ var ok = (boolean) XposedHelpers.callStaticMethod(clazz, "setBinder",
+ new Class[]{IBinder.class}, binder);
+ if (ok) return;
+ throw new RuntimeException("setBinder: " + false);
+ } catch (Throwable t) {
+ Utils.logW("Could not send binder to LSPosed Manager", t);
+ }
+ }
+
private static void hookForManager(ILSPManagerService managerService) {
var managerApkHooker = new XC_MethodHook() {
@Override
@@ -111,7 +123,7 @@ public class ParasiticManagerHooker {
protected void afterHookedMethod(MethodHookParam param) {
var pkgInfo = getManagerPkgInfo(null);
if (pkgInfo != null && XposedHelpers.getObjectField(param.thisObject, "mApplicationInfo") == pkgInfo.applicationInfo) {
- InstallerVerifier.sendBinderToManager((ClassLoader) param.getResult(), managerService.asBinder());
+ sendBinderToManager((ClassLoader) param.getResult(), managerService.asBinder());
unhooks[0].unhook();
}
}