blob: 8846c014324f21fb0c2393b0889d186d7d9ce37c [file] [log] [blame]
/*
* 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.
*/
#ifndef SRC_PROFILING_PERF_PROC_DESCRIPTORS_H_
#define SRC_PROFILING_PERF_PROC_DESCRIPTORS_H_
#include <sys/types.h>
#include <map>
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/unix_socket.h"
namespace perfetto {
// Callback interface for receiving /proc/<pid>/ file descriptors (proc-fds)
// from |ProcDescriptorGetter|.
class ProcDescriptorDelegate {
public:
virtual void OnProcDescriptors(pid_t pid,
uid_t uid,
base::ScopedFile maps_fd,
base::ScopedFile mem_fd) = 0;
virtual ~ProcDescriptorDelegate();
};
class ProcDescriptorGetter {
public:
virtual void GetDescriptorsForPid(pid_t pid) = 0;
virtual void SetDelegate(ProcDescriptorDelegate* delegate) = 0;
// TODO(b/151835887): attempt to remove the race condition in the Android
// platform itself, and remove this best-effort workaround.
virtual bool RequiresDelayedRequest() { return false; }
virtual ~ProcDescriptorGetter();
};
// Directly opens /proc/<pid>/{maps,mem} files. Used when the daemon is running
// with sufficient privileges to do so.
class DirectDescriptorGetter : public ProcDescriptorGetter {
public:
void GetDescriptorsForPid(pid_t pid) override;
void SetDelegate(ProcDescriptorDelegate* delegate) override;
~DirectDescriptorGetter() override;
private:
ProcDescriptorDelegate* delegate_ = nullptr;
};
// Implementation of |ProcDescriptorGetter| used when running as a system daemon
// on Android. Uses a socket inherited from |init| and platform signal handlers
// to obtain the proc-fds.
class AndroidRemoteDescriptorGetter : public ProcDescriptorGetter,
public base::UnixSocket::EventListener {
public:
AndroidRemoteDescriptorGetter(int listening_raw_socket,
base::TaskRunner* task_runner) {
listening_socket_ = base::UnixSocket::Listen(
base::ScopedFile(listening_raw_socket), this, task_runner,
base::SockFamily::kUnix, base::SockType::kStream);
}
// ProcDescriptorGetter impl:
void GetDescriptorsForPid(pid_t pid) override;
void SetDelegate(ProcDescriptorDelegate* delegate) override;
bool RequiresDelayedRequest() override { return true; }
// UnixSocket::EventListener impl:
void OnNewIncomingConnection(
base::UnixSocket*,
std::unique_ptr<base::UnixSocket> new_connection) override;
void OnDataAvailable(base::UnixSocket* self) override;
void OnDisconnect(base::UnixSocket* self) override;
~AndroidRemoteDescriptorGetter() override;
private:
ProcDescriptorDelegate* delegate_ = nullptr;
std::unique_ptr<base::UnixSocket> listening_socket_;
// Holds onto connections until we receive the file descriptors (keyed by
// their raw addresses, which the map keeps stable).
std::map<base::UnixSocket*, std::unique_ptr<base::UnixSocket>>
active_connections_;
};
} // namespace perfetto
#endif // SRC_PROFILING_PERF_PROC_DESCRIPTORS_H_