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

Commit 769f35fc authored by Tej Singh's avatar Tej Singh
Browse files

Add NamedLatch to statsd

This is a sychronizing primitive that is similar to a latch, but a
thread must count down with an identifier. It will be used to make sure
the boot complete, uid map, and all pullers signals are received before
triggering the bucket split.

The latch's countDown operation takes in a string identifier, so that if
the same operation happens twice, it is only counted once.

Bug: 144099206
Test: atest statsd_test

Change-Id: I261a3e50eabbc4998ca30ddf2d67a9a1e788911e
parent 1dcd8f41
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ cc_defaults {
        "src/subscriber/IncidentdReporter.cpp",
        "src/subscriber/SubscriberReporter.cpp",
        "src/uid_data.proto",
        "src/utils/NamedLatch.cpp",
    ],

    local_include_dirs: [
@@ -361,6 +362,7 @@ cc_test {
        "tests/StatsService_test.cpp",
        "tests/storage/StorageManager_test.cpp",
        "tests/UidMap_test.cpp",
        "tests/utils/NamedLatch_test.cpp",
    ],

    static_libs: [
+12 −4
Original line number Diff line number Diff line
@@ -118,8 +118,9 @@ StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQ
                  }
              })),
      mEventQueue(queue),
      mStatsCompanionServiceDeathRecipient(AIBinder_DeathRecipient_new(
              StatsService::statsCompanionServiceDied)) {
      mBootCompleteLatch({kBootCompleteTag, kUidMapReceivedTag, kAllPullersRegisteredTag}),
      mStatsCompanionServiceDeathRecipient(
              AIBinder_DeathRecipient_new(StatsService::statsCompanionServiceDied)) {
    mUidMap = UidMap::getInstance();
    mPullerManager = new StatsPullerManager();
    StatsPuller::SetUidMap(mUidMap);
@@ -164,6 +165,12 @@ StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQ
        std::thread pushedEventThread([this] { readLogs(); });
        pushedEventThread.detach();
    }

    std::thread bootCompletedThread([this] {
        mBootCompleteLatch.wait();
        VLOG("In the boot completed thread");
    });
    bootCompletedThread.detach();
}

StatsService::~StatsService() {
@@ -939,6 +946,7 @@ Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
                       packageNames,
                       installers);

    mBootCompleteLatch.countDown(kUidMapReceivedTag);
    VLOG("StatsService::informAllUidData UidData proto parsed successfully.");
    return Status::ok();
}
@@ -1058,7 +1066,7 @@ Status StatsService::bootCompleted() {
    ENFORCE_UID(AID_SYSTEM);

    VLOG("StatsService::bootCompleted was called");

    mBootCompleteLatch.countDown(kBootCompleteTag);
    return Status::ok();
}

@@ -1227,7 +1235,7 @@ Status StatsService::allPullersFromBootRegistered() {
    ENFORCE_UID(AID_SYSTEM);

    VLOG("StatsService::allPullersFromBootRegistered was called");

    mBootCompleteLatch.countDown(kAllPullersRegisteredTag);
    return Status::ok();
}

+13 −7
Original line number Diff line number Diff line
@@ -17,7 +17,14 @@
#ifndef STATS_SERVICE_H
#define STATS_SERVICE_H

#include <aidl/android/os/BnStatsd.h>
#include <aidl/android/os/IPendingIntentRef.h>
#include <aidl/android/os/IPullAtomCallback.h>
#include <gtest/gtest_prod.h>
#include <utils/Looper.h>

#include <mutex>

#include "StatsLogProcessor.h"
#include "anomaly/AlarmMonitor.h"
#include "config/ConfigManager.h"
@@ -26,13 +33,7 @@
#include "packages/UidMap.h"
#include "shell/ShellSubscriber.h"
#include "statscompanion_util.h"

#include <aidl/android/os/BnStatsd.h>
#include <aidl/android/os/IPendingIntentRef.h>
#include <aidl/android/os/IPullAtomCallback.h>
#include <utils/Looper.h>

#include <mutex>
#include "utils/NamedLatch.h"

using namespace android;
using namespace android::os;
@@ -385,6 +386,11 @@ private:
    mutable mutex mShellSubscriberMutex;
    std::shared_ptr<LogEventQueue> mEventQueue;

    NamedLatch mBootCompleteLatch;
    static const inline string kBootCompleteTag = "BOOT_COMPLETE";
    static const inline string kUidMapReceivedTag = "UID_MAP";
    static const inline string kAllPullersRegisteredTag = "PULLERS_REGISTERED";

    ScopedAIBinder_DeathRecipient mStatsCompanionServiceDeathRecipient;

    FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define DEBUG false  // STOPSHIP if true

#include "NamedLatch.h"

using namespace std;

namespace android {
namespace os {
namespace statsd {

NamedLatch::NamedLatch(const set<string>& eventNames) : mRemainingEventNames(eventNames) {
}

void NamedLatch::countDown(const string& eventName) {
    bool notify = false;
    {
        lock_guard<mutex> lg(mMutex);
        mRemainingEventNames.erase(eventName);
        notify = mRemainingEventNames.empty();
    }
    if (notify) {
        mConditionVariable.notify_all();
    }
}

void NamedLatch::wait() const {
    unique_lock<mutex> unique_lk(mMutex);
    mConditionVariable.wait(unique_lk, [this] { return mRemainingEventNames.empty(); });
}

}  // namespace statsd
}  // namespace os
}  // namespace android
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <gtest/gtest_prod.h>

#include <condition_variable>
#include <mutex>
#include <set>

namespace android {
namespace os {
namespace statsd {

/**
 * This class provides a threading primitive similar to a latch.
 * The primary difference is that it waits for named events to occur instead of waiting for
 * N threads to reach a certain point.
 *
 * It uses a condition variable under the hood.
 */
class NamedLatch {
public:
    explicit NamedLatch(const std::set<std::string>& eventNames);

    NamedLatch(const NamedLatch&) = delete;
    NamedLatch& operator=(const NamedLatch&) = delete;

    // Mark a specific event as completed. If this event has called countDown already or if the
    // event was not specified in the constructor, the function is a no-op.
    void countDown(const std::string& eventName);

    // Blocks the calling thread until all events in eventNames have called countDown.
    void wait() const;

private:
    mutable std::mutex mMutex;
    mutable std::condition_variable mConditionVariable;
    std::set<std::string> mRemainingEventNames;

    FRIEND_TEST(NamedLatchTest, TestCountDownCalledBySameEventName);
};
}  // namespace statsd
}  // namespace os
}  // namespace android
Loading