summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java15
-rw-r--r--core/java/com/android/internal/pm/parsing/pkg/ParsedPackage.java3
-rw-r--r--core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java3
-rw-r--r--core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java11
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java14
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java32
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java34
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt1
9 files changed, 109 insertions, 19 deletions
diff --git a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
index 73df5e8e7b1b..5e89d06facd1 100644
--- a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
@@ -421,6 +421,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
@NonNull
private String[] mUsesStaticLibrariesSorted;
+ private boolean mAppMetadataFileInApk = false;
+
@NonNull
public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
@NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp,
@@ -1063,6 +1065,11 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
return memtagMode;
}
+ @Override
+ public boolean isAppMetadataFileInApk() {
+ return mAppMetadataFileInApk;
+ }
+
@Nullable
@Override
public Bundle getMetaData() {
@@ -2151,6 +2158,12 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
}
@Override
+ public PackageImpl setAppMetadataFileInApk(boolean fileInApk) {
+ mAppMetadataFileInApk = fileInApk;
+ return this;
+ }
+
+ @Override
public PackageImpl setMetaData(@Nullable Bundle value) {
metaData = value;
return this;
@@ -3264,6 +3277,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
dest.writeLong(this.mBooleans);
dest.writeLong(this.mBooleans2);
dest.writeBoolean(this.mAllowCrossUidActivitySwitchFromBelow);
+ dest.writeBoolean(this.mAppMetadataFileInApk);
}
public PackageImpl(Parcel in) {
@@ -3426,6 +3440,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal,
this.mBooleans = in.readLong();
this.mBooleans2 = in.readLong();
this.mAllowCrossUidActivitySwitchFromBelow = in.readBoolean();
+ this.mAppMetadataFileInApk = in.readBoolean();
assignDerivedFields();
assignDerivedFields2();
diff --git a/core/java/com/android/internal/pm/parsing/pkg/ParsedPackage.java b/core/java/com/android/internal/pm/parsing/pkg/ParsedPackage.java
index 66cfb69d7871..3c26a7c3eba3 100644
--- a/core/java/com/android/internal/pm/parsing/pkg/ParsedPackage.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/ParsedPackage.java
@@ -127,4 +127,7 @@ public interface ParsedPackage extends AndroidPackage {
ParsedPackage setDirectBootAware(boolean directBootAware);
ParsedPackage setPersistent(boolean persistent);
+
+ /** Retrieves whether the apk contains a app metadata file. */
+ boolean isAppMetadataFileInApk();
}
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
index 5d185af17d48..5ab17a6b2b19 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
@@ -133,6 +133,9 @@ public interface ParsingPackage {
@Nullable SparseArray<int[]> splitDependencies
);
+ /** Sets whether the apk contains a app metadata file. */
+ ParsingPackage setAppMetadataFileInApk(boolean fileInApk);
+
ParsingPackage setMetaData(Bundle metaData);
ParsingPackage setForceQueryable(boolean forceQueryable);
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
index 2e6053d3d904..00c482722fa3 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
@@ -46,6 +46,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.Flags;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.Property;
@@ -163,6 +164,8 @@ public class ParsingPackageUtils {
*/
public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
+ public static final String APP_METADATA_FILE_NAME = "app.metadata";
+
/**
* Path prefix for apps on expanded storage
*/
@@ -636,6 +639,11 @@ public class ParsingPackageUtils {
pkg.setSigningDetails(SigningDetails.UNKNOWN);
}
+ if (Flags.aslInApkAppMetadataSource()
+ && ArrayUtils.contains(assets.list(""), APP_METADATA_FILE_NAME)) {
+ pkg.setAppMetadataFileInApk(true);
+ }
+
return input.success(pkg);
} catch (Exception e) {
return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
@@ -686,7 +694,8 @@ public class ParsingPackageUtils {
*/
private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
String codePath, Resources res, XmlResourceParser parser, int flags,
- boolean shouldSkipComponents) throws XmlPullParserException, IOException {
+ boolean shouldSkipComponents)
+ throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index a1dac0456ff9..108112a4cade 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -17,6 +17,8 @@
package com.android.server.pm;
import static android.content.pm.Flags.disallowSdkLibsToBeApps;
+import static android.content.pm.PackageManager.APP_METADATA_SOURCE_APK;
+import static android.content.pm.PackageManager.APP_METADATA_SOURCE_INSTALLER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
@@ -43,11 +45,11 @@ import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
+import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.APP_METADATA_FILE_NAME;
import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
-import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
@@ -2207,10 +2209,16 @@ final class InstallPackageHelper {
if (appMetadataFile.exists()) {
ps.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
if (Flags.aslInApkAppMetadataSource()) {
- ps.setAppMetadataSource(PackageManager.APP_METADATA_SOURCE_INSTALLER);
+ ps.setAppMetadataSource(APP_METADATA_SOURCE_INSTALLER);
}
} else {
- ps.setAppMetadataFilePath(null);
+ if (Flags.aslInApkAppMetadataSource()
+ && parsedPackage.isAppMetadataFileInApk()) {
+ ps.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
+ ps.setAppMetadataSource(APP_METADATA_SOURCE_APK);
+ } else {
+ ps.setAppMetadataFilePath(null);
+ }
}
}
if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5792d864a8ab..6deae7790fdf 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -358,7 +358,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
/** Default byte size limit for app metadata */
private static final long DEFAULT_APP_METADATA_BYTE_SIZE_LIMIT = 32000;
- private static final int APP_METADATA_FILE_ACCESS_MODE = 0640;
+ static final int APP_METADATA_FILE_ACCESS_MODE = 0640;
/**
* Throws IllegalArgumentException if the {@link IntentSender} from an immutable
@@ -1782,8 +1782,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
private File getStagedAppMetadataFile() {
- File file = new File(stageDir, APP_METADATA_FILE_NAME);
- return file.exists() ? file : null;
+ return new File(stageDir, APP_METADATA_FILE_NAME);
}
private static boolean isAppMetadata(String name) {
@@ -1799,7 +1798,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertCallerIsOwnerOrRoot();
synchronized (mLock) {
assertPreparedAndNotCommittedOrDestroyedLocked("getAppMetadataFd");
- if (getStagedAppMetadataFile() == null) {
+ if (!getStagedAppMetadataFile().exists()) {
return null;
}
try {
@@ -1813,12 +1812,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public void removeAppMetadata() {
File file = getStagedAppMetadataFile();
- if (file != null) {
+ if (file.exists()) {
file.delete();
}
}
- private static long getAppMetadataSizeLimit() {
+ static long getAppMetadataSizeLimit() {
final long token = Binder.clearCallingIdentity();
try {
return DeviceConfig.getLong(NAMESPACE_PACKAGE_MANAGER_SERVICE,
@@ -2131,7 +2130,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
File appMetadataFile = getStagedAppMetadataFile();
- if (appMetadataFile != null) {
+ if (appMetadataFile.exists()) {
long sizeLimit = getAppMetadataSizeLimit();
if (appMetadataFile.length() > sizeLimit) {
appMetadataFile.delete();
@@ -3419,7 +3418,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final List<ApkLite> addedFiles = getAddedApkLitesLocked();
if (addedFiles.isEmpty()
- && (removeSplitList.size() == 0 || getStagedAppMetadataFile() != null)) {
+ && (removeSplitList.size() == 0 || getStagedAppMetadataFile().exists())) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
TextUtils.formatSimple("Session: %d. No packages staged in %s", sessionId,
stageDir.getAbsolutePath()));
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dadafd7f9438..380de56b5c19 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -18,6 +18,8 @@ package com.android.server.pm;
import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.content.pm.PackageManager.APP_METADATA_SOURCE_APK;
+import static android.content.pm.PackageManager.APP_METADATA_SOURCE_UNKNOWN;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
@@ -596,7 +598,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
static final String RANDOM_DIR_PREFIX = "~~";
static final char RANDOM_CODEPATH_PREFIX = '-';
- static final String APP_METADATA_FILE_NAME = "app.metadata";
+ public static final String APP_METADATA_FILE_NAME = "app.metadata";
+ public static final String APP_METADATA_FILE_IN_APK_PATH = "assets/" + APP_METADATA_FILE_NAME;
static final int DEFAULT_FILE_ACCESS_MODE = 0644;
@@ -5230,15 +5233,30 @@ public class PackageManagerService implements PackageSender, TestUtilityService
new PackageManager.NameNotFoundException(packageName));
}
String filePath = ps.getAppMetadataFilePath();
- if (filePath != null) {
- File file = new File(filePath);
- try {
- return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
- } catch (FileNotFoundException e) {
+ if (filePath == null) {
+ return null;
+ }
+ File file = new File(filePath);
+ if (Flags.aslInApkAppMetadataSource() && !file.exists()
+ && ps.getAppMetadataSource() == APP_METADATA_SOURCE_APK) {
+ String apkPath = ps.getPkg().getSplits().get(0).getPath();
+ if (!PackageManagerServiceUtils.extractAppMetadataFromApk(apkPath, file)) {
+ if (file.exists()) {
+ file.delete();
+ }
+ synchronized (mLock) {
+ PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
+ pkgSetting.setAppMetadataFilePath(null);
+ pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN);
+ }
return null;
}
}
- return null;
+ try {
+ return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ return null;
+ }
}
@android.annotation.EnforcePermission(android.Manifest.permission.GET_APP_METADATA)
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 4f9ed03dc8e7..eb9035dba038 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -27,6 +27,9 @@ import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__EXPLICIT_INTENT_FILTER_UNMATCH;
import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
+import static com.android.server.pm.PackageInstallerSession.APP_METADATA_FILE_ACCESS_MODE;
+import static com.android.server.pm.PackageInstallerSession.getAppMetadataSizeLimit;
+import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_IN_APK_PATH;
import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING;
@@ -142,6 +145,8 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
/**
* Class containing helper methods for the PackageManagerService.
@@ -1556,6 +1561,35 @@ public class PackageManagerServiceUtils {
return initiatingPackageName == null || SHELL_PACKAGE_NAME.equals(initiatingPackageName);
}
+ /**
+ * Extract the app.metadata file from apk.
+ */
+ public static boolean extractAppMetadataFromApk(String apkPath, File appMetadataFile) {
+ boolean found = false;
+ try (ZipInputStream zipInputStream =
+ new ZipInputStream(new FileInputStream(new File(apkPath)))) {
+ ZipEntry zipEntry = null;
+ while ((zipEntry = zipInputStream.getNextEntry()) != null) {
+ if (zipEntry.getName().equals(APP_METADATA_FILE_IN_APK_PATH)) {
+ found = true;
+ try (FileOutputStream out = new FileOutputStream(appMetadataFile)) {
+ FileUtils.copy(zipInputStream, out);
+ }
+ if (appMetadataFile.length() > getAppMetadataSizeLimit()) {
+ appMetadataFile.delete();
+ return false;
+ }
+ Os.chmod(appMetadataFile.getAbsolutePath(), APP_METADATA_FILE_ACCESS_MODE);
+ break;
+ }
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, e.getMessage());
+ return false;
+ }
+ return found;
+ }
+
public static void linkFilesToOldDirs(@NonNull Installer installer,
@NonNull String packageName,
@NonNull File newPath,
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index d4b57f191ecd..96e9ca0c19b5 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -275,6 +275,7 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag
AndroidPackage::isUpdatableSystem,
AndroidPackage::getEmergencyInstaller,
AndroidPackage::isAllowCrossUidActivitySwitchFromBelow,
+ PackageImpl::isAppMetadataFileInApk,
)
override fun extraParams() = listOf(