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

Commit 3775b06f authored by Tej Singh's avatar Tej Singh
Browse files

Enforce duration metric dimension rules

Dimension_in_what, condition links, and state links should be a subset
of the dimensions in what.

Test: atest statsd_test
Bug: 167491517
Change-Id: Ibd776829e975f04bd3c992fa7c299f017801c948
parent b5e682ef
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -107,6 +107,12 @@ DurationMetricProducer::DurationMetricProducer(
        ALOGE("Position ANY in dimension_in_what not supported.");
    }

    // Dimensions in what must be subset of internal dimensions
    if (!subsetDimensions(mDimensionsInWhat, mInternalDimensions)) {
        ALOGE("Dimensions in what must be a subset of the internal dimensions");
        mValid = false;
    }

    mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what());

    if (metric.links().size() > 0) {
@@ -115,6 +121,10 @@ DurationMetricProducer::DurationMetricProducer(
            mc.conditionId = link.condition();
            translateFieldMatcher(link.fields_in_what(), &mc.metricFields);
            translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields);
            if (!subsetDimensions(mc.metricFields, mInternalDimensions)) {
                ALOGE(("Condition links must be a subset of the internal dimensions"));
                mValid = false;
            }
            mMetric2ConditionLinks.push_back(mc);
        }
        mConditionSliced = true;
@@ -126,6 +136,10 @@ DurationMetricProducer::DurationMetricProducer(
        ms.stateAtomId = stateLink.state_atom_id();
        translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
        translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
        if (!subsetDimensions(ms.metricFields, mInternalDimensions)) {
            ALOGE(("State links must be a subset of the dimensions in what  internal dimensions"));
            mValid = false;
        }
        mMetric2StateLinks.push_back(ms);
    }

+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ MetricProducer::MetricProducer(
    : mMetricId(metricId),
      mProtoHash(protoHash),
      mConfigKey(key),
      mValid(true),
      mTimeBaseNs(timeBaseNs),
      mCurrentBucketStartTimeNs(timeBaseNs),
      mCurrentBucketNum(0),
+6 −0
Original line number Diff line number Diff line
@@ -336,6 +336,10 @@ public:
        return mSlicedStateAtoms;
    }

    inline bool isValid() const {
        return mValid;
    }

    /* Adds an AnomalyTracker and returns it. */
    virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
                                                 const sp<AlarmMonitor>& anomalyAlarmMonitor) {
@@ -468,6 +472,8 @@ protected:

    const ConfigKey mConfigKey;

    bool mValid;

    // The time when this metric producer was first created. The end time for the current bucket
    // can be computed from this based on mCurrentBucketNum.
    int64_t mTimeBaseNs;
+11 −5
Original line number Diff line number Diff line
@@ -519,6 +519,7 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
    translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
    for (const auto& stateLink : metric.state_link()) {
        if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
            ALOGW("DurationMetric's MetricStateLinks must be a subset of dimensions in what");
            return nullopt;
        }
    }
@@ -537,11 +538,15 @@ optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
        return nullopt;
    }

    return {new DurationMetricProducer(key, metric, conditionIndex, initialConditionCache,
                                       whatIndex, startIndex, stopIndex, stopAllIndex, nesting,
                                       wizard, metricHash, internalDimensions, timeBaseNs,
                                       currentTimeNs, eventActivationMap, eventDeactivationMap,
                                       slicedStateAtoms, stateGroupMap)};
    sp<MetricProducer> producer = new DurationMetricProducer(
            key, metric, conditionIndex, initialConditionCache, whatIndex, startIndex, stopIndex,
            stopAllIndex, nesting, wizard, metricHash, internalDimensions, timeBaseNs,
            currentTimeNs, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
            stateGroupMap);
    if (!producer->isValid()) {
        return nullopt;
    }
    return {producer};
}

optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
@@ -679,6 +684,7 @@ optional<sp<MetricProducer>> createValueMetricProducerAndUpdateMetadata(
    translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
    for (const auto& stateLink : metric.state_link()) {
        if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
            ALOGW("ValueMetric's MetricStateLinks must be a subset of the dimensions in what");
            return nullopt;
        }
    }
+13 −10
Original line number Diff line number Diff line
@@ -486,11 +486,11 @@ TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
    // Links between wakelock state atom and condition of app is in background.
    auto links = durationMetric->add_links();
    links->set_condition(isInBackgroundPredicate.id());
    auto dimensionWhat = links->mutable_fields_in_what();
    dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED);
    dimensionWhat->add_child()->set_field(1);  // uid field.
    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
            util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
    *links->mutable_fields_in_what() =
            CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
    auto dimensionCondition = links->mutable_fields_in_condition();
    dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
    dimensionCondition->add_child()->set_field(1);  // uid field.

    ConfigKey cfgKey;
    uint64_t bucketStartTimeNs = 10000000000;
@@ -591,11 +591,11 @@ TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
    // Links between wakelock state atom and condition of app is in background.
    auto links = durationMetric->add_links();
    links->set_condition(isInBackgroundPredicate.id());
    auto dimensionWhat = links->mutable_fields_in_what();
    dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED);
    dimensionWhat->add_child()->set_field(1);  // uid field.
    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
            util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
    *links->mutable_fields_in_what() =
            CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
    auto dimensionCondition = links->mutable_fields_in_condition();
    dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
    dimensionCondition->add_child()->set_field(1);  // uid field.

    auto metric_activation1 = config.add_metric_activation();
    metric_activation1->set_metric_id(durationMetric->id());
@@ -1228,6 +1228,9 @@ TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset) {
    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();

    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
    *(holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions()) =
            CreateAttributionUidAndOtherDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST},
                                                   {3 /* tag */});
    *config.add_predicate() = holdingWakelockPredicate;

    auto uidProcessState = CreateUidProcessState();
Loading