Merge "Install system app in greatest priority partition" into rvc-dev am: d32418a72a am: d5bfbd0f27

Change-Id: Ibd5291cc48b25d168fd7bae736c180ff28916b8b
This commit is contained in:
Ryan Mitchell
2020-05-29 18:14:54 +00:00
committed by Automerger Merge Worker
6 changed files with 67 additions and 52 deletions

View File

@@ -93,15 +93,23 @@ public class PackagePartitions {
return out; return out;
} }
private static File canonicalize(File path) {
try {
return path.getCanonicalFile();
} catch (IOException e) {
return path;
}
}
/** Represents a partition that contains application packages. */ /** Represents a partition that contains application packages. */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public static class SystemPartition { public static class SystemPartition {
@NonNull
public final File folder;
@PartitionType @PartitionType
public final int type; public final int type;
@NonNull
private final DeferredCanonicalFile mFolder;
@Nullable @Nullable
private final DeferredCanonicalFile mAppFolder; private final DeferredCanonicalFile mAppFolder;
@@ -113,18 +121,18 @@ public class PackagePartitions {
private SystemPartition(@NonNull File folder, @PartitionType int type, private SystemPartition(@NonNull File folder, @PartitionType int type,
boolean containsPrivApp, boolean containsOverlay) { boolean containsPrivApp, boolean containsOverlay) {
this.folder = folder;
this.type = type; this.type = type;
this.mFolder = new DeferredCanonicalFile(folder);
this.mAppFolder = new DeferredCanonicalFile(folder, "app"); this.mAppFolder = new DeferredCanonicalFile(folder, "app");
this.mPrivAppFolder = containsPrivApp ? this.mPrivAppFolder = containsPrivApp ? new DeferredCanonicalFile(folder, "priv-app")
new DeferredCanonicalFile(folder, "priv-app") : null; : null;
this.mOverlayFolder = containsOverlay ? this.mOverlayFolder = containsOverlay ? new DeferredCanonicalFile(folder, "overlay")
new DeferredCanonicalFile(folder, "overlay") : null; : null;
} }
public SystemPartition(@NonNull SystemPartition original) { public SystemPartition(@NonNull SystemPartition original) {
this.folder = original.folder;
this.type = original.type; this.type = original.type;
this.mFolder = new DeferredCanonicalFile(original.mFolder.getFile());
this.mAppFolder = original.mAppFolder; this.mAppFolder = original.mAppFolder;
this.mPrivAppFolder = original.mPrivAppFolder; this.mPrivAppFolder = original.mPrivAppFolder;
this.mOverlayFolder = original.mOverlayFolder; this.mOverlayFolder = original.mOverlayFolder;
@@ -139,6 +147,12 @@ public class PackagePartitions {
partition.mOverlayFolder != null); partition.mOverlayFolder != null);
} }
/** Returns the canonical folder of the partition. */
@NonNull
public File getFolder() {
return mFolder.getFile();
}
/** Returns the canonical app folder of the partition. */ /** Returns the canonical app folder of the partition. */
@Nullable @Nullable
public File getAppFolder() { public File getAppFolder() {
@@ -157,30 +171,29 @@ public class PackagePartitions {
return mOverlayFolder == null ? null : mOverlayFolder.getFile(); return mOverlayFolder == null ? null : mOverlayFolder.getFile();
} }
/** Returns whether the partition contains the specified file. */
public boolean containsPath(@NonNull String path) {
return containsFile(new File(path));
}
/** Returns whether the partition contains the specified file. */
public boolean containsFile(@NonNull File file) {
return FileUtils.contains(mFolder.getFile(), canonicalize(file));
}
/** Returns whether the partition contains the specified file in its priv-app folder. */ /** Returns whether the partition contains the specified file in its priv-app folder. */
public boolean containsPrivApp(@NonNull File scanFile) { public boolean containsPrivApp(@NonNull File scanFile) {
return FileUtils.contains(mPrivAppFolder.getFile(), scanFile); return FileUtils.contains(mPrivAppFolder.getFile(), canonicalize(scanFile));
} }
/** Returns whether the partition contains the specified file in its app folder. */ /** Returns whether the partition contains the specified file in its app folder. */
public boolean containsApp(@NonNull File scanFile) { public boolean containsApp(@NonNull File scanFile) {
return FileUtils.contains(mAppFolder.getFile(), scanFile); return FileUtils.contains(mAppFolder.getFile(), canonicalize(scanFile));
} }
/** Returns whether the partition contains the specified file in its overlay folder. */ /** Returns whether the partition contains the specified file in its overlay folder. */
public boolean containsOverlay(@NonNull File scanFile) { public boolean containsOverlay(@NonNull File scanFile) {
return FileUtils.contains(mOverlayFolder.getFile(), scanFile); return FileUtils.contains(mOverlayFolder.getFile(), canonicalize(scanFile));
}
/** Returns whether the partition contains the specified file. */
public boolean containsPath(@NonNull String path) {
return path.startsWith(folder.getPath() + "/");
}
/** Returns whether the partition contains the specified file in its priv-app folder. */
public boolean containsPrivPath(@NonNull String path) {
return mPrivAppFolder != null
&& path.startsWith(mPrivAppFolder.getFile().getPath() + "/");
} }
} }
@@ -190,22 +203,24 @@ public class PackagePartitions {
* have the correct selinux policies. * have the correct selinux policies.
*/ */
private static class DeferredCanonicalFile { private static class DeferredCanonicalFile {
private boolean mIsCanonical; private boolean mIsCanonical = false;
@NonNull
private File mFile; private File mFile;
private DeferredCanonicalFile(File dir, String fileName) {
mFile = new File(dir, fileName); private DeferredCanonicalFile(@NonNull File dir) {
mIsCanonical = false; mFile = dir;
} }
private DeferredCanonicalFile(@NonNull File dir, @NonNull String fileName) {
mFile = new File(dir, fileName);
}
@NonNull
private File getFile() { private File getFile() {
if (mIsCanonical) { if (!mIsCanonical) {
return mFile; mFile = canonicalize(mFile);
} mIsCanonical = true;
mIsCanonical = true;
try {
mFile = mFile.getCanonicalFile();
} catch (IOException ignore) {
// failed to look up canonical path, continue with original one
} }
return mFile; return mFile;
} }

View File

@@ -110,7 +110,9 @@ public class OverlayConfig {
} else { } else {
// Rebase the system partitions and settings file on the specified root directory. // Rebase the system partitions and settings file on the specified root directory.
partitions = new ArrayList<>(PackagePartitions.getOrderedPartitions( partitions = new ArrayList<>(PackagePartitions.getOrderedPartitions(
p -> new OverlayPartition(new File(rootDirectory, p.folder.getPath()), p))); p -> new OverlayPartition(
new File(rootDirectory, p.getFolder().getPath()),
p)));
} }
boolean foundConfigFile = false; boolean foundConfigFile = false;
@@ -143,7 +145,7 @@ public class OverlayConfig {
// Filter out overlays not present in the partition. // Filter out overlays not present in the partition.
partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos); partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos);
for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) { for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) {
if (!partition.containsPath(partitionOverlayInfos.get(j).path.getPath())) { if (!partition.containsFile(partitionOverlayInfos.get(j).path)) {
partitionOverlayInfos.remove(j); partitionOverlayInfos.remove(j);
} }
} }

View File

@@ -27,8 +27,8 @@ import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.util.Xml; import android.util.Xml;
import com.android.internal.util.XmlUtils;
import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo; import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
import com.android.internal.util.XmlUtils;
import libcore.io.IoUtils; import libcore.io.IoUtils;
@@ -154,7 +154,7 @@ final class OverlayConfigParser {
return POLICY_PRODUCT; return POLICY_PRODUCT;
default: default:
throw new IllegalStateException("Unable to determine policy for " throw new IllegalStateException("Unable to determine policy for "
+ partition.folder); + partition.getFolder());
} }
} }
} }

View File

@@ -2711,13 +2711,13 @@ public class PackageManagerService extends IPackageManager.Stub
return SCAN_AS_SYSTEM_EXT; return SCAN_AS_SYSTEM_EXT;
default: default:
throw new IllegalStateException("Unable to determine scan flag for " throw new IllegalStateException("Unable to determine scan flag for "
+ partition.folder); + partition.getFolder());
} }
} }
@Override @Override
public String toString() { public String toString() {
return folder.getAbsolutePath() + ":" + scanFlag; return getFolder().getAbsolutePath() + ":" + scanFlag;
} }
} }
@@ -3283,7 +3283,7 @@ public class PackageManagerService extends IPackageManager.Stub
@ParseFlags int reparseFlags = 0; @ParseFlags int reparseFlags = 0;
@ScanFlags int rescanFlags = 0; @ScanFlags int rescanFlags = 0;
for (int i1 = 0, size = mDirsToScanAsSystem.size(); i1 < size; i1++) { for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
final ScanPartition partition = mDirsToScanAsSystem.get(i1); final ScanPartition partition = mDirsToScanAsSystem.get(i1);
if (partition.containsPrivApp(scanFile)) { if (partition.containsPrivApp(scanFile)) {
reparseFlags = systemParseFlags; reparseFlags = systemParseFlags;
@@ -18681,7 +18681,7 @@ public class PackageManagerService extends IPackageManager.Stub
for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) { for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
ScanPartition sp = SYSTEM_PARTITIONS.get(i); ScanPartition sp = SYSTEM_PARTITIONS.get(i);
if (apexInfo.preInstalledApexPath.getAbsolutePath().startsWith( if (apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
sp.folder.getAbsolutePath())) { sp.getFolder().getAbsolutePath())) {
return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX); return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX);
} }
} }
@@ -18777,23 +18777,23 @@ public class PackageManagerService extends IPackageManager.Stub
@Nullable int[] allUserHandles, @Nullable int[] origUserHandles, @Nullable int[] allUserHandles, @Nullable int[] origUserHandles,
@Nullable PermissionsState origPermissionState, boolean writeSettings) @Nullable PermissionsState origPermissionState, boolean writeSettings)
throws PackageManagerException { throws PackageManagerException {
final File codePath = new File(codePathString);
@ParseFlags int parseFlags = @ParseFlags int parseFlags =
mDefParseFlags mDefParseFlags
| PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_MUST_BE_APK
| PackageParser.PARSE_IS_SYSTEM_DIR; | PackageParser.PARSE_IS_SYSTEM_DIR;
@ScanFlags int scanFlags = SCAN_AS_SYSTEM; @ScanFlags int scanFlags = SCAN_AS_SYSTEM;
for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) { for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
ScanPartition partition = mDirsToScanAsSystem.get(i); ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.containsPath(codePathString)) { if (partition.containsFile(codePath)) {
scanFlags |= partition.scanFlag; scanFlags |= partition.scanFlag;
if (partition.containsPrivPath(codePathString)) { if (partition.containsPrivApp(codePath)) {
scanFlags |= SCAN_AS_PRIVILEGED; scanFlags |= SCAN_AS_PRIVILEGED;
} }
break; break;
} }
} }
final File codePath = new File(codePathString);
final AndroidPackage pkg = final AndroidPackage pkg =
scanPackageTracedLI(codePath, parseFlags, scanFlags, 0 /*currentTime*/, null); scanPackageTracedLI(codePath, parseFlags, scanFlags, 0 /*currentTime*/, null);

View File

@@ -3235,7 +3235,7 @@ public final class Settings {
PackageManagerService.ScanPartition partition = PackageManagerService.ScanPartition partition =
PackageManagerService.SYSTEM_PARTITIONS.get(index); PackageManagerService.SYSTEM_PARTITIONS.get(index);
File preferredDir = new File(partition.folder, "etc/preferred-apps"); File preferredDir = new File(partition.getFolder(), "etc/preferred-apps");
if (!preferredDir.exists() || !preferredDir.isDirectory()) { if (!preferredDir.exists() || !preferredDir.isDirectory()) {
continue; continue;
} }

View File

@@ -122,10 +122,8 @@ public class PackageManagerServiceTest {
final PackageManagerService.ScanPartition scanPartition = final PackageManagerService.ScanPartition scanPartition =
PackageManagerService.SYSTEM_PARTITIONS.get(i); PackageManagerService.SYSTEM_PARTITIONS.get(i);
for (int j = 0; j < appdir.length; j++) { for (int j = 0; j < appdir.length; j++) {
String canonical = new File("/" + partitions[i]).getCanonicalPath(); File path = new File(String.format("%s/%s/A.apk", partitions[i], appdir[j]));
String path = String.format("%s/%s/A.apk", canonical, appdir[j]); Assert.assertEquals(j == 1 && i != 3, scanPartition.containsPrivApp(path));
Assert.assertEquals(j == 1 && i != 3, scanPartition.containsPrivPath(path));
final int scanFlag = scanPartition.scanFlag; final int scanFlag = scanPartition.scanFlag;
Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR); Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR);