blob: d5e319c327c1ee1c99ff7ff099809693ceaa1210 [file]
/*
* Copyright (C) 2025 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 <mutex>
#include "BinderObserverConfig.h"
#include "BinderStatsPusher.h"
#include "BinderStatsSpscQueue.h"
#include "BinderStatsUtils.h"
namespace android {
/**
* Collects and manages binder transaction statistics from IPC threads.
*
* Gathers BinderCallData from BinderStatsSpscQueue instances associated
* with each IPCThreadState. It periodically flushes these queues, aggregates
* data using BinderStatsCollector, and sends statistics via BinderStatsPusher.
*
* How it is works:
* - An instance is typically owned by ProcessState.
* - IPCThreadState instances register themselves with the BinderObserver.
* - IPCThreadState reports binder calls using onBeginTransaction/onEndTransaction
* - this pushes BinderCallData to the stats queue of the thread via addStatMaybeFlush.
* - flushStats (or flushIfRequired) periodically collects data from all
* registered queues and passes it to BinderStatsPusher.
*
* Threading Requirements:
* - onBeginTransaction, onEndTransaction, registerThread, deregisterThread: thread-safe
* - addStatMaybeFlush: thread-safe
*/
class BinderObserver {
public:
// Initial data for tracking a binder call
struct CallInfo {
int64_t startTimeNanos;
int64_t cpuUsageStartTimeNanos;
String16 interfaceDescriptor;
String16 aidlMethodName;
uint32_t code;
uid_t callingUid;
BinderObserverConfig::TrackingInfo trackingInfo;
};
BinderObserver() = default;
explicit BinderObserver(std::unique_ptr<BinderObserverConfig> config);
void deregisterThread(std::shared_ptr<BinderStatsSpscQueue>& queue);
// Disabled inlining to correctly understand the performance impact of BinderObserver.
__attribute__((noinline))
CallInfo onBeginTransaction(BBinder* binder, uint32_t code, uid_t callingUid);
__attribute__((noinline))
void onEndTransaction(std::shared_ptr<BinderStatsSpscQueue>& queue, const CallInfo& callInfo);
private:
// Add stats to the local queue, flush if queue is full.
void addStatMaybeFlush(const std::shared_ptr<BinderStatsSpscQueue>& queue,
const BinderCallData& stat);
void flushStats(int64_t nowMillis);
bool isFlushRequired(int64_t nowMillis);
std::unique_ptr<BinderObserverConfig> mConfig = BinderObserverConfig::createConfig();
// Time since last flush time. Used to trigger a flush if more than kSendTimeoutSec
// has elapsed since last flush.
std::atomic<int64_t> mLastFlushTimeSec;
// BinderStatsCollector stores shared ptrs to queues in IPCThreadState and pulls data from them.
BinderStatsCollector mBinderStatsCollector;
// BinderStatsPusher aggregates Stats and pushes them to data store.
BinderStatsPusher mPusher;
// Lock used to ensure that only one thread is running a flush and push at a time.
std::mutex mFlushLock;
};
} // namespace android