• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cstdint>
18 #include <string>
19 #include <string_view>
20 #include <vector>
21 
22 #include "perfetto/base/status.h"
23 #include "src/base/test/status_matchers.h"
24 #include "src/trace_redaction/find_package_uid.h"
25 #include "src/trace_redaction/prune_package_list.h"
26 #include "src/trace_redaction/trace_redaction_framework.h"
27 #include "src/trace_redaction/trace_redaction_integration_fixture.h"
28 #include "src/trace_redaction/trace_redactor.h"
29 #include "test/gtest_and_gmock.h"
30 
31 #include "protos/perfetto/trace/android/packages_list.gen.h"
32 #include "protos/perfetto/trace/android/packages_list.pbzero.h"
33 #include "protos/perfetto/trace/trace.pbzero.h"
34 #include "protos/perfetto/trace/trace_packet.gen.h"
35 #include "protos/perfetto/trace/trace_packet.pbzero.h"
36 
37 namespace perfetto::trace_redaction {
38 
39 namespace {
40 
41 // Set the package name to "just some package name". If a specific package name
42 // is needed, the test it should overwrite this value.
43 constexpr std::string_view kPackageName =
44     "com.Unity.com.unity.multiplayer.samples.coop";
45 constexpr uint64_t kPackageUid = 10252;
46 
47 }  // namespace
48 
49 class PrunePackageListIntegrationTest
50     : public testing::Test,
51       protected TraceRedactionIntegrationFixure {
52  protected:
SetUp()53   void SetUp() override {
54     context_.package_name = kPackageName;
55 
56     trace_redactor_.emplace_collect<FindPackageUid>();
57     trace_redactor_.emplace_transform<PrunePackageList>();
58   }
59 
GetPackageInfo(const protos::pbzero::Trace::Decoder & trace) const60   std::vector<protos::gen::PackagesList::PackageInfo> GetPackageInfo(
61       const protos::pbzero::Trace::Decoder& trace) const {
62     std::vector<protos::gen::PackagesList::PackageInfo> packages;
63 
64     for (auto packet_it = trace.packet(); packet_it; ++packet_it) {
65       protos::pbzero::TracePacket::Decoder packet(*packet_it);
66 
67       if (!packet.has_packages_list()) {
68         continue;
69       }
70 
71       protos::pbzero::PackagesList::Decoder list(packet.packages_list());
72 
73       for (auto info = list.packages(); info; ++info) {
74         auto& item = packages.emplace_back();
75         item.ParseFromArray(info->data(), info->size());
76       }
77     }
78 
79     return packages;
80   }
81 
GetPackageNames(const protos::pbzero::Trace::Decoder & trace) const82   std::vector<std::string> GetPackageNames(
83       const protos::pbzero::Trace::Decoder& trace) const {
84     std::vector<std::string> names;
85 
86     for (const auto& package : GetPackageInfo(trace)) {
87       if (package.has_name()) {
88         names.push_back(package.name());
89       }
90     }
91 
92     return names;
93   }
94 
95   Context context_;
96   TraceRedactor trace_redactor_;
97 };
98 
99 // It is possible for two packages_list to appear in the trace. The
100 // find_package_uid will stop after the first one is found. Package uids are
101 // appear as n * 1,000,000 where n is some integer. It is also possible for two
102 // packages_list to contain copies of each other - for example
103 // "com.Unity.com.unity.multiplayer.samples.coop" appears in both packages_list.
TEST_F(PrunePackageListIntegrationTest,FindsPackageAndFiltersPackageList)104 TEST_F(PrunePackageListIntegrationTest, FindsPackageAndFiltersPackageList) {
105   auto result = Redact(trace_redactor_, &context_);
106   ASSERT_OK(result) << result.message();
107 
108   auto after_raw_trace = LoadRedacted();
109   ASSERT_OK(after_raw_trace) << after_raw_trace.status().message();
110 
111   ASSERT_TRUE(context_.package_uid.has_value());
112   ASSERT_EQ(*context_.package_uid, kPackageUid);
113 
114   protos::pbzero::Trace::Decoder redacted_trace(after_raw_trace.value());
115   auto packages = GetPackageInfo(redacted_trace);
116 
117   ASSERT_EQ(packages.size(), 2u);
118 
119   for (const auto& package : packages) {
120     ASSERT_TRUE(package.has_name());
121     ASSERT_EQ(package.name(), kPackageName);
122 
123     ASSERT_TRUE(package.has_uid());
124     ASSERT_EQ(NormalizeUid(package.uid()), kPackageUid);
125   }
126 }
127 
128 // It is possible for multiple packages to share a uid. The names will appears
129 // across multiple package lists. The only time the package name appears is in
130 // the package list, so there is no way to differentiate these packages (only
131 // the uid is used later), so each entry should remain.
TEST_F(PrunePackageListIntegrationTest,RetainsAllInstancesOfUid)132 TEST_F(PrunePackageListIntegrationTest, RetainsAllInstancesOfUid) {
133   context_.package_name = "com.google.android.networkstack.tethering";
134 
135   auto result = Redact(trace_redactor_, &context_);
136   ASSERT_OK(result) << result.message();
137 
138   auto after_raw_trace = LoadRedacted();
139   ASSERT_OK(after_raw_trace) << after_raw_trace.status().message();
140 
141   protos::pbzero::Trace::Decoder redacted_trace(after_raw_trace.value());
142   auto package_names = GetPackageNames(redacted_trace);
143 
144   std::vector<std::string> expected_package_names = {
145       "com.google.android.cellbroadcastservice",
146       "com.google.android.cellbroadcastservice",
147       "com.google.android.networkstack",
148       "com.google.android.networkstack",
149       "com.google.android.networkstack.permissionconfig",
150       "com.google.android.networkstack.permissionconfig",
151       "com.google.android.networkstack.tethering",
152       "com.google.android.networkstack.tethering",
153   };
154 
155   // Sort to make compare possible.
156   std::sort(expected_package_names.begin(), expected_package_names.end());
157   std::sort(package_names.begin(), package_names.end());
158 
159   ASSERT_TRUE(std::equal(package_names.begin(), package_names.end(),
160                          expected_package_names.begin(),
161                          expected_package_names.end()));
162 }
163 
164 }  // namespace perfetto::trace_redaction
165