Merge "Install system app in greatest priority partition" into rvc-dev am: d32418a72a am: d5bfbd0f27
Change-Id: Ibd5291cc48b25d168fd7bae736c180ff28916b8b
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user