Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7a302e9 authored by Max Loh's avatar Max Loh
Browse files

ASL update fields to finalized declarations, part 1

Includes: system_app_safety_label change to declaration, data labels ephemeral change, data labels category/type name consolidation

Bug: b/329902686
Test: Unit tests
Change-Id: I74ce395ca14209eeedd05af7f18f9152f35ba605
parent d30e9888
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.asllib.util.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@@ -40,6 +41,11 @@ public class DataCategory implements AslMarshallable {
        this.mDataTypes = dataTypes;
    }

    public DataCategory(String categoryName) {
        this.mCategoryName = categoryName;
        this.mDataTypes = new LinkedHashMap<String, DataType>();
    }

    public String getCategoryName() {
        return mCategoryName;
    }
+1 −26
Original line number Diff line number Diff line
@@ -26,33 +26,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class DataCategoryFactory implements AslMarshallableFactory<DataCategory> {
    @Override
    public DataCategory createFromHrElements(List<Element> elements) throws MalformedXmlException {
        String categoryName = null;
        Map<String, DataType> dataTypeMap = new LinkedHashMap<String, DataType>();
        for (Element ele : elements) {
            categoryName = XmlUtils.getStringAttr(ele, XmlUtils.HR_ATTR_DATA_CATEGORY, true);
            String dataTypeName = XmlUtils.getStringAttr(ele, XmlUtils.HR_ATTR_DATA_TYPE, true);
            if (!DataTypeConstants.getValidDataTypes().containsKey(categoryName)) {
                throw new MalformedXmlException(
                        String.format("Unrecognized data category %s", categoryName));
            }
            if (!DataTypeConstants.getValidDataTypes().get(categoryName).contains(dataTypeName)) {
                throw new MalformedXmlException(
                        String.format(
                                "Unrecognized data type name %s for category %s",
                                dataTypeName, categoryName));
            }
            dataTypeMap.put(
                    dataTypeName, new DataTypeFactory().createFromHrElements(XmlUtils.listOf(ele)));
        }

        return new DataCategory(categoryName, dataTypeMap);
    }

public class DataCategoryFactory {
    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
    @Override
    public DataCategory createFromOdElements(List<Element> elements) throws MalformedXmlException {
        Element dataCategoryEle = XmlUtils.getSingleElement(elements);
        Map<String, DataType> dataTypeMap = new LinkedHashMap<String, DataType>();
+16 −21
Original line number Diff line number Diff line
@@ -30,27 +30,16 @@ import java.util.Map;
 * DataCategory}
 */
public class DataLabels implements AslMarshallable {
    private final Map<String, DataCategory> mDataAccessed;
    private final Map<String, DataCategory> mDataCollected;
    private final Map<String, DataCategory> mDataShared;

    public DataLabels(
            Map<String, DataCategory> dataAccessed,
            Map<String, DataCategory> dataCollected,
            Map<String, DataCategory> dataShared) {
        mDataAccessed = dataAccessed;
        mDataCollected = dataCollected;
        mDataShared = dataShared;
    }

    /**
     * Returns the data accessed {@link Map} of {@link DataCategoryConstants} to {@link
     * DataCategory}
     */
    public Map<String, DataCategory> getDataAccessed() {
        return mDataAccessed;
    }

    /**
     * Returns the data collected {@link Map} of {@link DataCategoryConstants} to {@link
     * DataCategory}
@@ -72,7 +61,6 @@ public class DataLabels implements AslMarshallable {
        Element dataLabelsEle =
                XmlUtils.createPbundleEleWithName(doc, XmlUtils.OD_NAME_DATA_LABELS);

        maybeAppendDataUsages(doc, dataLabelsEle, mDataAccessed, XmlUtils.OD_NAME_DATA_ACCESSED);
        maybeAppendDataUsages(doc, dataLabelsEle, mDataCollected, XmlUtils.OD_NAME_DATA_COLLECTED);
        maybeAppendDataUsages(doc, dataLabelsEle, mDataShared, XmlUtils.OD_NAME_DATA_SHARED);

@@ -83,9 +71,12 @@ public class DataLabels implements AslMarshallable {
    @Override
    public List<Element> toHrDomElements(Document doc) {
        Element dataLabelsEle = doc.createElement(XmlUtils.HR_TAG_DATA_LABELS);
        maybeAppendHrDataUsages(doc, dataLabelsEle, mDataAccessed, XmlUtils.HR_TAG_DATA_ACCESSED);
        maybeAppendHrDataUsages(doc, dataLabelsEle, mDataCollected, XmlUtils.HR_TAG_DATA_COLLECTED);
        maybeAppendHrDataUsages(doc, dataLabelsEle, mDataShared, XmlUtils.HR_TAG_DATA_SHARED);
        maybeAppendHrDataUsages(
                doc, dataLabelsEle, mDataCollected, XmlUtils.HR_TAG_DATA_COLLECTED, false);
        maybeAppendHrDataUsages(
                doc, dataLabelsEle, mDataCollected, XmlUtils.HR_TAG_DATA_COLLECTED_EPHEMERAL, true);
        maybeAppendHrDataUsages(
                doc, dataLabelsEle, mDataShared, XmlUtils.HR_TAG_DATA_SHARED, false);
        return XmlUtils.listOf(dataLabelsEle);
    }

@@ -115,7 +106,8 @@ public class DataLabels implements AslMarshallable {
            Document doc,
            Element dataLabelsEle,
            Map<String, DataCategory> dataCategoriesMap,
            String dataUsageTypeName) {
            String dataUsageTypeName,
            boolean ephemeral) {
        if (dataCategoriesMap.isEmpty()) {
            return;
        }
@@ -123,10 +115,15 @@ public class DataLabels implements AslMarshallable {
            DataCategory dataCategory = dataCategoriesMap.get(dataCategoryName);
            for (String dataTypeName : dataCategory.getDataTypes().keySet()) {
                DataType dataType = dataCategory.getDataTypes().get(dataTypeName);
                // XmlUtils.appendChildren(dataLabelsEle, dataType.toHrDomElements(doc));
                if (ephemeral
                        != (dataType.getEphemeral() != null ? dataType.getEphemeral() : false)) {
                    continue;
                }

                Element hrDataTypeEle = doc.createElement(dataUsageTypeName);
                hrDataTypeEle.setAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY, dataCategoryName);
                hrDataTypeEle.setAttribute(XmlUtils.HR_ATTR_DATA_TYPE, dataTypeName);
                hrDataTypeEle.setAttribute(
                        XmlUtils.HR_ATTR_DATA_TYPE,
                        dataCategoryName + XmlUtils.DATA_TYPE_SEPARATOR + dataTypeName);
                XmlUtils.maybeSetHrBoolAttr(
                        hrDataTypeEle,
                        XmlUtils.HR_ATTR_IS_COLLECTION_OPTIONAL,
@@ -135,8 +132,6 @@ public class DataLabels implements AslMarshallable {
                        hrDataTypeEle,
                        XmlUtils.HR_ATTR_IS_SHARING_OPTIONAL,
                        dataType.getIsSharingOptional());
                XmlUtils.maybeSetHrBoolAttr(
                        hrDataTypeEle, XmlUtils.HR_ATTR_EPHEMERAL, dataType.getEphemeral());
                hrDataTypeEle.setAttribute(
                        XmlUtils.HR_ATTR_PURPOSES,
                        String.join(
+74 −44
Original line number Diff line number Diff line
@@ -18,16 +18,15 @@ package com.android.asllib.marshallable;

import com.android.asllib.util.AslgenUtil;
import com.android.asllib.util.DataCategoryConstants;
import com.android.asllib.util.DataTypeConstants;
import com.android.asllib.util.MalformedXmlException;
import com.android.asllib.util.XmlUtils;

import org.w3c.dom.Element;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class DataLabelsFactory implements AslMarshallableFactory<DataLabels> {

@@ -39,13 +38,46 @@ public class DataLabelsFactory implements AslMarshallableFactory<DataLabels> {
            AslgenUtil.logI("Found no DataLabels in hr format.");
            return null;
        }
        Map<String, DataCategory> dataAccessed =
                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_ACCESSED);
        Map<String, DataCategory> dataCollected =
                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_COLLECTED);
                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_COLLECTED, false);
        Map<String, DataCategory> dataCollectedEphemeral =
                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_COLLECTED_EPHEMERAL, true);
        Map<String, DataCategory> dataShared =
                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_SHARED);
        DataLabels dataLabels = new DataLabels(dataAccessed, dataCollected, dataShared);
                getDataCategoriesWithTag(ele, XmlUtils.HR_TAG_DATA_SHARED, null);

        for (String dataCollectedEphemeralDataCategoryKey : dataCollectedEphemeral.keySet()) {
            DataCategory dataCategoryEphemeral =
                    dataCollectedEphemeral.get(dataCollectedEphemeralDataCategoryKey);
            for (String dataCollectedEphemeralDataTypeKey :
                    dataCategoryEphemeral.getDataTypes().keySet()) {
                if (dataCollected.containsKey(dataCollectedEphemeralDataCategoryKey)
                        && dataCollected
                                .get(dataCollectedEphemeralDataCategoryKey)
                                .getDataTypes()
                                .containsKey(dataCollectedEphemeralDataTypeKey)) {
                    throw new MalformedXmlException(
                            String.format(
                                    "Duplicate entries in data-collected and"
                                            + " data-collected-ephemeral: %s %s",
                                    dataCollectedEphemeralDataCategoryKey,
                                    dataCollectedEphemeralDataTypeKey));
                }

                if (!dataCollected.containsKey(dataCollectedEphemeralDataCategoryKey)) {
                    dataCollected.put(
                            dataCollectedEphemeralDataCategoryKey,
                            new DataCategory(dataCollectedEphemeralDataCategoryKey));
                }
                DataType dataTypeEphemeral =
                        dataCategoryEphemeral.getDataTypes().get(dataCollectedEphemeralDataTypeKey);
                dataCollected
                        .get(dataCollectedEphemeralDataCategoryKey)
                        .getDataTypes()
                        .put(dataCollectedEphemeralDataTypeKey, dataTypeEphemeral);
            }
        }
        DataLabels dataLabels = new DataLabels(dataCollected, dataShared);

        validateIsXOptional(dataLabels);
        return dataLabels;
    }
@@ -58,13 +90,11 @@ public class DataLabelsFactory implements AslMarshallableFactory<DataLabels> {
            AslgenUtil.logI("Found no DataLabels in od format.");
            return null;
        }
        Map<String, DataCategory> dataAccessed =
                getOdDataCategoriesWithTag(dataLabelsEle, XmlUtils.OD_NAME_DATA_ACCESSED);
        Map<String, DataCategory> dataCollected =
                getOdDataCategoriesWithTag(dataLabelsEle, XmlUtils.OD_NAME_DATA_COLLECTED);
        Map<String, DataCategory> dataShared =
                getOdDataCategoriesWithTag(dataLabelsEle, XmlUtils.OD_NAME_DATA_SHARED);
        DataLabels dataLabels = new DataLabels(dataAccessed, dataCollected, dataShared);
        DataLabels dataLabels = new DataLabels(dataCollected, dataShared);
        validateIsXOptional(dataLabels);
        return dataLabels;
    }
@@ -88,56 +118,56 @@ public class DataLabelsFactory implements AslMarshallableFactory<DataLabels> {
    }

    private static Map<String, DataCategory> getDataCategoriesWithTag(
            Element dataLabelsEle, String dataCategoryUsageTypeTag) throws MalformedXmlException {
            Element dataLabelsEle, String dataCategoryUsageTypeTag, Boolean ephemeral)
            throws MalformedXmlException {
        List<Element> dataUsedElements =
                XmlUtils.getChildrenByTagName(dataLabelsEle, dataCategoryUsageTypeTag);
        Map<String, DataCategory> dataCategoryMap = new LinkedHashMap<String, DataCategory>();

        Set<String> dataCategoryNames = new HashSet<String>();
        for (int i = 0; i < dataUsedElements.size(); i++) {
            Element dataUsedEle = dataUsedElements.get(i);
            String dataCategoryName = dataUsedEle.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY);
            String dataCategoryAndTypeCombinedStr =
                    dataUsedEle.getAttribute(XmlUtils.HR_ATTR_DATA_TYPE);
            String[] strs = dataCategoryAndTypeCombinedStr.split(XmlUtils.DATA_TYPE_SEPARATOR);
            if (strs.length != 2) {
                throw new MalformedXmlException(
                        String.format(
                                "Could not parse human-readable data type string (expecting"
                                        + " substring of _data_type_): %s",
                                dataCategoryAndTypeCombinedStr));
            }
            String dataCategoryName = strs[0];
            String dataTypeName = strs[1];

            if (!DataCategoryConstants.getValidDataCategories().contains(dataCategoryName)) {
                throw new MalformedXmlException(
                        String.format("Unrecognized category name: %s", dataCategoryName));
            }
            dataCategoryNames.add(dataCategoryName);
            if (!DataTypeConstants.getValidDataTypes()
                    .get(dataCategoryName)
                    .contains(dataTypeName)) {
                throw new MalformedXmlException(
                        String.format(
                                "Unrecognized data type name %s for category %s",
                                dataTypeName, dataCategoryName));
            }
        for (String dataCategoryName : dataCategoryNames) {
            var dataCategoryElements =
                    dataUsedElements.stream()
                            .filter(
                                    ele ->
                                            ele.getAttribute(XmlUtils.HR_ATTR_DATA_CATEGORY)
                                                    .equals(dataCategoryName))
                            .toList();
            DataCategory dataCategory =
                    new DataCategoryFactory().createFromHrElements(dataCategoryElements);
            dataCategoryMap.put(dataCategoryName, dataCategory);

            if (!dataCategoryMap.containsKey(dataCategoryName)) {
                dataCategoryMap.put(dataCategoryName, new DataCategory(dataCategoryName));
            }
            dataCategoryMap
                    .get(dataCategoryName)
                    .getDataTypes()
                    .put(
                            dataTypeName,
                            new DataTypeFactory().createFromHrElements(dataUsedEle, ephemeral));
        }

        return dataCategoryMap;
    }

    private void validateIsXOptional(DataLabels dataLabels) throws MalformedXmlException {
        // Validate booleans such as isCollectionOptional, isSharingOptional.
        for (DataCategory dataCategory : dataLabels.getDataAccessed().values()) {
            for (DataType dataType : dataCategory.getDataTypes().values()) {
                if (dataType.getIsSharingOptional() != null) {
                    throw new MalformedXmlException(
                            String.format(
                                    "isSharingOptional was unexpectedly defined on a DataType"
                                            + " belonging to data accessed: %s",
                                    dataType.getDataTypeName()));
                }
                if (dataType.getIsCollectionOptional() != null) {
                    throw new MalformedXmlException(
                            String.format(
                                    "isCollectionOptional was unexpectedly defined on a DataType"
                                            + " belonging to data accessed: %s",
                                    dataType.getDataTypeName()));
                }
            }
        }
        for (DataCategory dataCategory : dataLabels.getDataCollected().values()) {
            for (DataType dataType : dataCategory.getDataTypes().values()) {
                if (dataType.getIsSharingOptional() != null) {
+17 −7
Original line number Diff line number Diff line
@@ -25,12 +25,22 @@ import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

public class DataTypeFactory implements AslMarshallableFactory<DataType> {
public class DataTypeFactory {
    /** Creates a {@link DataType} from the human-readable DOM element. */
    @Override
    public DataType createFromHrElements(List<Element> elements) throws MalformedXmlException {
        Element hrDataTypeEle = XmlUtils.getSingleElement(elements);
        String dataTypeName = hrDataTypeEle.getAttribute(XmlUtils.HR_ATTR_DATA_TYPE);
    public DataType createFromHrElements(Element hrDataTypeEle, Boolean ephemeral)
            throws MalformedXmlException {
        String dataCategoryAndTypeCombinedStr =
                hrDataTypeEle.getAttribute(XmlUtils.HR_ATTR_DATA_TYPE);
        String[] strs = dataCategoryAndTypeCombinedStr.split(XmlUtils.DATA_TYPE_SEPARATOR);
        if (strs.length != 2) {
            throw new MalformedXmlException(
                    String.format(
                            "Could not parse human-readable data type string (expecting substring"
                                    + " of _data_type_): %s",
                            dataCategoryAndTypeCombinedStr));
        }
        String dataTypeName = strs[1];

        List<DataType.Purpose> purposes =
                XmlUtils.getPipelineSplitAttr(hrDataTypeEle, XmlUtils.HR_ATTR_PURPOSES, true)
                        .stream()
@@ -47,13 +57,13 @@ public class DataTypeFactory implements AslMarshallableFactory<DataType> {
                XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_IS_COLLECTION_OPTIONAL, false);
        Boolean isSharingOptional =
                XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_IS_SHARING_OPTIONAL, false);
        Boolean ephemeral = XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_EPHEMERAL, false);
        // Boolean ephemeral = XmlUtils.getBoolAttr(hrDataTypeEle, XmlUtils.HR_ATTR_EPHEMERAL,
        // false);
        return new DataType(
                dataTypeName, purposes, isCollectionOptional, isSharingOptional, ephemeral);
    }

    /** Creates an {@link AslMarshallableFactory} from on-device DOM elements */
    @Override
    public DataType createFromOdElements(List<Element> elements) throws MalformedXmlException {
        Element odDataTypeEle = XmlUtils.getSingleElement(elements);
        String dataTypeName = odDataTypeEle.getAttribute(XmlUtils.OD_ATTR_NAME);
Loading