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

Commit 0d01987e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Statsd - adb cmd for AppHook; long compare support"

parents 0f919b18 b223c4ec
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
#include <utils/String16.h>
#include <statslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/system_properties.h>
@@ -235,6 +236,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>&
        if (!args[0].compare(String8("write-to-disk"))) {
            return cmd_write_data_to_disk(out);
        }

        if (!args[0].compare(String8("log-app-hook"))) {
            return cmd_log_app_hook(out, args);
        }
    }

    print_cmd_help(out);
@@ -272,6 +277,15 @@ void StatsService::print_cmd_help(FILE* out) {
    fprintf(out, "  Flushes all data on memory to disk.\n");
    fprintf(out, "\n");
    fprintf(out, "\n");
    fprintf(out, "usage: adb shell cmd stats log-app-hook [UID] LABEL STATE\n");
    fprintf(out, "  Writes an AppHook event to the statslog buffer.\n");
    fprintf(out, "  UID           The uid to use. It is only possible to pass a UID\n");
    fprintf(out, "                parameter on eng builds. If UID is omitted the calling\n");
    fprintf(out, "                uid is used.\n");
    fprintf(out, "  LABEL         Integer in [0, 15], as per atoms.proto.\n");
    fprintf(out, "  STATE         Integer in [0, 3], as per atoms.proto.\n");
    fprintf(out, "\n");
    fprintf(out, "\n");
    fprintf(out, "usage: adb shell cmd stats config remove [UID] [NAME]\n");
    fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
    fprintf(out, "\n");
@@ -523,6 +537,42 @@ status_t StatsService::cmd_write_data_to_disk(FILE* out) {
    return NO_ERROR;
}

status_t StatsService::cmd_log_app_hook(FILE* out, const Vector<String8>& args) {
    bool good = false;
    int32_t uid;
    int32_t label;
    int32_t state;
    const int argCount = args.size();
    if (argCount == 3) {
        // Automatically pick the UID
        uid = IPCThreadState::self()->getCallingUid();
        label = atoi(args[1].c_str());
        state = atoi(args[2].c_str());
        good = true;
    } else if (argCount == 4) {
        uid = atoi(args[1].c_str());
        // If it's a userdebug or eng build, then the shell user can impersonate other uids.
        // Otherwise, the uid must match the actual caller's uid.
        if (mEngBuild || (uid >= 0 && (uid_t)uid == IPCThreadState::self()->getCallingUid())) {
            label = atoi(args[2].c_str());
            state = atoi(args[3].c_str());
            good = true;
        } else {
            fprintf(out,
                    "Selecting a UID for writing AppHook can only be dumped for other UIDs on eng"
                            " or userdebug builds.\n");
        }
    }
    if (good) {
        fprintf(out, "Logging AppHook(%d, %d, %d) to statslog.\n", uid, label, state);
        android::util::stats_write(android::util::APP_HOOK, uid, label, state);
    } else {
        print_cmd_help(out);
        return UNKNOWN_ERROR;
    }
    return NO_ERROR;
}

status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) {
    int s = atoi(args[1].c_str());
    vector<shared_ptr<LogEvent> > stats;
+5 −0
Original line number Diff line number Diff line
@@ -182,6 +182,11 @@ private:
     */
    status_t cmd_write_data_to_disk(FILE* out);

    /**
     * Write an AppHook event to the StatsLog buffer, as though StatsLog.write(APP_HOOK).
     */
    status_t cmd_log_app_hook(FILE* out, const Vector<String8>& args);

    /**
     * Print contents of a pulled metrics source.
     */
+53 −36
Original line number Diff line number Diff line
@@ -129,12 +129,12 @@ bool matchesNonRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap
        }
        bool matched = false;
        switch (matcher.value_matcher_case()) {
            case FieldValueMatcher::ValueMatcherCase::kEqBool:
            case FieldValueMatcher::ValueMatcherCase::kEqBool: {
                // Logd does not support bool, it is int instead.
                matched = ((ret.first->second.value_int() > 0) == matcher.eq_bool());
                break;
            case FieldValueMatcher::ValueMatcherCase::kEqString:
                 {
            }
            case FieldValueMatcher::ValueMatcherCase::kEqString: {
                if (IsAttributionUidField(*rootField)) {
                    const int uid = ret.first->second.value_int();
                    std::set<string> packageNames =
@@ -143,29 +143,46 @@ bool matchesNonRepeatedField(const UidMap& uidMap, const FieldValueMap& fieldMap
                } else {
                    matched = (ret.first->second.value_str() == matcher.eq_string());
                }
                 }
                break;
            case FieldValueMatcher::ValueMatcherCase::kEqInt:
                 matched = (ret.first->second.value_int() == matcher.eq_int());
            }
            case FieldValueMatcher::ValueMatcherCase::kEqInt: {
                    int64_t val = ret.first->second.has_value_int() ?
                                  ret.first->second.value_int() : ret.first->second.value_long();
                    matched = (val == matcher.eq_int());
                break;
            case FieldValueMatcher::ValueMatcherCase::kLtInt:
                 matched = (ret.first->second.value_int() < matcher.lt_int());
            }
            case FieldValueMatcher::ValueMatcherCase::kLtInt: {
                int64_t val = ret.first->second.has_value_int() ?
                              ret.first->second.value_int() : ret.first->second.value_long();
                matched = (val < matcher.lt_int());
                break;
            case FieldValueMatcher::ValueMatcherCase::kGtInt:
                 matched = (ret.first->second.value_int() > matcher.gt_int());
            }
            case FieldValueMatcher::ValueMatcherCase::kGtInt: {
                int64_t val = ret.first->second.has_value_int() ?
                              ret.first->second.value_int() : ret.first->second.value_long();
                matched = (val > matcher.gt_int());
                break;
            case FieldValueMatcher::ValueMatcherCase::kLtFloat:
            }
            case FieldValueMatcher::ValueMatcherCase::kLtFloat: {
                matched = (ret.first->second.value_float() < matcher.lt_float());
                break;
            case FieldValueMatcher::ValueMatcherCase::kGtFloat:
            }
            case FieldValueMatcher::ValueMatcherCase::kGtFloat: {
                matched = (ret.first->second.value_float() > matcher.gt_float());
                break;
            case FieldValueMatcher::ValueMatcherCase::kLteInt:
                 matched = (ret.first->second.value_int() <= matcher.lte_int());
            }
            case FieldValueMatcher::ValueMatcherCase::kLteInt: {
                int64_t val = ret.first->second.has_value_int() ?
                              ret.first->second.value_int() : ret.first->second.value_long();
                matched = (val <= matcher.lte_int());
                break;
            case FieldValueMatcher::ValueMatcherCase::kGteInt:
                 matched = (ret.first->second.value_int() >= matcher.gte_int());
            }
            case FieldValueMatcher::ValueMatcherCase::kGteInt: {
                int64_t val = ret.first->second.has_value_int() ?
                              ret.first->second.value_int() : ret.first->second.value_long();
                matched = (val >= matcher.gte_int());
                break;
            }
            default:
                break;
        }
+29 −8
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ const int FIELD_ID_METRICS = 1;

MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
                               const long timeBaseSec, sp<UidMap> uidMap)
    : mConfigKey(key), mUidMap(uidMap) {
    : mConfigKey(key), mUidMap(uidMap), mStatsdUid(getStatsdUid()) {
    mConfigValid =
            initStatsdConfig(key, config, *uidMap, timeBaseSec, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
                             mAllMetricProducers, mAllAnomalyTrackers, mConditionToMetricMap,
@@ -61,6 +61,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,

        mAllowedUid.push_back(1000);
        mAllowedUid.push_back(0);
        mAllowedUid.push_back(mStatsdUid);
        mAllowedLogSources.insert(mAllowedUid.begin(), mAllowedUid.end());
    } else {
        for (const auto& source : config.allowed_log_source()) {
@@ -191,18 +192,28 @@ void MetricsManager::onLogEvent(const LogEvent& event) {

    if (event.GetTagId() == android::util::APP_HOOK) { // Check that app hook fields are valid.
        // TODO: Find a way to make these checks easier to maintain if the app hooks get changed.
        status_t err = NO_ERROR;

        // Uid is 3rd from last field and must match the caller's uid,
        // unless that caller is statsd itself (statsd is allowed to spoof uids).
        long appHookUid = event.GetLong(event.size()-2, &err);
        int32_t loggerUid = event.GetUid();
        if (err != NO_ERROR || (loggerUid != appHookUid && loggerUid != mStatsdUid)) {
            VLOG("AppHook has invalid uid: claimed %ld but caller is %d", appHookUid, loggerUid);
            return;
        }

        // Label is 2nd from last field and must be from [0, 15].
        status_t err = NO_ERROR;
        long label = event.GetLong(event.size()-1, &err);
        if (err != NO_ERROR || label < 0 || label > 15) {
            VLOG("App hook does not have valid label %ld", label);
        long appHookLabel = event.GetLong(event.size()-1, &err);
        if (err != NO_ERROR || appHookLabel < 0 || appHookLabel > 15) {
            VLOG("AppHook does not have valid label %ld", appHookLabel);
            return;
        }

        // The state must be from 0,3. This part of code must be manually updated.
        long apphookState = event.GetLong(event.size(), &err);
        if (err != NO_ERROR || apphookState < 0 || apphookState > 3) {
            VLOG("App hook does not have valid state %ld", apphookState);
        long appHookState = event.GetLong(event.size(), &err);
        if (err != NO_ERROR || appHookState < 0 || appHookState > 3) {
            VLOG("AppHook does not have valid state %ld", appHookState);
            return;
        }
    } else if (event.GetTagId() == android::util::DAVEY_OCCURRED) {
@@ -322,6 +333,16 @@ size_t MetricsManager::byteSize() {
    return totalSize;
}

int32_t MetricsManager::getStatsdUid() {
    auto suit = UidMap::sAidToUidMapping.find("AID_STATSD");
    if (suit != UidMap::sAidToUidMapping.end()) {
        return suit->second;
    } else {
        ALOGE("Statsd failed to find its own uid!");
        return -1;
    }
}

}  // namespace statsd
}  // namespace os
}  // namespace android
+6 −0
Original line number Diff line number Diff line
@@ -75,6 +75,9 @@ private:

    sp<UidMap> mUidMap;

    // The uid of statsd.
    const int32_t mStatsdUid;

    bool mConfigValid = false;

    // The uid log sources from StatsdConfig.
@@ -136,6 +139,9 @@ private:

    void initLogSourceWhiteList();

    // Fetches the uid of statsd from UidMap.
    static int32_t getStatsdUid();

    // The metrics that don't need to be uploaded or even reported.
    std::set<int64_t> mNoReportMetricIds;

Loading