Merge "Add NamedLatch to statsd" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
259e20acec
@@ -104,6 +104,7 @@ cc_defaults {
|
|||||||
"src/subscriber/IncidentdReporter.cpp",
|
"src/subscriber/IncidentdReporter.cpp",
|
||||||
"src/subscriber/SubscriberReporter.cpp",
|
"src/subscriber/SubscriberReporter.cpp",
|
||||||
"src/uid_data.proto",
|
"src/uid_data.proto",
|
||||||
|
"src/utils/NamedLatch.cpp",
|
||||||
],
|
],
|
||||||
|
|
||||||
local_include_dirs: [
|
local_include_dirs: [
|
||||||
@@ -361,6 +362,7 @@ cc_test {
|
|||||||
"tests/StatsService_test.cpp",
|
"tests/StatsService_test.cpp",
|
||||||
"tests/storage/StorageManager_test.cpp",
|
"tests/storage/StorageManager_test.cpp",
|
||||||
"tests/UidMap_test.cpp",
|
"tests/UidMap_test.cpp",
|
||||||
|
"tests/utils/NamedLatch_test.cpp",
|
||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
|
|||||||
@@ -118,8 +118,9 @@ StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQ
|
|||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
mEventQueue(queue),
|
mEventQueue(queue),
|
||||||
mStatsCompanionServiceDeathRecipient(AIBinder_DeathRecipient_new(
|
mBootCompleteLatch({kBootCompleteTag, kUidMapReceivedTag, kAllPullersRegisteredTag}),
|
||||||
StatsService::statsCompanionServiceDied)) {
|
mStatsCompanionServiceDeathRecipient(
|
||||||
|
AIBinder_DeathRecipient_new(StatsService::statsCompanionServiceDied)) {
|
||||||
mUidMap = UidMap::getInstance();
|
mUidMap = UidMap::getInstance();
|
||||||
mPullerManager = new StatsPullerManager();
|
mPullerManager = new StatsPullerManager();
|
||||||
StatsPuller::SetUidMap(mUidMap);
|
StatsPuller::SetUidMap(mUidMap);
|
||||||
@@ -164,6 +165,12 @@ StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQ
|
|||||||
std::thread pushedEventThread([this] { readLogs(); });
|
std::thread pushedEventThread([this] { readLogs(); });
|
||||||
pushedEventThread.detach();
|
pushedEventThread.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::thread bootCompletedThread([this] {
|
||||||
|
mBootCompleteLatch.wait();
|
||||||
|
VLOG("In the boot completed thread");
|
||||||
|
});
|
||||||
|
bootCompletedThread.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
StatsService::~StatsService() {
|
StatsService::~StatsService() {
|
||||||
@@ -939,6 +946,7 @@ Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
|
|||||||
packageNames,
|
packageNames,
|
||||||
installers);
|
installers);
|
||||||
|
|
||||||
|
mBootCompleteLatch.countDown(kUidMapReceivedTag);
|
||||||
VLOG("StatsService::informAllUidData UidData proto parsed successfully.");
|
VLOG("StatsService::informAllUidData UidData proto parsed successfully.");
|
||||||
return Status::ok();
|
return Status::ok();
|
||||||
}
|
}
|
||||||
@@ -1058,7 +1066,7 @@ Status StatsService::bootCompleted() {
|
|||||||
ENFORCE_UID(AID_SYSTEM);
|
ENFORCE_UID(AID_SYSTEM);
|
||||||
|
|
||||||
VLOG("StatsService::bootCompleted was called");
|
VLOG("StatsService::bootCompleted was called");
|
||||||
|
mBootCompleteLatch.countDown(kBootCompleteTag);
|
||||||
return Status::ok();
|
return Status::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1227,7 +1235,7 @@ Status StatsService::allPullersFromBootRegistered() {
|
|||||||
ENFORCE_UID(AID_SYSTEM);
|
ENFORCE_UID(AID_SYSTEM);
|
||||||
|
|
||||||
VLOG("StatsService::allPullersFromBootRegistered was called");
|
VLOG("StatsService::allPullersFromBootRegistered was called");
|
||||||
|
mBootCompleteLatch.countDown(kAllPullersRegisteredTag);
|
||||||
return Status::ok();
|
return Status::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,14 @@
|
|||||||
#ifndef STATS_SERVICE_H
|
#ifndef STATS_SERVICE_H
|
||||||
#define 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 <gtest/gtest_prod.h>
|
||||||
|
#include <utils/Looper.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "StatsLogProcessor.h"
|
#include "StatsLogProcessor.h"
|
||||||
#include "anomaly/AlarmMonitor.h"
|
#include "anomaly/AlarmMonitor.h"
|
||||||
#include "config/ConfigManager.h"
|
#include "config/ConfigManager.h"
|
||||||
@@ -26,13 +33,7 @@
|
|||||||
#include "packages/UidMap.h"
|
#include "packages/UidMap.h"
|
||||||
#include "shell/ShellSubscriber.h"
|
#include "shell/ShellSubscriber.h"
|
||||||
#include "statscompanion_util.h"
|
#include "statscompanion_util.h"
|
||||||
|
#include "utils/NamedLatch.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>
|
|
||||||
|
|
||||||
using namespace android;
|
using namespace android;
|
||||||
using namespace android::os;
|
using namespace android::os;
|
||||||
@@ -385,6 +386,11 @@ private:
|
|||||||
mutable mutex mShellSubscriberMutex;
|
mutable mutex mShellSubscriberMutex;
|
||||||
std::shared_ptr<LogEventQueue> mEventQueue;
|
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;
|
ScopedAIBinder_DeathRecipient mStatsCompanionServiceDeathRecipient;
|
||||||
|
|
||||||
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
|
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
|
||||||
|
|||||||
48
cmds/statsd/src/utils/NamedLatch.cpp
Normal file
48
cmds/statsd/src/utils/NamedLatch.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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
cmds/statsd/src/utils/NamedLatch.h
Normal file
58
cmds/statsd/src/utils/NamedLatch.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
96
cmds/statsd/tests/utils/NamedLatch_test.cpp
Normal file
96
cmds/statsd/tests/utils/NamedLatch_test.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "utils/NamedLatch.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <set>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using std::this_thread::sleep_for;
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace os {
|
||||||
|
namespace statsd {
|
||||||
|
|
||||||
|
TEST(NamedLatchTest, TestWait) {
|
||||||
|
int numEvents = 5;
|
||||||
|
string t1 = "t1", t2 = "t2", t3 = "t3", t4 = "t4", t5 = "t5";
|
||||||
|
set<string> eventNames = {t1, t2, t3, t4, t5};
|
||||||
|
|
||||||
|
NamedLatch latch(eventNames);
|
||||||
|
vector<thread> threads;
|
||||||
|
vector<bool> done(numEvents, false);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (const string& eventName : eventNames) {
|
||||||
|
threads.emplace_back([&done, &eventName, &latch, i] {
|
||||||
|
sleep_for(chrono::milliseconds(3));
|
||||||
|
done[i] = true;
|
||||||
|
latch.countDown(eventName);
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.wait();
|
||||||
|
|
||||||
|
for (i = 0; i < numEvents; i++) {
|
||||||
|
EXPECT_EQ(done[i], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numEvents; i++) {
|
||||||
|
threads[i].join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NamedLatchTest, TestNoWorkers) {
|
||||||
|
NamedLatch latch({});
|
||||||
|
latch.wait();
|
||||||
|
// Ensure that latch does not wait if no events need to countDown.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NamedLatchTest, TestCountDownCalledBySameEventName) {
|
||||||
|
string t1 = "t1", t2 = "t2";
|
||||||
|
set<string> eventNames = {t1, t2};
|
||||||
|
|
||||||
|
NamedLatch latch(eventNames);
|
||||||
|
|
||||||
|
thread waiterThread([&latch] { latch.wait(); });
|
||||||
|
|
||||||
|
latch.countDown(t1);
|
||||||
|
latch.countDown(t1);
|
||||||
|
|
||||||
|
// Ensure that the latch's remaining threads still has t2.
|
||||||
|
latch.mMutex.lock();
|
||||||
|
ASSERT_EQ(latch.mRemainingEventNames.size(), 1);
|
||||||
|
EXPECT_NE(latch.mRemainingEventNames.find(t2), latch.mRemainingEventNames.end());
|
||||||
|
latch.mMutex.unlock();
|
||||||
|
|
||||||
|
latch.countDown(t2);
|
||||||
|
waiterThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace statsd
|
||||||
|
} // namespace os
|
||||||
|
} // namespace android
|
||||||
|
#else
|
||||||
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user