Loading core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -12368,6 +12368,7 @@ package android.content.pm { public final class ModuleInfo implements android.os.Parcelable { method public int describeContents(); method @FlaggedApi("android.content.pm.provide_info_of_apk_in_apex") @NonNull public java.util.Collection<java.lang.String> getApkInApexPackageNames(); method @Nullable public CharSequence getName(); method @Nullable public String getPackageName(); method public boolean isHidden(); Loading @@ -12378,6 +12379,7 @@ package android.content.pm { public class PackageInfo implements android.os.Parcelable { ctor public PackageInfo(); method public int describeContents(); method @FlaggedApi("android.content.pm.provide_info_of_apk_in_apex") @Nullable public String getApexPackageName(); method @FlaggedApi("android.content.pm.archiving") public long getArchiveTimeMillis(); method public long getLongVersionCode(); method public void setLongVersionCode(long); core/java/android/content/pm/ModuleInfo.java +39 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,15 @@ package android.content.pm; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; /** Loading @@ -46,6 +51,13 @@ public final class ModuleInfo implements Parcelable { /** Whether or not this module is hidden from the user. */ private boolean mHidden; /** * The list of the package names of all APK-in-APEX apps in the module, or * null if there are none. */ @Nullable private List<String> mApkInApexPackageNames; // TODO: Decide whether we need an additional metadata bundle to support out of band // updates to ModuleInfo. // Loading @@ -61,6 +73,9 @@ public final class ModuleInfo implements Parcelable { mPackageName = orig.mPackageName; mHidden = orig.mHidden; mApexModuleName = orig.mApexModuleName; if (orig.mApkInApexPackageNames != null) { mApkInApexPackageNames = List.copyOf(orig.mApkInApexPackageNames); } } /** @hide Sets the public name of this module. */ Loading Loading @@ -107,6 +122,25 @@ public final class ModuleInfo implements Parcelable { return mApexModuleName; } /** @hide Sets the list of the package name of APK-in-APEX apps in this module. */ public ModuleInfo setApkInApexPackageNames(@NonNull Collection<String> apkInApexPackageNames) { Objects.requireNonNull(apkInApexPackageNames); mApkInApexPackageNames = List.copyOf(apkInApexPackageNames); return this; } /** * Gets the list of the package name of all APK-in-APEX apps in the module. */ @NonNull @FlaggedApi(android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) public Collection<String> getApkInApexPackageNames() { if (mApkInApexPackageNames == null) { return Collections.emptyList(); } return mApkInApexPackageNames; } /** Returns a string representation of this object. */ public String toString() { return "ModuleInfo{" Loading @@ -125,6 +159,7 @@ public final class ModuleInfo implements Parcelable { hashCode = 31 * hashCode + Objects.hashCode(mName); hashCode = 31 * hashCode + Objects.hashCode(mPackageName); hashCode = 31 * hashCode + Objects.hashCode(mApexModuleName); hashCode = 31 * hashCode + Objects.hashCode(mApkInApexPackageNames); hashCode = 31 * hashCode + Boolean.hashCode(mHidden); return hashCode; } Loading @@ -138,6 +173,7 @@ public final class ModuleInfo implements Parcelable { return Objects.equals(mName, other.mName) && Objects.equals(mPackageName, other.mPackageName) && Objects.equals(mApexModuleName, other.mApexModuleName) && Objects.equals(mApkInApexPackageNames, other.mApkInApexPackageNames) && mHidden == other.mHidden; } Loading @@ -147,6 +183,8 @@ public final class ModuleInfo implements Parcelable { dest.writeString(mPackageName); dest.writeBoolean(mHidden); dest.writeString(mApexModuleName); // Parcel#writeStringList handles null case, we can use it directly dest.writeStringList(mApkInApexPackageNames); } private ModuleInfo(Parcel source) { Loading @@ -154,6 +192,7 @@ public final class ModuleInfo implements Parcelable { mPackageName = source.readString(); mHidden = source.readBoolean(); mApexModuleName = source.readString(); mApkInApexPackageNames = source.createStringArrayList(); } public static final @android.annotation.NonNull Parcelable.Creator<ModuleInfo> CREATOR = Loading core/java/android/content/pm/PackageInfo.java +40 −0 Original line number Diff line number Diff line Loading @@ -499,6 +499,16 @@ public class PackageInfo implements Parcelable { */ public boolean isActiveApex; /** * If the package is an APEX package (i.e. the value of {@link #isApex} * is true), this field is the package name of the APEX. If the package * is one APK-in-APEX app, this field is the package name of the parent * APEX that contains the app. If the package is not one of the above * two cases, this field is {@code null}. */ @Nullable private String mApexPackageName; public PackageInfo() { } Loading Loading @@ -535,6 +545,26 @@ public class PackageInfo implements Parcelable { mArchiveTimeMillis = value; } /** * If the package is an APEX package (i.e. the value of {@link #isApex} * is true), returns the package name of the APEX. If the package * is one APK-in-APEX app, returns the package name of the parent * APEX that contains the app. If the package is not one of the above * two cases, returns {@code null}. */ @Nullable @FlaggedApi(android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) public String getApexPackageName() { return mApexPackageName; } /** * @hide */ public void setApexPackageName(@Nullable String apexPackageName) { mApexPackageName = apexPackageName; } @Override public String toString() { return "PackageInfo{" Loading Loading @@ -603,6 +633,12 @@ public class PackageInfo implements Parcelable { dest.writeBoolean(isApex); dest.writeBoolean(isActiveApex); dest.writeLong(mArchiveTimeMillis); if (mApexPackageName != null) { dest.writeInt(1); dest.writeString8(mApexPackageName); } else { dest.writeInt(0); } dest.restoreAllowSquashing(prevAllowSquashing); } Loading Loading @@ -669,5 +705,9 @@ public class PackageInfo implements Parcelable { isApex = source.readBoolean(); isActiveApex = source.readBoolean(); mArchiveTimeMillis = source.readLong(); int hasApexPackageName = source.readInt(); if (hasApexPackageName != 0) { mApexPackageName = source.readString8(); } } } core/tests/coretests/src/android/content/pm/ModuleInfoTest.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; import static com.google.common.truth.Truth.assertThat; import android.os.Parcel; import android.platform.test.annotations.AppModeFull; import android.text.TextUtils; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.List; @RunWith(AndroidJUnit4.class) @AppModeFull public class ModuleInfoTest { private static final String APEX_MODULE_NAME = "apexModuleName"; private static final String APK_IN_APEX_PACKAGE_NAME = "apkInApexPackageName"; private static final String MODULE_PACKAGE_NAME = "modulePackageName"; private static final String MODULE_NAME = "moduleName"; @Test public void testSimple() { ModuleInfo info = new ModuleInfo(); assertThat(info.toString()).isNotNull(); } @Test public void testDefaultCopy() { ModuleInfo oldInfo = new ModuleInfo(); ModuleInfo newInfo = new ModuleInfo(oldInfo); assertThat(newInfo).isEqualTo(oldInfo); } @Test public void testCopy() { boolean isHidden = false; ModuleInfo info = new ModuleInfo(); info.setHidden(isHidden); info.setApexModuleName(APEX_MODULE_NAME); info.setPackageName(MODULE_PACKAGE_NAME); info.setName(MODULE_NAME); info.setApkInApexPackageNames(List.of(APK_IN_APEX_PACKAGE_NAME)); ModuleInfo newInfo = new ModuleInfo(info); assertThat(newInfo).isEqualTo(info); } @Test public void testGetApkInApexPackageNamesReturnEmptyListInDefault() { ModuleInfo info = new ModuleInfo(); assertThat(info.getApkInApexPackageNames()).isNotNull(); assertThat(info.getApkInApexPackageNames()).isEmpty(); } @Test public void testModuleInfoParcelizeDeparcelize() { boolean isHidden = false; ModuleInfo info = new ModuleInfo(); info.setHidden(isHidden); info.setApexModuleName(APEX_MODULE_NAME); info.setPackageName(MODULE_PACKAGE_NAME); info.setName(MODULE_NAME); info.setApkInApexPackageNames(List.of(APK_IN_APEX_PACKAGE_NAME)); final Parcel p = Parcel.obtain(); info.writeToParcel(p, 0); p.setDataPosition(0); final ModuleInfo targetInfo = ModuleInfo.CREATOR.createFromParcel(p); p.recycle(); assertThat(info.isHidden()).isEqualTo(targetInfo.isHidden()); assertThat(info.getApexModuleName()).isEqualTo(targetInfo.getApexModuleName()); assertThat(info.getPackageName()).isEqualTo(targetInfo.getPackageName()); assertThat(TextUtils.equals(info.getName(), targetInfo.getName())).isTrue(); assertThat(info.getApkInApexPackageNames().toArray()).isEqualTo( targetInfo.getApkInApexPackageNames().toArray()); } } services/core/java/com/android/server/pm/ComputerEngine.java +8 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.AuxiliaryResolveInfo; import android.content.pm.ComponentInfo; import android.content.pm.Flags; import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppRequest; import android.content.pm.InstantAppResolveInfo; Loading Loading @@ -1511,6 +1512,13 @@ public class ComputerEngine implements Computer { packageInfo.packageName = packageInfo.applicationInfo.packageName = resolveExternalPackageName(p); if (Flags.provideInfoOfApkInApex()) { final String apexModuleName = ps.getApexModuleName(); if (apexModuleName != null) { packageInfo.setApexPackageName( mApexManager.getActivePackageNameForApexModuleName(apexModuleName)); } } return packageInfo; } else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0 && PackageUserStateUtils.isAvailable(state, flags)) { Loading Loading
core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -12368,6 +12368,7 @@ package android.content.pm { public final class ModuleInfo implements android.os.Parcelable { method public int describeContents(); method @FlaggedApi("android.content.pm.provide_info_of_apk_in_apex") @NonNull public java.util.Collection<java.lang.String> getApkInApexPackageNames(); method @Nullable public CharSequence getName(); method @Nullable public String getPackageName(); method public boolean isHidden(); Loading @@ -12378,6 +12379,7 @@ package android.content.pm { public class PackageInfo implements android.os.Parcelable { ctor public PackageInfo(); method public int describeContents(); method @FlaggedApi("android.content.pm.provide_info_of_apk_in_apex") @Nullable public String getApexPackageName(); method @FlaggedApi("android.content.pm.archiving") public long getArchiveTimeMillis(); method public long getLongVersionCode(); method public void setLongVersionCode(long);
core/java/android/content/pm/ModuleInfo.java +39 −0 Original line number Diff line number Diff line Loading @@ -16,10 +16,15 @@ package android.content.pm; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; /** Loading @@ -46,6 +51,13 @@ public final class ModuleInfo implements Parcelable { /** Whether or not this module is hidden from the user. */ private boolean mHidden; /** * The list of the package names of all APK-in-APEX apps in the module, or * null if there are none. */ @Nullable private List<String> mApkInApexPackageNames; // TODO: Decide whether we need an additional metadata bundle to support out of band // updates to ModuleInfo. // Loading @@ -61,6 +73,9 @@ public final class ModuleInfo implements Parcelable { mPackageName = orig.mPackageName; mHidden = orig.mHidden; mApexModuleName = orig.mApexModuleName; if (orig.mApkInApexPackageNames != null) { mApkInApexPackageNames = List.copyOf(orig.mApkInApexPackageNames); } } /** @hide Sets the public name of this module. */ Loading Loading @@ -107,6 +122,25 @@ public final class ModuleInfo implements Parcelable { return mApexModuleName; } /** @hide Sets the list of the package name of APK-in-APEX apps in this module. */ public ModuleInfo setApkInApexPackageNames(@NonNull Collection<String> apkInApexPackageNames) { Objects.requireNonNull(apkInApexPackageNames); mApkInApexPackageNames = List.copyOf(apkInApexPackageNames); return this; } /** * Gets the list of the package name of all APK-in-APEX apps in the module. */ @NonNull @FlaggedApi(android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) public Collection<String> getApkInApexPackageNames() { if (mApkInApexPackageNames == null) { return Collections.emptyList(); } return mApkInApexPackageNames; } /** Returns a string representation of this object. */ public String toString() { return "ModuleInfo{" Loading @@ -125,6 +159,7 @@ public final class ModuleInfo implements Parcelable { hashCode = 31 * hashCode + Objects.hashCode(mName); hashCode = 31 * hashCode + Objects.hashCode(mPackageName); hashCode = 31 * hashCode + Objects.hashCode(mApexModuleName); hashCode = 31 * hashCode + Objects.hashCode(mApkInApexPackageNames); hashCode = 31 * hashCode + Boolean.hashCode(mHidden); return hashCode; } Loading @@ -138,6 +173,7 @@ public final class ModuleInfo implements Parcelable { return Objects.equals(mName, other.mName) && Objects.equals(mPackageName, other.mPackageName) && Objects.equals(mApexModuleName, other.mApexModuleName) && Objects.equals(mApkInApexPackageNames, other.mApkInApexPackageNames) && mHidden == other.mHidden; } Loading @@ -147,6 +183,8 @@ public final class ModuleInfo implements Parcelable { dest.writeString(mPackageName); dest.writeBoolean(mHidden); dest.writeString(mApexModuleName); // Parcel#writeStringList handles null case, we can use it directly dest.writeStringList(mApkInApexPackageNames); } private ModuleInfo(Parcel source) { Loading @@ -154,6 +192,7 @@ public final class ModuleInfo implements Parcelable { mPackageName = source.readString(); mHidden = source.readBoolean(); mApexModuleName = source.readString(); mApkInApexPackageNames = source.createStringArrayList(); } public static final @android.annotation.NonNull Parcelable.Creator<ModuleInfo> CREATOR = Loading
core/java/android/content/pm/PackageInfo.java +40 −0 Original line number Diff line number Diff line Loading @@ -499,6 +499,16 @@ public class PackageInfo implements Parcelable { */ public boolean isActiveApex; /** * If the package is an APEX package (i.e. the value of {@link #isApex} * is true), this field is the package name of the APEX. If the package * is one APK-in-APEX app, this field is the package name of the parent * APEX that contains the app. If the package is not one of the above * two cases, this field is {@code null}. */ @Nullable private String mApexPackageName; public PackageInfo() { } Loading Loading @@ -535,6 +545,26 @@ public class PackageInfo implements Parcelable { mArchiveTimeMillis = value; } /** * If the package is an APEX package (i.e. the value of {@link #isApex} * is true), returns the package name of the APEX. If the package * is one APK-in-APEX app, returns the package name of the parent * APEX that contains the app. If the package is not one of the above * two cases, returns {@code null}. */ @Nullable @FlaggedApi(android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX) public String getApexPackageName() { return mApexPackageName; } /** * @hide */ public void setApexPackageName(@Nullable String apexPackageName) { mApexPackageName = apexPackageName; } @Override public String toString() { return "PackageInfo{" Loading Loading @@ -603,6 +633,12 @@ public class PackageInfo implements Parcelable { dest.writeBoolean(isApex); dest.writeBoolean(isActiveApex); dest.writeLong(mArchiveTimeMillis); if (mApexPackageName != null) { dest.writeInt(1); dest.writeString8(mApexPackageName); } else { dest.writeInt(0); } dest.restoreAllowSquashing(prevAllowSquashing); } Loading Loading @@ -669,5 +705,9 @@ public class PackageInfo implements Parcelable { isApex = source.readBoolean(); isActiveApex = source.readBoolean(); mArchiveTimeMillis = source.readLong(); int hasApexPackageName = source.readInt(); if (hasApexPackageName != 0) { mApexPackageName = source.readString8(); } } }
core/tests/coretests/src/android/content/pm/ModuleInfoTest.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; import static com.google.common.truth.Truth.assertThat; import android.os.Parcel; import android.platform.test.annotations.AppModeFull; import android.text.TextUtils; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.List; @RunWith(AndroidJUnit4.class) @AppModeFull public class ModuleInfoTest { private static final String APEX_MODULE_NAME = "apexModuleName"; private static final String APK_IN_APEX_PACKAGE_NAME = "apkInApexPackageName"; private static final String MODULE_PACKAGE_NAME = "modulePackageName"; private static final String MODULE_NAME = "moduleName"; @Test public void testSimple() { ModuleInfo info = new ModuleInfo(); assertThat(info.toString()).isNotNull(); } @Test public void testDefaultCopy() { ModuleInfo oldInfo = new ModuleInfo(); ModuleInfo newInfo = new ModuleInfo(oldInfo); assertThat(newInfo).isEqualTo(oldInfo); } @Test public void testCopy() { boolean isHidden = false; ModuleInfo info = new ModuleInfo(); info.setHidden(isHidden); info.setApexModuleName(APEX_MODULE_NAME); info.setPackageName(MODULE_PACKAGE_NAME); info.setName(MODULE_NAME); info.setApkInApexPackageNames(List.of(APK_IN_APEX_PACKAGE_NAME)); ModuleInfo newInfo = new ModuleInfo(info); assertThat(newInfo).isEqualTo(info); } @Test public void testGetApkInApexPackageNamesReturnEmptyListInDefault() { ModuleInfo info = new ModuleInfo(); assertThat(info.getApkInApexPackageNames()).isNotNull(); assertThat(info.getApkInApexPackageNames()).isEmpty(); } @Test public void testModuleInfoParcelizeDeparcelize() { boolean isHidden = false; ModuleInfo info = new ModuleInfo(); info.setHidden(isHidden); info.setApexModuleName(APEX_MODULE_NAME); info.setPackageName(MODULE_PACKAGE_NAME); info.setName(MODULE_NAME); info.setApkInApexPackageNames(List.of(APK_IN_APEX_PACKAGE_NAME)); final Parcel p = Parcel.obtain(); info.writeToParcel(p, 0); p.setDataPosition(0); final ModuleInfo targetInfo = ModuleInfo.CREATOR.createFromParcel(p); p.recycle(); assertThat(info.isHidden()).isEqualTo(targetInfo.isHidden()); assertThat(info.getApexModuleName()).isEqualTo(targetInfo.getApexModuleName()); assertThat(info.getPackageName()).isEqualTo(targetInfo.getPackageName()); assertThat(TextUtils.equals(info.getName(), targetInfo.getName())).isTrue(); assertThat(info.getApkInApexPackageNames().toArray()).isEqualTo( targetInfo.getApkInApexPackageNames().toArray()); } }
services/core/java/com/android/server/pm/ComputerEngine.java +8 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.AuxiliaryResolveInfo; import android.content.pm.ComponentInfo; import android.content.pm.Flags; import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppRequest; import android.content.pm.InstantAppResolveInfo; Loading Loading @@ -1511,6 +1512,13 @@ public class ComputerEngine implements Computer { packageInfo.packageName = packageInfo.applicationInfo.packageName = resolveExternalPackageName(p); if (Flags.provideInfoOfApkInApex()) { final String apexModuleName = ps.getApexModuleName(); if (apexModuleName != null) { packageInfo.setApexPackageName( mApexManager.getActivePackageNameForApexModuleName(apexModuleName)); } } return packageInfo; } else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0 && PackageUserStateUtils.isAvailable(state, flags)) { Loading