Skip to content

Commit 9058485

Browse files
authored
Adapt getInstalledPackages signature change (#603)
Android 17 Beta 3 changed the IPackageManager method signature to: ``` getInstalledPackages(JI)Landroid/content/pm/PackageInfoList; ``` We introduce a reflective helper to handle the new 'PackageInfoList' return type (which inherits from ParceledListSlice) and ensures compatibility with both Long and Int flag types across API levels.
1 parent 0e64a80 commit 9058485

1 file changed

Lines changed: 51 additions & 13 deletions

File tree

daemon/src/main/java/org/lsposed/lspd/service/PackageService.java

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import java.io.InputStreamReader;
5656
import java.lang.reflect.Constructor;
5757
import java.lang.reflect.InvocationTargetException;
58+
import java.lang.reflect.Method;
5859
import java.util.ArrayList;
5960
import java.util.Collections;
6061
import java.util.HashMap;
@@ -73,11 +74,49 @@ public class PackageService {
7374
static final int INSTALL_REASON_UNKNOWN = 0;
7475
static final int MATCH_ANY_USER = 0x00400000; // PackageManager.MATCH_ANY_USER
7576

76-
static final int MATCH_ALL_FLAGS = PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;
77+
static final int MATCH_ALL_FLAGS = PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE
78+
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;
7779
public static final int PER_USER_RANGE = 100000;
7880

7981
private static IPackageManager pm = null;
8082
private static IBinder binder = null;
83+
private static final Method getInstalledPackagesMethod;
84+
85+
static {
86+
Method method = null;
87+
try {
88+
boolean isLongFlags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
89+
Class<?> flagsType = isLongFlags ? long.class : int.class;
90+
91+
for (Method m : IPackageManager.class.getDeclaredMethods()) {
92+
if (m.getName().equals("getInstalledPackages") &&
93+
m.getParameterTypes().length == 2 &&
94+
m.getParameterTypes()[0] == flagsType) {
95+
m.setAccessible(true);
96+
method = m;
97+
break;
98+
}
99+
}
100+
} catch (Exception e) {
101+
Log.e("PackageManagerUtils", "Failed to find getInstalledPackages method", e);
102+
}
103+
getInstalledPackagesMethod = method;
104+
}
105+
106+
private static List<PackageInfo> getInstalledPackagesReflect(IPackageManager pm, Object flags, int userId) {
107+
if (getInstalledPackagesMethod == null || pm == null)
108+
return Collections.emptyList();
109+
try {
110+
Object result = getInstalledPackagesMethod.invoke(pm, flags, userId);
111+
if (result instanceof ParceledListSlice) {
112+
// noinspection unchecked
113+
return ((ParceledListSlice<PackageInfo>) result).getList();
114+
}
115+
} catch (Exception e) {
116+
Log.w("PackageManagerUtils", "Reflection call failed", e);
117+
}
118+
return Collections.emptyList();
119+
}
81120

82121
static boolean isAlive() {
83122
var pm = getPackageManager();
@@ -141,21 +180,20 @@ public static ApplicationInfo getApplicationInfo(String packageName, int flags,
141180
}
142181

143182
// Only for manager
144-
public static ParcelableListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags, boolean filterNoProcess) throws RemoteException {
183+
public static ParcelableListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags, boolean filterNoProcess)
184+
throws RemoteException {
145185
List<PackageInfo> res = new ArrayList<>();
146186
IPackageManager pm = getPackageManager();
147-
if (pm == null) return ParcelableListSlice.emptyList();
187+
if (pm == null)
188+
return ParcelableListSlice.emptyList();
189+
// Prepare flags once outside the loop
190+
Object flagsObj = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) ? (long) flags : flags;
148191
for (var user : UserService.getUsers()) {
149-
// in case pkginfo of other users in primary user
150-
ParceledListSlice<PackageInfo> infos;
151-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
152-
infos = pm.getInstalledPackages((long) flags, user.id);
153-
} else {
154-
infos = pm.getInstalledPackages(flags, user.id);
155-
}
156-
res.addAll(infos
157-
.getList().parallelStream()
158-
.filter(info -> info.applicationInfo != null && info.applicationInfo.uid / PER_USER_RANGE == user.id)
192+
// Use the reflective helper instead of direct AIDL calls
193+
List<PackageInfo> infos = getInstalledPackagesReflect(pm, flagsObj, user.id);
194+
res.addAll(infos.parallelStream()
195+
.filter(info -> info.applicationInfo != null
196+
&& info.applicationInfo.uid / PER_USER_RANGE == user.id)
159197
.filter(info -> {
160198
try {
161199
return isPackageAvailable(info.packageName, user.id, true);

0 commit comments

Comments
 (0)