diff --git a/device.mk b/device.mk index a79aaedf..537b254a 100644 --- a/device.mk +++ b/device.mk @@ -761,6 +761,10 @@ PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \ securedpud.slider +# Trusty Metrics Daemon +PRODUCT_PACKAGES += \ + trusty_metricsd.gs101 + PRODUCT_PACKAGES += \ android.hardware.graphics.composer@2.4-impl \ android.hardware.graphics.composer@2.4-service diff --git a/trusty/metrics/Android.bp b/trusty/metrics/Android.bp new file mode 100644 index 00000000..26c9f2f5 --- /dev/null +++ b/trusty/metrics/Android.bp @@ -0,0 +1,31 @@ +// Copyright (C) 2021 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. + +cc_binary { + name: "trusty_metricsd.gs101", + vendor: true, + init_rc: ["trusty_metricsd.gs101.rc"], + srcs: ["main.cpp"], + shared_libs: [ + "android.frameworks.stats-V1-ndk_platform", + "libbase", + "libbinder_ndk", + "libtrusty_metrics", + "vendor-pixelatoms-cpp", + ], + cflags: [ + "-Wall", + "-Werror", + ], +} diff --git a/trusty/metrics/main.cpp b/trusty/metrics/main.cpp new file mode 100644 index 00000000..fdde83ad --- /dev/null +++ b/trusty/metrics/main.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2021 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +using aidl::android::frameworks::stats::IStats; +using aidl::android::frameworks::stats::VendorAtom; +using aidl::android::frameworks::stats::VendorAtomValue; +using android::hardware::google::pixel::vendor::PixelAtoms::Atom; +using android::hardware::google::pixel::vendor::PixelAtoms::ReverseDomainNames; + +static void show_usage_and_exit(int code) { + LOG(ERROR) << "usage: trusty_metricsd -d "; + exit(code); +} + +static void parse_device_name(int argc, char* argv[], char*& device_name) { + static const char* _sopts = "h:d:"; + static const struct option _lopts[] = {{"help", no_argument, NULL, 'h'}, + {"trusty_dev", required_argument, NULL, 'd'}, + {0, 0, 0, 0}}; + int opt; + int oidx = 0; + + while ((opt = getopt_long(argc, argv, _sopts, _lopts, &oidx)) != -1) { + switch (opt) { + case 'd': + device_name = strdup(optarg); + break; + + default: + LOG(ERROR) << "unrecognized option: " << opt; + show_usage_and_exit(EXIT_FAILURE); + } + } + + if (device_name == nullptr) { + LOG(ERROR) << "missing required argument(s)"; + show_usage_and_exit(EXIT_FAILURE); + } + + LOG(INFO) << "starting trusty_metricsd"; + LOG(INFO) << "trusty dev: " << device_name; +} + +namespace android { +namespace trusty { +namespace metrics { + +class TrustyMetricsPixel : public TrustyMetrics { + private: + TrustyMetricsPixel(std::string tipc_dev, std::shared_ptr stats_client) + : TrustyMetrics(std::move(tipc_dev)), stats_client_(stats_client) {} + + std::shared_ptr stats_client_; + + public: + static std::unique_ptr Create(std::string tipc_dev) { + const std::string stats_service_name = + std::string(IStats::descriptor).append("/default"); + std::shared_ptr stats_client = IStats::fromBinder(ndk::SpAIBinder( + AServiceManager_waitForService(stats_service_name.c_str()))); + if (!stats_client) { + LOG(ERROR) << "failed to open IStats client"; + return nullptr; + } + + std::unique_ptr metrics( + new TrustyMetricsPixel(std::move(tipc_dev), stats_client)); + if (!metrics) { + LOG(ERROR) << "failed to allocate TrustyMetricsPixel"; + return nullptr; + } + + auto ret = metrics->Open(); + if (!ret.ok()) { + LOG(ERROR) << "failed to open TrustyMetricsPixel: " << ret.error(); + return nullptr; + } + + return metrics; + } + + virtual void HandleCrash(const std::string& app_id) override { + LOG(ERROR) << "TA crashed: " << app_id; + + std::vector v(1); + v[0].set(app_id); + + VendorAtom atom{ + .reverseDomainName = ReverseDomainNames().pixel(), + .atomId = Atom::kTrustyAppCrashed, + .values = std::move(v), + }; + + auto ret = stats_client_->reportVendorAtom(atom); + if (!ret.isOk()) { + LOG(ERROR) << "failed to report Trusty app crash to IStats"; + } + } + + virtual void HandleEventDrop() override { + LOG(ERROR) << "Trusty metrics event dropped!"; + } +}; + +} // namespace metrics +} // namespace trusty +} // namespace android + +int main(int argc, char* argv[]) { + char* device_name; + parse_device_name(argc, argv, device_name); + + auto metrics = android::trusty::metrics::TrustyMetricsPixel::Create(device_name); + if (!metrics) { + LOG(ERROR) << "failed to open Trusty metrics client"; + return EXIT_FAILURE; + } + + int binder_fd; + binder_status_t status = ABinderProcess_setupPolling(&binder_fd); + if (status != STATUS_OK || binder_fd < 0) { + LOG(ERROR) << "failed to setup binder polling"; + return EXIT_FAILURE; + } + + struct pollfd pfds[] = { + { + .fd = binder_fd, + .events = POLLIN, + }, + { + .fd = metrics->GetRawFd(), + .events = POLLIN, + }, + }; + + while (1) { + int rc = poll(pfds, 2, -1 /* no timeout */); + if (rc <= 0) { + LOG(ERROR) << "failed poll()"; + continue; + } + + short binder_revents = pfds[0].revents; + short metrics_revents = pfds[1].revents; + + short error_mask = POLLHUP | POLLERR | POLLNVAL; + if ((binder_revents & error_mask) || (metrics_revents & error_mask)) { + LOG(ERROR) << "received an error event from poll()"; + /* irrecoverable error */ + break; + } + + if (binder_revents & POLLIN) { + ABinderProcess_handlePolledCommands(); + } + + if (metrics_revents & POLLIN) { + metrics->HandleEvent(); + } + } + + return EXIT_FAILURE; +} diff --git a/trusty/metrics/trusty_metricsd.gs101.rc b/trusty/metrics/trusty_metricsd.gs101.rc new file mode 100644 index 00000000..69cb950c --- /dev/null +++ b/trusty/metrics/trusty_metricsd.gs101.rc @@ -0,0 +1,18 @@ +# Copyright (C) 2021 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. + +service trusty_metricsd /vendor/bin/trusty_metricsd.gs101 -d /dev/trusty-ipc-dev0 + class main + user system + group system