summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapi/system-current.txt1
-rw-r--r--core/java/android/content/pm/ModuleInfo.java22
-rw-r--r--core/java/android/content/pm/PackageManager.java20
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java24
-rw-r--r--services/core/java/com/android/server/pm/ModuleInfoProvider.java24
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java22
6 files changed, 103 insertions, 10 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index eb529bebe617..51033191d993 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2298,6 +2298,7 @@ package android.content.pm {
field public static final int MATCH_ANY_USER = 4194304; // 0x400000
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_INSTANT = 8388608; // 0x800000
+ field public static final int MODULE_APEX_NAME = 1; // 0x1
field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
field public static final int RESTRICTION_NONE = 0; // 0x0
diff --git a/core/java/android/content/pm/ModuleInfo.java b/core/java/android/content/pm/ModuleInfo.java
index d930c92d66ed..a6db662bcc43 100644
--- a/core/java/android/content/pm/ModuleInfo.java
+++ b/core/java/android/content/pm/ModuleInfo.java
@@ -37,6 +37,12 @@ public final class ModuleInfo implements Parcelable {
/** The package name of this module. */
private String mPackageName;
+ /**
+ * The name of the APEX this module is distributed as, or null if it is not distributed via
+ * APEX.
+ */
+ @Nullable private String mApexModuleName;
+
/** Whether or not this module is hidden from the user. */
private boolean mHidden;
@@ -54,6 +60,7 @@ public final class ModuleInfo implements Parcelable {
mName = orig.mName;
mPackageName = orig.mPackageName;
mHidden = orig.mHidden;
+ mApexModuleName = orig.mApexModuleName;
}
/** @hide Sets the public name of this module. */
@@ -89,6 +96,17 @@ public final class ModuleInfo implements Parcelable {
return mHidden;
}
+ /** @hide Sets the apex module name. */
+ public ModuleInfo setApexModuleName(@Nullable String apexModuleName) {
+ mApexModuleName = apexModuleName;
+ return this;
+ }
+
+ /** @hide Gets the apex module name. */
+ public @Nullable String getApexModuleName() {
+ return mApexModuleName;
+ }
+
/** Returns a string representation of this object. */
public String toString() {
return "ModuleInfo{"
@@ -106,6 +124,7 @@ public final class ModuleInfo implements Parcelable {
int hashCode = 0;
hashCode = 31 * hashCode + Objects.hashCode(mName);
hashCode = 31 * hashCode + Objects.hashCode(mPackageName);
+ hashCode = 31 * hashCode + Objects.hashCode(mApexModuleName);
hashCode = 31 * hashCode + Boolean.hashCode(mHidden);
return hashCode;
}
@@ -118,6 +137,7 @@ public final class ModuleInfo implements Parcelable {
final ModuleInfo other = (ModuleInfo) obj;
return Objects.equals(mName, other.mName)
&& Objects.equals(mPackageName, other.mPackageName)
+ && Objects.equals(mApexModuleName, other.mApexModuleName)
&& mHidden == other.mHidden;
}
@@ -126,12 +146,14 @@ public final class ModuleInfo implements Parcelable {
dest.writeCharSequence(mName);
dest.writeString(mPackageName);
dest.writeBoolean(mHidden);
+ dest.writeString(mApexModuleName);
}
private ModuleInfo(Parcel source) {
mName = source.readCharSequence();
mPackageName = source.readString();
mHidden = source.readBoolean();
+ mApexModuleName = source.readString();
}
public static final @android.annotation.NonNull Parcelable.Creator<ModuleInfo> CREATOR =
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 6694335f264c..3c083023f68d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -230,7 +230,7 @@ public abstract class PackageManager {
MATCH_ALL,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface ModuleInfoFlags {}
+ public @interface InstalledModulesFlags {}
/** @hide */
@IntDef(flag = true, prefix = { "GET_", "MATCH_" }, value = {
@@ -582,6 +582,22 @@ public abstract class PackageManager {
public static final int ONLY_IF_NO_MATCH_FOUND = 0x00000004;
/** @hide */
+ @IntDef(flag = true, prefix = { "MODULE_" }, value = {
+ MODULE_APEX_NAME,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ModuleInfoFlags {}
+
+ /**
+ * Flag for {@link #getModuleInfo}: allow ModuleInfo to be retrieved using the apex module
+ * name, rather than the package name.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int MODULE_APEX_NAME = 0x00000001;
+
+ /** @hide */
@IntDef(prefix = { "PERMISSION_" }, value = {
PERMISSION_GRANTED,
PERMISSION_DENIED
@@ -3929,7 +3945,7 @@ public abstract class PackageManager {
* there are no installed modules, an empty list is returned.
*/
@NonNull
- public List<ModuleInfo> getInstalledModules(@ModuleInfoFlags int flags) {
+ public List<ModuleInfo> getInstalledModules(@InstalledModulesFlags int flags) {
throw new UnsupportedOperationException(
"getInstalledModules not implemented in subclass");
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 28079099469a..c6d2b334bd71 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -66,7 +66,7 @@ import java.util.stream.Collectors;
* ApexManager class handles communications with the apex service to perform operation and queries,
* as well as providing caching to avoid unnecessary calls to the service.
*/
-abstract class ApexManager {
+public abstract class ApexManager {
private static final String TAG = "ApexManager";
@@ -265,6 +265,13 @@ abstract class ApexManager {
abstract List<String> getApksInApex(String apexPackageName);
/**
+ * Returns the apex module name for the given package name, if the package is an APEX. Otherwise
+ * returns {@code null}.
+ */
+ @Nullable
+ public abstract String getApexModuleNameForPackageName(String apexPackageName);
+
+ /**
* Dumps various state information to the provided {@link PrintWriter} object.
*
* @param pw the {@link PrintWriter} object to send information to.
@@ -646,6 +653,15 @@ abstract class ApexManager {
}
}
+ @Override
+ @Nullable
+ public String getApexModuleNameForPackageName(String apexPackageName) {
+ populatePackageNameToApexModuleNameIfNeeded();
+ synchronized (mLock) {
+ return mPackageNameToApexModuleName.get(apexPackageName);
+ }
+ }
+
/**
* Dump information about the packages contained in a particular cache
* @param packagesCache the cache to print information about.
@@ -843,6 +859,12 @@ abstract class ApexManager {
}
@Override
+ @Nullable
+ public String getApexModuleNameForPackageName(String apexPackageName) {
+ return null;
+ }
+
+ @Override
void dump(PrintWriter pw, String packageName) {
// No-op
}
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index 69510d9e5565..06706cd06e11 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -57,9 +57,9 @@ public class ModuleInfoProvider {
*/
private static final String MODULE_METADATA_KEY = "android.content.pm.MODULE_METADATA";
-
private final Context mContext;
private final IPackageManager mPackageManager;
+ private final ApexManager mApexManager;
private final Map<String, ModuleInfo> mModuleInfo;
// TODO: Move this to an earlier boot phase if anybody requires it then.
@@ -69,13 +69,16 @@ public class ModuleInfoProvider {
ModuleInfoProvider(Context context, IPackageManager packageManager) {
mContext = context;
mPackageManager = packageManager;
+ mApexManager = ApexManager.getInstance();
mModuleInfo = new ArrayMap<>();
}
@VisibleForTesting
- public ModuleInfoProvider(XmlResourceParser metadata, Resources resources) {
+ public ModuleInfoProvider(
+ XmlResourceParser metadata, Resources resources, ApexManager apexManager) {
mContext = null;
mPackageManager = null;
+ mApexManager = apexManager;
mModuleInfo = new ArrayMap<>();
loadModuleMetadata(metadata, resources);
}
@@ -150,6 +153,8 @@ public class ModuleInfoProvider {
mi.setHidden(isHidden);
mi.setPackageName(modulePackageName);
mi.setName(moduleName);
+ mi.setApexModuleName(
+ mApexManager.getApexModuleNameForPackageName(modulePackageName));
mModuleInfo.put(modulePackageName, mi);
}
@@ -167,7 +172,7 @@ public class ModuleInfoProvider {
*
* @param flags Use {@link PackageManager#MATCH_ALL} flag to get all modules.
*/
- List<ModuleInfo> getInstalledModules(@PackageManager.ModuleInfoFlags int flags) {
+ List<ModuleInfo> getInstalledModules(@PackageManager.InstalledModulesFlags int flags) {
if (!mMetadataLoaded) {
throw new IllegalStateException("Call to getInstalledModules before metadata loaded");
}
@@ -195,12 +200,19 @@ public class ModuleInfoProvider {
return installedModules;
}
- ModuleInfo getModuleInfo(String packageName, int flags) {
+ ModuleInfo getModuleInfo(String name, @PackageManager.ModuleInfoFlags int flags) {
if (!mMetadataLoaded) {
throw new IllegalStateException("Call to getModuleInfo before metadata loaded");
}
-
- return mModuleInfo.get(packageName);
+ if ((flags & PackageManager.MODULE_APEX_NAME) != 0) {
+ for (ModuleInfo moduleInfo : mModuleInfo.values()) {
+ if (name.equals(moduleInfo.getApexModuleName())) {
+ return moduleInfo;
+ }
+ }
+ return null;
+ }
+ return mModuleInfo.get(name);
}
String getPackageName() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
index 3852b9fec001..6a9ef8a2b7bd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
@@ -15,6 +15,9 @@
*/
package com.android.server.pm;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
import android.content.Context;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageManager;
@@ -22,11 +25,25 @@ import android.test.InstrumentationTestCase;
import com.android.frameworks.servicestests.R;
+import org.mockito.Mock;
+
import java.util.Collections;
import java.util.List;
public class ModuleInfoProviderTest extends InstrumentationTestCase {
+
+ @Mock private ApexManager mApexManager;
+
+ public void setUp() {
+ initMocks(this);
+ }
+
public void testSuccessfulParse() {
+ when(mApexManager.getApexModuleNameForPackageName("com.android.module1"))
+ .thenReturn("com.module1.apex");
+ when(mApexManager.getApexModuleNameForPackageName("com.android.module2"))
+ .thenReturn("com.module2.apex");
+
ModuleInfoProvider provider = getProvider(R.xml.well_formed_metadata);
List<ModuleInfo> mi = provider.getInstalledModules(PackageManager.MATCH_ALL);
@@ -40,11 +57,13 @@ public class ModuleInfoProviderTest extends InstrumentationTestCase {
ModuleInfo mi1 = provider.getModuleInfo("com.android.module1", 0);
assertEquals("com.android.module1", mi1.getPackageName());
assertEquals("module_1_name", mi1.getName());
+ assertEquals("com.module1.apex", mi1.getApexModuleName());
assertEquals(false, mi1.isHidden());
ModuleInfo mi2 = provider.getModuleInfo("com.android.module2", 0);
assertEquals("com.android.module2", mi2.getPackageName());
assertEquals("module_2_name", mi2.getName());
+ assertEquals("com.module2.apex", mi2.getApexModuleName());
assertEquals(true, mi2.isHidden());
}
@@ -75,6 +94,7 @@ public class ModuleInfoProviderTest extends InstrumentationTestCase {
*/
private ModuleInfoProvider getProvider(int resourceId) {
final Context ctx = getInstrumentation().getContext();
- return new ModuleInfoProvider(ctx.getResources().getXml(resourceId), ctx.getResources());
+ return new ModuleInfoProvider(
+ ctx.getResources().getXml(resourceId), ctx.getResources(), mApexManager);
}
}