Merge "Provided a solution to sort partitions from order in /product/overlay/partition_order.xml, added a debugging command to dump the partition order and how it get established." into main
This commit is contained in:
@@ -190,4 +190,15 @@ interface IOverlayManager {
|
|||||||
* @throws SecurityException if the transaction failed
|
* @throws SecurityException if the transaction failed
|
||||||
*/
|
*/
|
||||||
void commit(in OverlayManagerTransaction transaction);
|
void commit(in OverlayManagerTransaction transaction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a String of a list of partitions from low priority to high.
|
||||||
|
*/
|
||||||
|
String getPartitionOrder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean which represent whether the partition list is sorted by default.
|
||||||
|
* If not then it should be sorted by /product/overlay/partition_order.xml.
|
||||||
|
*/
|
||||||
|
boolean isDefaultPartitionOrder();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,15 @@ import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
|
|||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.function.TriConsumer;
|
import com.android.internal.util.function.TriConsumer;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -46,6 +53,10 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for reading overlay configuration files and handling queries of overlay mutability,
|
* Responsible for reading overlay configuration files and handling queries of overlay mutability,
|
||||||
* default-enabled state, and priority.
|
* default-enabled state, and priority.
|
||||||
@@ -61,6 +72,8 @@ public class OverlayConfig {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static final int DEFAULT_PRIORITY = Integer.MAX_VALUE;
|
public static final int DEFAULT_PRIORITY = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
public static final String PARTITION_ORDER_FILE_PATH = "/product/overlay/partition_order.xml";
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static final class Configuration {
|
public static final class Configuration {
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -119,6 +132,10 @@ public class OverlayConfig {
|
|||||||
// Singleton instance only assigned in system server
|
// Singleton instance only assigned in system server
|
||||||
private static OverlayConfig sInstance;
|
private static OverlayConfig sInstance;
|
||||||
|
|
||||||
|
private final String mPartitionOrder;
|
||||||
|
|
||||||
|
private final boolean mIsDefaultPartitionOrder;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public OverlayConfig(@Nullable File rootDirectory,
|
public OverlayConfig(@Nullable File rootDirectory,
|
||||||
@Nullable Supplier<OverlayScanner> scannerFactory,
|
@Nullable Supplier<OverlayScanner> scannerFactory,
|
||||||
@@ -137,6 +154,8 @@ public class OverlayConfig {
|
|||||||
new File(rootDirectory, p.getNonConicalFolder().getPath()),
|
new File(rootDirectory, p.getNonConicalFolder().getPath()),
|
||||||
p)));
|
p)));
|
||||||
}
|
}
|
||||||
|
mIsDefaultPartitionOrder = !sortPartitions(PARTITION_ORDER_FILE_PATH, partitions);
|
||||||
|
mPartitionOrder = generatePartitionOrderString(partitions);
|
||||||
|
|
||||||
ArrayMap<Integer, List<String>> activeApexesPerPartition = getActiveApexes(partitions);
|
ArrayMap<Integer, List<String>> activeApexesPerPartition = getActiveApexes(partitions);
|
||||||
|
|
||||||
@@ -198,6 +217,96 @@ public class OverlayConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String generatePartitionOrderString(List<OverlayPartition> partitions) {
|
||||||
|
if (partitions == null || partitions.size() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder partitionOrder = new StringBuilder();
|
||||||
|
partitionOrder.append(partitions.get(0).getName());
|
||||||
|
for (int i = 1; i < partitions.size(); i++) {
|
||||||
|
partitionOrder.append(", ").append(partitions.get(i).getName());
|
||||||
|
}
|
||||||
|
return partitionOrder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean parseAndValidatePartitionsOrderXml(String partitionOrderFilePath,
|
||||||
|
Map<String, Integer> orderMap, List<OverlayPartition> partitions) {
|
||||||
|
try {
|
||||||
|
File file = new File(partitionOrderFilePath);
|
||||||
|
if (!file.exists()) {
|
||||||
|
Log.w(TAG, "partition_order.xml does not exist.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var dbFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||||
|
Document doc = dBuilder.parse(file);
|
||||||
|
doc.getDocumentElement().normalize();
|
||||||
|
|
||||||
|
Element root = doc.getDocumentElement();
|
||||||
|
if (!root.getNodeName().equals("partition-order")) {
|
||||||
|
Log.w(TAG, "Invalid partition_order.xml, "
|
||||||
|
+ "xml root element is not partition-order");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeList partitionList = doc.getElementsByTagName("partition");
|
||||||
|
for (int order = 0; order < partitionList.getLength(); order++) {
|
||||||
|
Node partitionNode = partitionList.item(order);
|
||||||
|
if (partitionNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
Element partitionElement = (Element) partitionNode;
|
||||||
|
String partitionName = partitionElement.getAttribute("name");
|
||||||
|
if (orderMap.containsKey(partitionName)) {
|
||||||
|
Log.w(TAG, "Invalid partition_order.xml, "
|
||||||
|
+ "it has duplicate partition: " + partitionName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
orderMap.put(partitionName, order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderMap.keySet().size() != partitions.size()) {
|
||||||
|
Log.w(TAG, "Invalid partition_order.xml, partition_order.xml has "
|
||||||
|
+ orderMap.keySet().size() + " partitions, "
|
||||||
|
+ "which is different from SYSTEM_PARTITIONS");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < partitions.size(); i++) {
|
||||||
|
if (!orderMap.keySet().contains(partitions.get(i).getName())) {
|
||||||
|
Log.w(TAG, "Invalid Parsing partition_order.xml, "
|
||||||
|
+ "partition_order.xml does not have partition: "
|
||||||
|
+ partitions.get(i).getName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||||
|
Log.w(TAG, "Parsing or validating partition_order.xml failed, "
|
||||||
|
+ "exception thrown: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log.i(TAG, "Sorting partitions in the specified order from partitions_order.xml");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort partitions by order in partition_order.xml if the file exists.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static boolean sortPartitions(String partitionOrderFilePath,
|
||||||
|
List<OverlayPartition> partitions) {
|
||||||
|
Map<String, Integer> orderMap = new HashMap<>();
|
||||||
|
if (!parseAndValidatePartitionsOrderXml(partitionOrderFilePath, orderMap, partitions)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Comparator<OverlayPartition> partitionComparator = Comparator.comparingInt(
|
||||||
|
o -> orderMap.get(o.getName()));
|
||||||
|
Collections.sort(partitions, partitionComparator);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of OverlayConfig for use in the zygote process.
|
* Creates an instance of OverlayConfig for use in the zygote process.
|
||||||
* This instance will not include information of static overlays existing outside of a partition
|
* This instance will not include information of static overlays existing outside of a partition
|
||||||
@@ -476,4 +585,19 @@ public class OverlayConfig {
|
|||||||
*/
|
*/
|
||||||
private static native String[] createIdmap(@NonNull String targetPath,
|
private static native String[] createIdmap(@NonNull String targetPath,
|
||||||
@NonNull String[] overlayPath, @NonNull String[] policies, boolean enforceOverlayable);
|
@NonNull String[] overlayPath, @NonNull String[] policies, boolean enforceOverlayable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isDefaultPartitionOrder() {
|
||||||
|
return mIsDefaultPartitionOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public String getPartitionOrder() {
|
||||||
|
return mPartitionOrder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.util.ArraySet;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
|
import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
@@ -53,8 +54,11 @@ import java.util.Map;
|
|||||||
*
|
*
|
||||||
* @see #parseOverlay(File, XmlPullParser, OverlayScanner, ParsingContext)
|
* @see #parseOverlay(File, XmlPullParser, OverlayScanner, ParsingContext)
|
||||||
* @see #parseMerge(File, XmlPullParser, OverlayScanner, ParsingContext)
|
* @see #parseMerge(File, XmlPullParser, OverlayScanner, ParsingContext)
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
**/
|
**/
|
||||||
final class OverlayConfigParser {
|
@VisibleForTesting
|
||||||
|
public final class OverlayConfigParser {
|
||||||
|
|
||||||
// Default values for overlay configurations.
|
// Default values for overlay configurations.
|
||||||
static final boolean DEFAULT_ENABLED_STATE = false;
|
static final boolean DEFAULT_ENABLED_STATE = false;
|
||||||
@@ -115,7 +119,11 @@ final class OverlayConfigParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class OverlayPartition extends SystemPartition {
|
/**
|
||||||
|
* @hide
|
||||||
|
**/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static class OverlayPartition extends SystemPartition {
|
||||||
// Policies passed to idmap2 during idmap creation.
|
// Policies passed to idmap2 during idmap creation.
|
||||||
// Keep partition policy constants in sync with f/b/cmds/idmap2/include/idmap2/Policies.h.
|
// Keep partition policy constants in sync with f/b/cmds/idmap2/include/idmap2/Policies.h.
|
||||||
static final String POLICY_ODM = "odm";
|
static final String POLICY_ODM = "odm";
|
||||||
@@ -128,7 +136,11 @@ final class OverlayConfigParser {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public final String policy;
|
public final String policy;
|
||||||
|
|
||||||
OverlayPartition(@NonNull SystemPartition partition) {
|
/**
|
||||||
|
* @hide
|
||||||
|
**/
|
||||||
|
@VisibleForTesting
|
||||||
|
public OverlayPartition(@NonNull SystemPartition partition) {
|
||||||
super(partition);
|
super(partition);
|
||||||
this.policy = policyForPartition(partition);
|
this.policy = policyForPartition(partition);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertNotNull;
|
|||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.content.pm.PackagePartitions;
|
||||||
import android.os.FileUtils;
|
import android.os.FileUtils;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
@@ -32,6 +33,7 @@ import androidx.test.runner.AndroidJUnit4;
|
|||||||
import com.android.frameworks.coretests.R;
|
import com.android.frameworks.coretests.R;
|
||||||
import com.android.internal.content.om.OverlayConfig;
|
import com.android.internal.content.om.OverlayConfig;
|
||||||
import com.android.internal.content.om.OverlayConfig.IdmapInvocation;
|
import com.android.internal.content.om.OverlayConfig.IdmapInvocation;
|
||||||
|
import com.android.internal.content.om.OverlayConfigParser.OverlayPartition;
|
||||||
import com.android.internal.content.om.OverlayScanner;
|
import com.android.internal.content.om.OverlayScanner;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -46,6 +48,7 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -88,6 +91,17 @@ public class OverlayConfigTest {
|
|||||||
assertEquals(configIndex, config.configIndex);
|
assertEquals(configIndex, config.configIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String generatePartitionOrderString(List<OverlayPartition> partitions) {
|
||||||
|
StringBuilder partitionOrder = new StringBuilder();
|
||||||
|
for (int i = 0; i < partitions.size(); i++) {
|
||||||
|
partitionOrder.append(partitions.get(i).getName());
|
||||||
|
if (i < partitions.size() - 1) {
|
||||||
|
partitionOrder.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return partitionOrder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImmutableAfterNonImmutableFails() throws IOException {
|
public void testImmutableAfterNonImmutableFails() throws IOException {
|
||||||
mExpectedException.expect(IllegalStateException.class);
|
mExpectedException.expect(IllegalStateException.class);
|
||||||
@@ -685,4 +699,122 @@ public class OverlayConfigTest {
|
|||||||
OverlayConfig.Configuration o3 = overlayConfig.getConfiguration("three");
|
OverlayConfig.Configuration o3 = overlayConfig.getConfiguration("three");
|
||||||
assertNotNull(o3);
|
assertNotNull(o3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortPartitionsWithoutXml() throws IOException {
|
||||||
|
ArrayList<OverlayPartition> partitions = new ArrayList<>(
|
||||||
|
PackagePartitions.getOrderedPartitions(OverlayPartition::new));
|
||||||
|
|
||||||
|
final OverlayConfig overlayConfig = createConfigImpl();
|
||||||
|
String partitionOrderFilePath = String.format("%s/%s", mTestFolder.getRoot(),
|
||||||
|
"/product/overlay/partition_order.xml");
|
||||||
|
assertEquals(false, overlayConfig.sortPartitions(partitionOrderFilePath, partitions));
|
||||||
|
assertEquals("system, vendor, odm, oem, product, system_ext",
|
||||||
|
generatePartitionOrderString(partitions));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortPartitionsWithInvalidXmlRootElement() throws IOException {
|
||||||
|
ArrayList<OverlayPartition> partitions = new ArrayList<>(
|
||||||
|
PackagePartitions.getOrderedPartitions(OverlayPartition::new));
|
||||||
|
createFile("/product/overlay/partition_order.xml",
|
||||||
|
"<partition-list>\n"
|
||||||
|
+ " <partition name=\"system_ext\"/>\n"
|
||||||
|
+ " <partition name=\"vendor\"/>\n"
|
||||||
|
+ " <partition name=\"oem\"/>\n"
|
||||||
|
+ " <partition name=\"odm\"/>\n"
|
||||||
|
+ " <partition name=\"product\"/>\n"
|
||||||
|
+ " <partition name=\"system\"/>\n"
|
||||||
|
+ "</partition-list>\n");
|
||||||
|
final OverlayConfig overlayConfig = createConfigImpl();
|
||||||
|
String partitionOrderFilePath = String.format("%s/%s", mTestFolder.getRoot(),
|
||||||
|
"/product/overlay/partition_order.xml");
|
||||||
|
assertEquals(false, overlayConfig.sortPartitions(partitionOrderFilePath, partitions));
|
||||||
|
assertEquals("system, vendor, odm, oem, product, system_ext",
|
||||||
|
generatePartitionOrderString(partitions));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortPartitionsWithInvalidPartition() throws IOException {
|
||||||
|
ArrayList<OverlayPartition> partitions = new ArrayList<>(
|
||||||
|
PackagePartitions.getOrderedPartitions(OverlayPartition::new));
|
||||||
|
createFile("/product/overlay/partition_order.xml",
|
||||||
|
"<partition-order>\n"
|
||||||
|
+ " <partition name=\"INVALID\"/>\n"
|
||||||
|
+ " <partition name=\"vendor\"/>\n"
|
||||||
|
+ " <partition name=\"oem\"/>\n"
|
||||||
|
+ " <partition name=\"odm\"/>\n"
|
||||||
|
+ " <partition name=\"product\"/>\n"
|
||||||
|
+ " <partition name=\"system\"/>\n"
|
||||||
|
+ "</partition-order>\n");
|
||||||
|
final OverlayConfig overlayConfig = createConfigImpl();
|
||||||
|
String partitionOrderFilePath = String.format("%s/%s", mTestFolder.getRoot(),
|
||||||
|
"/product/overlay/partition_order.xml");
|
||||||
|
assertEquals(false, overlayConfig.sortPartitions(partitionOrderFilePath, partitions));
|
||||||
|
assertEquals("system, vendor, odm, oem, product, system_ext",
|
||||||
|
generatePartitionOrderString(partitions));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortPartitionsWithDuplicatePartition() throws IOException {
|
||||||
|
ArrayList<OverlayPartition> partitions = new ArrayList<>(
|
||||||
|
PackagePartitions.getOrderedPartitions(OverlayPartition::new));
|
||||||
|
createFile("/product/overlay/partition_order.xml",
|
||||||
|
"<partition-order>\n"
|
||||||
|
+ " <partition name=\"system_ext\"/>\n"
|
||||||
|
+ " <partition name=\"system\"/>\n"
|
||||||
|
+ " <partition name=\"vendor\"/>\n"
|
||||||
|
+ " <partition name=\"oem\"/>\n"
|
||||||
|
+ " <partition name=\"odm\"/>\n"
|
||||||
|
+ " <partition name=\"product\"/>\n"
|
||||||
|
+ " <partition name=\"system\"/>\n"
|
||||||
|
+ "</partition-order>\n");
|
||||||
|
final OverlayConfig overlayConfig = createConfigImpl();
|
||||||
|
String partitionOrderFilePath = String.format("%s/%s", mTestFolder.getRoot(),
|
||||||
|
"/product/overlay/partition_order.xml");
|
||||||
|
assertEquals(false, overlayConfig.sortPartitions(partitionOrderFilePath, partitions));
|
||||||
|
assertEquals("system, vendor, odm, oem, product, system_ext",
|
||||||
|
generatePartitionOrderString(partitions));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortPartitionsWithMissingPartition() throws IOException {
|
||||||
|
ArrayList<OverlayPartition> partitions = new ArrayList<>(
|
||||||
|
PackagePartitions.getOrderedPartitions(OverlayPartition::new));
|
||||||
|
createFile("/product/overlay/partition_order.xml",
|
||||||
|
"<partition-order>\n"
|
||||||
|
+ " <partition name=\"vendor\"/>\n"
|
||||||
|
+ " <partition name=\"oem\"/>\n"
|
||||||
|
+ " <partition name=\"odm\"/>\n"
|
||||||
|
+ " <partition name=\"product\"/>\n"
|
||||||
|
+ " <partition name=\"system\"/>\n"
|
||||||
|
+ "</partition-order>\n");
|
||||||
|
final OverlayConfig overlayConfig = createConfigImpl();
|
||||||
|
String partitionOrderFilePath = String.format("%s/%s", mTestFolder.getRoot(),
|
||||||
|
"/product/overlay/partition_order.xml");
|
||||||
|
assertEquals(false, overlayConfig.sortPartitions(partitionOrderFilePath, partitions));
|
||||||
|
assertEquals("system, vendor, odm, oem, product, system_ext",
|
||||||
|
generatePartitionOrderString(partitions));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortPartitionsWithCorrectPartitionOrderXml() throws IOException {
|
||||||
|
ArrayList<OverlayPartition> partitions = new ArrayList<>(
|
||||||
|
PackagePartitions.getOrderedPartitions(OverlayPartition::new));
|
||||||
|
createFile("/product/overlay/partition_order.xml",
|
||||||
|
"<partition-order>\n"
|
||||||
|
+ " <partition name=\"system_ext\"/>\n"
|
||||||
|
+ " <partition name=\"vendor\"/>\n"
|
||||||
|
+ " <partition name=\"oem\"/>\n"
|
||||||
|
+ " <partition name=\"odm\"/>\n"
|
||||||
|
+ " <partition name=\"product\"/>\n"
|
||||||
|
+ " <partition name=\"system\"/>\n"
|
||||||
|
+ "</partition-order>\n");
|
||||||
|
final OverlayConfig overlayConfig = createConfigImpl();
|
||||||
|
String partitionOrderFilePath = String.format("%s/%s", mTestFolder.getRoot(),
|
||||||
|
"/product/overlay/partition_order.xml");
|
||||||
|
assertEquals(true, overlayConfig.sortPartitions(partitionOrderFilePath, partitions));
|
||||||
|
assertEquals("system_ext, vendor, oem, odm, product, system",
|
||||||
|
generatePartitionOrderString(partitions));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1109,6 +1109,21 @@ public final class OverlayManagerService extends SystemService {
|
|||||||
int callingUid = Binder.getCallingUid();
|
int callingUid = Binder.getCallingUid();
|
||||||
mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, realUserId);
|
mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, realUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public String getPartitionOrder() {
|
||||||
|
return mImpl.getOverlayConfig().getPartitionOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isDefaultPartitionOrder() {
|
||||||
|
return mImpl.getOverlayConfig().isDefaultPartitionOrder();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final class PackageManagerHelperImpl implements PackageManagerHelper {
|
private static final class PackageManagerHelperImpl implements PackageManagerHelper {
|
||||||
|
|||||||
@@ -876,4 +876,8 @@ final class OverlayManagerServiceImpl {
|
|||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OverlayConfig getOverlayConfig() {
|
||||||
|
return mOverlayConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.server.om;
|
package com.android.server.om;
|
||||||
|
|
||||||
|
import static com.android.internal.content.om.OverlayConfig.PARTITION_ORDER_FILE_PATH;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -79,6 +81,8 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
|||||||
return runLookup();
|
return runLookup();
|
||||||
case "fabricate":
|
case "fabricate":
|
||||||
return runFabricate();
|
return runFabricate();
|
||||||
|
case "partition-order":
|
||||||
|
return runPartitionOrder();
|
||||||
default:
|
default:
|
||||||
return handleDefaultCommands(cmd);
|
return handleDefaultCommands(cmd);
|
||||||
}
|
}
|
||||||
@@ -130,6 +134,9 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
|||||||
out.println(" Create an overlay from a single resource. Caller must be root. Example:");
|
out.println(" Create an overlay from a single resource. Caller must be root. Example:");
|
||||||
out.println(" fabricate --target android --name LighterGray \\");
|
out.println(" fabricate --target android --name LighterGray \\");
|
||||||
out.println(" android:color/lighter_gray 0x1c 0xffeeeeee");
|
out.println(" android:color/lighter_gray 0x1c 0xffeeeeee");
|
||||||
|
out.println(" partition-order");
|
||||||
|
out.println(" Print the partition order from overlay config and how this order");
|
||||||
|
out.println(" got established, by default or by " + PARTITION_ORDER_FILE_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int runList() throws RemoteException {
|
private int runList() throws RemoteException {
|
||||||
@@ -230,6 +237,14 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int runPartitionOrder() throws RemoteException {
|
||||||
|
final PrintWriter out = getOutPrintWriter();
|
||||||
|
out.println("Partition order (low to high priority): " + mInterface.getPartitionOrder());
|
||||||
|
out.println("Established by " + (mInterface.isDefaultPartitionOrder() ? "default"
|
||||||
|
: PARTITION_ORDER_FILE_PATH));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private int runFabricate() throws RemoteException {
|
private int runFabricate() throws RemoteException {
|
||||||
final PrintWriter err = getErrPrintWriter();
|
final PrintWriter err = getErrPrintWriter();
|
||||||
if (Binder.getCallingUid() != Process.ROOT_UID) {
|
if (Binder.getCallingUid() != Process.ROOT_UID) {
|
||||||
|
|||||||
Reference in New Issue
Block a user