blob: 98ace774ea1643105282af92dfa5eae4e34e8ecd [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.
*/
#include "include/InputReaderTracer.h"
#include <android-base/logging.h>
#if defined(__ANDROID__)
#include <gui/SurfaceComposerClient.h>
#endif
#include <gui/WindowInfosUpdate.h>
#include <input/Input.h>
#include <utils/StrongPointer.h>
#include <algorithm>
#include <memory>
#include <mutex>
#include "InputTracingBackendInterface.h"
#include "RawEvent.h"
namespace android {
InputReaderTracer::InputReaderTracer(
std::shared_ptr<input_trace::InputTracingBackendInterface> backend)
: InputReaderTracer(
backend,
[](const sp<android::gui::WindowInfosListener>& listener) {
#if defined(__ANDROID__)
android::base::Result<gui::WindowInfosUpdate> result =
SurfaceComposerClient::getDefault()->addWindowInfosListener(listener);
if (result.ok()) {
return result->windowInfos;
}
LOG(ERROR) << "Failed to register WindowInfosListener in InputReaderTracer: "
<< result.error().message();
#endif
return std::vector<gui::WindowInfo>();
},
[](const sp<android::gui::WindowInfosListener>& listener) {
#if defined(__ANDROID__)
SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
#endif
}) {
}
InputReaderTracer::InputReaderTracer(
std::shared_ptr<input_trace::InputTracingBackendInterface> backend,
const WindowListenerRegisterConsumer& registerListener,
const WindowListenerUnregisterConsumer& unregisterListener)
: mBackend(backend),
mRegisterListener(registerListener),
mUnregisterListener(unregisterListener) {
mWindowListener = sp<WindowListener>::make(*this);
std::vector<gui::WindowInfo> initialWindowInfos = mRegisterListener(mWindowListener);
mWindowListener->onWindowInfosChanged(
{initialWindowInfos, /*displayInfos=*/{}, /*vsyncId=*/-1, /*timestamp=*/0});
}
InputReaderTracer::~InputReaderTracer() {
// After unregistering a WindowInfosListener it could still be called one last time, if the
// callback was queued before it was unregistered. Set a flag on the listener to stop it from
// calling the tracer after disposal.
mWindowListener->mTracerDestroyed = true;
mUnregisterListener(mWindowListener);
}
void InputReaderTracer::traceRawEvent(const RawEvent& event) {
input_trace::TracedEventMetadata metadata;
{
std::scoped_lock lock(mLock);
metadata.isSecure = mSecureWindowVisible;
}
metadata.processingTimestamp = event.readTime;
mBackend->traceRawEvent(event, metadata);
}
void InputReaderTracer::traceDeviceAddition(nsecs_t timestamp,
const input_trace::TracedEvdevDevice& device) {
input_trace::TracedEventMetadata metadata;
{
std::scoped_lock lock(mLock);
metadata.isSecure = mSecureWindowVisible;
}
metadata.processingTimestamp = timestamp;
mBackend->traceEvdevDeviceAddition(device, metadata);
}
void InputReaderTracer::traceDeviceRemoval(nsecs_t timestamp, RawDeviceId deviceId) {
input_trace::TracedEventMetadata metadata;
{
std::scoped_lock lock(mLock);
metadata.isSecure = mSecureWindowVisible;
}
metadata.processingTimestamp = timestamp;
mBackend->traceEvdevDeviceRemoval(deviceId, metadata);
}
void InputReaderTracer::setSecureWindowVisible(bool visible) {
std::scoped_lock lock(mLock);
mSecureWindowVisible = visible;
}
void InputReaderTracer::WindowListener::onWindowInfosChanged(const gui::WindowInfosUpdate& update) {
if (mTracerDestroyed) {
return;
}
// Since we trace raw events before we know what window(s) they will result in events being
// dispatched to, we calculate the trace level for them by assuming that they will go to all
// visible windows. So, if there is any secure window visible on the screen, we'll set isSecure
// in the metadata.
const bool secureWindowVisible =
std::ranges::any_of(update.windowInfos, [](const gui::WindowInfo& info) {
return !info.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE) &&
!info.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL) &&
info.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY);
});
mTracer.setSecureWindowVisible(secureWindowVisible);
}
} // namespace android