diff --git a/api/current.txt b/api/current.txt index b192d7f5eaec3..cb71160ef2635 100755 --- a/api/current.txt +++ b/api/current.txt @@ -11137,6 +11137,7 @@ package android.content.pm { field public int[] gids; field public int installLocation; field public android.content.pm.InstrumentationInfo[] instrumentation; + field public boolean isApex; field public long lastUpdateTime; field public java.lang.String packageName; field public android.content.pm.PermissionInfo[] permissions; @@ -11528,6 +11529,7 @@ package android.content.pm { field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0 field public static final int INSTALL_REASON_USER = 4; // 0x4 field public static final int MATCH_ALL = 131072; // 0x20000 + field public static final int MATCH_APEX = 1073741824; // 0x40000000 field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000 field public static final int MATCH_DIRECT_BOOT_AUTO = 268435456; // 0x10000000 field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000 diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 9e2050327ece8..ecdd810653ecd 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -18,6 +18,7 @@ package android.content.pm; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; +import android.apex.ApexInfo; import android.os.Parcel; import android.os.Parcelable; @@ -390,6 +391,11 @@ public class PackageInfo implements Parcelable { @Nullable public String compileSdkVersionCodename; + /** + * Whether the package is an APEX package. + */ + public boolean isApex; + public PackageInfo() { } @@ -472,6 +478,7 @@ public class PackageInfo implements Parcelable { } else { dest.writeInt(0); } + dest.writeBoolean(isApex); } public static final Parcelable.Creator CREATOR @@ -533,7 +540,7 @@ public class PackageInfo implements Parcelable { if (hasSigningInfo != 0) { signingInfo = SigningInfo.CREATOR.createFromParcel(source); } - + isApex = source.readBoolean(); // The component lists were flattened with the redundant ApplicationInfo // instances omitted. Distribute the canonical one here as appropriate. if (applicationInfo != null) { @@ -544,6 +551,15 @@ public class PackageInfo implements Parcelable { } } + /** + * @hide + */ + public PackageInfo(ApexInfo apexInfo) { + packageName = apexInfo.packageName; + setLongVersionCode(apexInfo.versionCode); + isApex = true; + } + private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) { if (components != null) { for (ComponentInfo ci : components) { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e14b17e5cdd32..361bebaec3a2b 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -145,6 +145,7 @@ public abstract class PackageManager { MATCH_FACTORY_ONLY, MATCH_DEBUG_TRIAGED_MISSING, MATCH_INSTANT, + MATCH_APEX, GET_DISABLED_COMPONENTS, GET_DISABLED_UNTIL_USED_COMPONENTS, GET_UNINSTALLED_PACKAGES, @@ -539,6 +540,17 @@ public abstract class PackageManager { */ public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 0x20000000; + /** + * {@link PackageInfo} flag: include APEX packages that are currently + * installed. In APEX terminology, this corresponds to packages that are + * currently active, i.e. mounted and available to other processes of the OS. + * In particular, this flag alone will not match APEX files that are staged + * for activation at next reboot. + * TODO(b/119767311): include uninstalled/inactive APEX if + * MATCH_UNINSTALLED_PACKAGES is set. + */ + public static final int MATCH_APEX = 0x40000000; + /** * Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when * resolving an intent that matches the {@code CrossProfileIntentFilter}, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e4e8010ac9e96..9856a2bb87e6e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -68,6 +68,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import static android.content.pm.PackageManager.MATCH_ALL; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.content.pm.PackageManager.MATCH_APEX; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; @@ -125,6 +126,8 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.apex.ApexInfo; +import android.apex.IApexService; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppDetailsActivity; @@ -7727,6 +7730,8 @@ public class PackageManagerService extends IPackageManager.Stub if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList(); flags = updateFlagsForPackage(flags, userId, null); final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0; + final boolean listApex = (flags & MATCH_APEX) != 0; + mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get installed packages"); @@ -7765,7 +7770,22 @@ public class PackageManagerService extends IPackageManager.Stub } } } - + if (listApex) { + final IApexService apex = IApexService.Stub.asInterface( + ServiceManager.getService("apexservice")); + if (apex != null) { + try { + final ApexInfo[] activePkgs = apex.getActivePackages(); + for (ApexInfo apexInfo : activePkgs) { + list.add(new PackageInfo(apexInfo)); + } + } catch (RemoteException e) { + Log.e(TAG, "Unable to retrieve packages from apexservice: " + e.toString()); + } + } else { + Log.e(TAG, "Unable to connect to apexservice for querying packages."); + } + } return new ParceledListSlice<>(list); } }