feat: adding package lister with app name and versions#13
feat: adding package lister with app name and versions#13
Conversation
WalkthroughA new standalone Java class 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
2 issues found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/src/main/java/com/mobilenext/devicekit/PackageLister.java">
<violation number="1" location="app/src/main/java/com/mobilenext/devicekit/PackageLister.java:41">
P2: Avoid hard-coding userId=0 when querying installed packages; it can return the wrong package set on multi-user devices.</violation>
<violation number="2" location="app/src/main/java/com/mobilenext/devicekit/PackageLister.java:61">
P1: Close `AssetManager` after use; creating one per package without closing can leak native resources.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| displayName = appInfo.nonLocalizedLabel.toString(); | ||
| } else if (appInfo.labelRes != 0 && appInfo.sourceDir != null) { | ||
| try { | ||
| AssetManager assets = AssetManager.class.getDeclaredConstructor().newInstance(); |
There was a problem hiding this comment.
P1: Close AssetManager after use; creating one per package without closing can leak native resources.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/java/com/mobilenext/devicekit/PackageLister.java, line 61:
<comment>Close `AssetManager` after use; creating one per package without closing can leak native resources.</comment>
<file context>
@@ -0,0 +1,88 @@
+ displayName = appInfo.nonLocalizedLabel.toString();
+ } else if (appInfo.labelRes != 0 && appInfo.sourceDir != null) {
+ try {
+ AssetManager assets = AssetManager.class.getDeclaredConstructor().newInstance();
+ Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class);
+ addAssetPath.invoke(assets, appInfo.sourceDir);
</file context>
|
|
||
| // Call getInstalledPackages(flags, userId) | ||
| Method getInstalledPackages = ipm.getClass().getMethod("getInstalledPackages", long.class, int.class); | ||
| Object parceledList = getInstalledPackages.invoke(ipm, 0L, 0); |
There was a problem hiding this comment.
P2: Avoid hard-coding userId=0 when querying installed packages; it can return the wrong package set on multi-user devices.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/java/com/mobilenext/devicekit/PackageLister.java, line 41:
<comment>Avoid hard-coding userId=0 when querying installed packages; it can return the wrong package set on multi-user devices.</comment>
<file context>
@@ -0,0 +1,88 @@
+
+ // Call getInstalledPackages(flags, userId)
+ Method getInstalledPackages = ipm.getClass().getMethod("getInstalledPackages", long.class, int.class);
+ Object parceledList = getInstalledPackages.invoke(ipm, 0L, 0);
+
+ // ParceledListSlice.getList()
</file context>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/src/main/java/com/mobilenext/devicekit/PackageLister.java (1)
60-70: Close the per-packageAssetManager.
AssetManagerisAutoCloseableand exposesclose(). Since this loop allocates one per package, not closing it retains native resources until process exit; wrap the label lookup infinally. (android.googlesource.com)♻️ Proposed fix
- AssetManager assets = AssetManager.class.getDeclaredConstructor().newInstance(); - Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class); - addAssetPath.invoke(assets, appInfo.sourceDir); - Resources res = new Resources(assets, new DisplayMetrics(), new Configuration()); - String label = res.getString(appInfo.labelRes); - if (label != null && !label.isEmpty()) { - displayName = label; - } + AssetManager assets = AssetManager.class.getDeclaredConstructor().newInstance(); + try { + Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class); + addAssetPath.invoke(assets, appInfo.sourceDir); + Resources res = new Resources(assets, new DisplayMetrics(), new Configuration()); + String label = res.getString(appInfo.labelRes); + if (label != null && !label.isEmpty()) { + displayName = label; + } + } finally { + assets.close(); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/mobilenext/devicekit/PackageLister.java` around lines 60 - 70, The created per-package AssetManager in the try block (AssetManager assets = AssetManager.class.getDeclaredConstructor().newInstance(); used with addAssetPath and Resources) is not closed and leaks native resources; update the code around AssetManager/assets (and the label lookup that uses appInfo.labelRes and Resources) to use try-with-resources or ensure assets.close() is called in a finally block after obtaining the label, so each AssetManager is closed for every package iteration before continuing and displayName assignment remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/src/main/java/com/mobilenext/devicekit/PackageLister.java`:
- Around line 39-41: The reflection call in PackageLister that retrieves
getInstalledPackages on ipm currently assumes the signature
getInstalledPackages(long,int) and hardcodes userId 0, which will fail on older
Android (e.g., Android 10) that exposes getInstalledPackages(int,int) and
ignores multi-user installs; update the logic in PackageLister to try a fallback
chain: first attempt ipm.getClass().getMethod("getInstalledPackages",
long.class, int.class) and invoke it if present, then catch
NoSuchMethodException and try ipm.getClass().getMethod("getInstalledPackages",
int.class, int.class) and invoke that instead, mapping the long argument to an
int when using the older signature; also add a parameter to the PackageLister
API (or method where this reflection occurs) to accept a targetUserId instead of
hardcoding 0 and pass that value when invoking either signature so packages for
the requested user are returned.
---
Nitpick comments:
In `@app/src/main/java/com/mobilenext/devicekit/PackageLister.java`:
- Around line 60-70: The created per-package AssetManager in the try block
(AssetManager assets =
AssetManager.class.getDeclaredConstructor().newInstance(); used with
addAssetPath and Resources) is not closed and leaks native resources; update the
code around AssetManager/assets (and the label lookup that uses appInfo.labelRes
and Resources) to use try-with-resources or ensure assets.close() is called in a
finally block after obtaining the label, so each AssetManager is closed for
every package iteration before continuing and displayName assignment remains
unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e28ae274-308c-405a-880e-584910ca1dba
📒 Files selected for processing (1)
app/src/main/java/com/mobilenext/devicekit/PackageLister.java
| // Call getInstalledPackages(flags, userId) | ||
| Method getInstalledPackages = ipm.getClass().getMethod("getInstalledPackages", long.class, int.class); | ||
| Object parceledList = getInstalledPackages.invoke(ipm, 0L, 0); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In AOSP, compare the declared signatures of android.content.pm.IPackageManager#getInstalledPackages on current master and android10-release, and confirm whether the userId parameter scopes the returned package list.
💡 Result:
The declared signatures of android.content.pm.IPackageManager#getInstalledPackages differ between AOSP current master and android10-release. In current AOSP master (refs/heads/main), the relevant method is: ParceledListSlice<PackageInfo> getInstalledPackages(@PackageManager.PackageInfoFlagsBits long flags, int userId) In android10-release (Android 10 / Q), the relevant method is: ParceledListSlice<PackageInfo> getInstalledPackages(int flags, in int userId) Both branches have the userId parameter as the second parameter. The userId parameter scopes the returned package list to packages installed for that specific user. In Android's multi-user system, packages can be installed per-user, and this method returns PackageInfo objects filtered to the specified userId, respecting per-user installation states. This is evident from the implementation pattern where ApplicationPackageManager passes userId to IPackageManager.getInstalledPackages, and PackageManagerService uses userId to filter results based on PackageUserState.isInstalled for that user.
Citations:
- 1: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/pm/IPackageManager.aidl
- 2: https://raw.githubusercontent.com/LineageOS/android_frameworks_base/7fc95f204527ee079c5891d56c969668f0b35a0b/core/java/android/content/pm/IPackageManager.aidl
- 3: https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
- 4: https://android.googlesource.com/platform/frameworks/base/+/879c5e0/core/java/android/app/ApplicationPackageManager.java
- 5: https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r1/core/java/android/content/pm/PackageManager.java
🏁 Script executed:
# Get the file content around the specified lines to understand context
head -60 "app/src/main/java/com/mobilenext/devicekit/PackageLister.java" | tail -40Repository: mobile-next/devicekit-android
Length of output: 2090
Add fallback for different getInstalledPackages signatures across Android versions.
Lines 40–41 assume the method signature getInstalledPackages(long, int) (AOSP master), but older releases like Android 10 expose getInstalledPackages(int, int). This will raise NoSuchMethodException at runtime on those versions. Additionally, hardcoding userId=0 ignores packages installed for other users on multi-user devices.
Implement a try-fallback chain to attempt the master signature first, then fall back to the older (int, int) signature. Consider accepting the target user as a parameter instead of pinning it to 0.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/src/main/java/com/mobilenext/devicekit/PackageLister.java` around lines
39 - 41, The reflection call in PackageLister that retrieves
getInstalledPackages on ipm currently assumes the signature
getInstalledPackages(long,int) and hardcodes userId 0, which will fail on older
Android (e.g., Android 10) that exposes getInstalledPackages(int,int) and
ignores multi-user installs; update the logic in PackageLister to try a fallback
chain: first attempt ipm.getClass().getMethod("getInstalledPackages",
long.class, int.class) and invoke it if present, then catch
NoSuchMethodException and try ipm.getClass().getMethod("getInstalledPackages",
int.class, int.class) and invoke that instead, mapping the long argument to an
int when using the older signature; also add a parameter to the PackageLister
API (or method where this reflection occurs) to accept a targetUserId instead of
hardcoding 0 and pass that value when invoking either signature so packages for
the requested user are returned.
Summary by cubic
Adds a standalone package lister runnable via
app_processthat outputs a JSON array of installed apps with package name, app name, and version. Useful for inspecting devices from the shell without launching an app.com.mobilenext.devicekit.PackageListeras a shell entry point (adb shell CLASSPATH=/path/to/classes.dex app_process / com.mobilenext.devicekit.PackageLister).ServiceManager+IPackageManagerfor user 0.nonLocalizedLabel, thenlabelRes(using a temporaryAssetManager), with fallback to the package name; outputspackageName,appName,versionto stdout.Written for commit facfcb5. Summary will update on new commits.