/* * Copyright (C) 2024 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 "perfetto/base/status.h" #include "src/base/test/status_matchers.h" #include "src/trace_redaction/find_package_uid.h" #include "src/trace_redaction/prune_package_list.h" #include "src/trace_redaction/trace_redaction_framework.h" #include "src/trace_redaction/trace_redaction_integration_fixture.h" #include "src/trace_redaction/trace_redactor.h" #include "test/gtest_and_gmock.h" #include "protos/perfetto/trace/android/packages_list.gen.h" #include "protos/perfetto/trace/android/packages_list.pbzero.h" #include "protos/perfetto/trace/trace.pbzero.h" #include "protos/perfetto/trace/trace_packet.gen.h" #include "protos/perfetto/trace/trace_packet.pbzero.h" namespace perfetto::trace_redaction { namespace { // Set the package name to "just some package name". If a specific package name // is needed, the test it should overwrite this value. constexpr std::string_view kPackageName = "com.Unity.com.unity.multiplayer.samples.coop"; constexpr uint64_t kPackageUid = 10252; } // namespace class PrunePackageListIntegrationTest : public testing::Test, protected TraceRedactionIntegrationFixure { protected: void SetUp() override { context_.package_name = kPackageName; trace_redactor_.emplace_collect(); trace_redactor_.emplace_transform(); } std::vector GetPackageInfo( const protos::pbzero::Trace::Decoder& trace) const { std::vector packages; for (auto packet_it = trace.packet(); packet_it; ++packet_it) { protos::pbzero::TracePacket::Decoder packet(*packet_it); if (!packet.has_packages_list()) { continue; } protos::pbzero::PackagesList::Decoder list(packet.packages_list()); for (auto info = list.packages(); info; ++info) { auto& item = packages.emplace_back(); item.ParseFromArray(info->data(), info->size()); } } return packages; } std::vector GetPackageNames( const protos::pbzero::Trace::Decoder& trace) const { std::vector names; for (const auto& package : GetPackageInfo(trace)) { if (package.has_name()) { names.push_back(package.name()); } } return names; } Context context_; TraceRedactor trace_redactor_; }; // It is possible for two packages_list to appear in the trace. The // find_package_uid will stop after the first one is found. Package uids are // appear as n * 1,000,000 where n is some integer. It is also possible for two // packages_list to contain copies of each other - for example // "com.Unity.com.unity.multiplayer.samples.coop" appears in both packages_list. TEST_F(PrunePackageListIntegrationTest, FindsPackageAndFiltersPackageList) { auto result = Redact(trace_redactor_, &context_); ASSERT_OK(result) << result.message(); auto after_raw_trace = LoadRedacted(); ASSERT_OK(after_raw_trace) << after_raw_trace.status().message(); ASSERT_TRUE(context_.package_uid.has_value()); ASSERT_EQ(*context_.package_uid, kPackageUid); protos::pbzero::Trace::Decoder redacted_trace(after_raw_trace.value()); auto packages = GetPackageInfo(redacted_trace); ASSERT_EQ(packages.size(), 2u); for (const auto& package : packages) { ASSERT_TRUE(package.has_name()); ASSERT_EQ(package.name(), kPackageName); ASSERT_TRUE(package.has_uid()); ASSERT_EQ(NormalizeUid(package.uid()), kPackageUid); } } // It is possible for multiple packages to share a uid. The names will appears // across multiple package lists. The only time the package name appears is in // the package list, so there is no way to differentiate these packages (only // the uid is used later), so each entry should remain. TEST_F(PrunePackageListIntegrationTest, RetainsAllInstancesOfUid) { context_.package_name = "com.google.android.networkstack.tethering"; auto result = Redact(trace_redactor_, &context_); ASSERT_OK(result) << result.message(); auto after_raw_trace = LoadRedacted(); ASSERT_OK(after_raw_trace) << after_raw_trace.status().message(); protos::pbzero::Trace::Decoder redacted_trace(after_raw_trace.value()); auto package_names = GetPackageNames(redacted_trace); std::vector expected_package_names = { "com.google.android.cellbroadcastservice", "com.google.android.cellbroadcastservice", "com.google.android.networkstack", "com.google.android.networkstack", "com.google.android.networkstack.permissionconfig", "com.google.android.networkstack.permissionconfig", "com.google.android.networkstack.tethering", "com.google.android.networkstack.tethering", }; // Sort to make compare possible. std::sort(expected_package_names.begin(), expected_package_names.end()); std::sort(package_names.begin(), package_names.end()); ASSERT_TRUE(std::equal(package_names.begin(), package_names.end(), expected_package_names.begin(), expected_package_names.end())); } } // namespace perfetto::trace_redaction