blob: e772ef26f363cce407e65657cafa30e55e8ab1bc [file] [log] [blame]
/*
* 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 <cstdint>
#include <string>
#include "src/base/test/status_matchers.h"
#include "src/trace_redaction/find_package_uid.h"
#include "test/gtest_and_gmock.h"
#include "protos/perfetto/trace/android/packages_list.gen.h"
#include "protos/perfetto/trace/ps/process_tree.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
namespace perfetto::trace_redaction {
namespace {
// packet {
// trusted_uid: 9999
// trusted_packet_sequence_id: 2
// previous_packet_dropped: true
// packages_list {
// packages {
// name: "com.shannon.qualifiednetworksservice"
// uid: 10201
// debuggable: false
// profileable_from_shell: false
// version_code: 131
// }
// packages {
// name: "com.google.android.uvexposurereporter"
// uid: 10205
// debuggable: false
// profileable_from_shell: false
// version_code: 34
// }
// packages {
// name: "com.android.internal.display.cutout.emulation.noCutout"
// uid: 10007
// debuggable: false
// profileable_from_shell: false
// version_code: 1
// }
// packages {
// name: "com.google.android.networkstack.tethering"
// uid: 1073
// debuggable: false
// profileable_from_shell: false
// version_code: 34
// }
// packages {
// name: "com.amazon.mShop.android.shopping"
// uid: 10303
// debuggable: false
// profileable_from_shell: false
// version_code: 1241261011
// }
// }
// trusted_pid: 1085
// first_packet_on_sequence: true
// }
//
// packet {
// process_tree {
// processes {
// pid: 23022
// ppid: 1
// cmdline: "/vendor/bin/hw/wpa_supplicant"
// cmdline: "-O/data/vendor/wifi/wpa/sockets"
// cmdline: "-dd"
// cmdline: "-g@android:wpa_wlan0"
// uid: 1010
// }
// threads {
// tid: 6382
// tgid: 18176
// }
// threads {
// tid: 18419
// tgid: 18176
// }
// threads {
// tid: 18434
// tgid: 18176
// }
// collection_end_timestamp: 333724398314653
// }
// trusted_uid: 9999
// timestamp: 333724396714922
// trusted_packet_sequence_id: 3
// trusted_pid: 1085
// }
void AddPackage(const std::string& name,
uint64_t uid,
int version_code,
protos::gen::PackagesList* list) {
auto* pkg = list->add_packages();
pkg->set_name(name);
pkg->set_uid(uid);
pkg->set_version_code(version_code);
}
void AddProcess(protos::gen::ProcessTree* process_tree) {
auto* p0 = process_tree->add_processes();
p0->set_pid(23022);
p0->set_ppid(1);
p0->add_cmdline("/vendor/bin/hw/wpa_supplicant");
p0->add_cmdline("-O/data/vendor/wifi/wpa/sockets");
p0->add_cmdline("-dd");
p0->add_cmdline("-g@android:wpa_wlan0");
p0->set_uid(1010);
}
void AddThread(int32_t tid,
int32_t ttid,
protos::gen::ProcessTree* process_tree) {
auto* thread = process_tree->add_threads();
thread->set_tid(tid);
thread->set_tgid(ttid);
}
std::string CreatePackageListPacket() {
protos::gen::TracePacket packet;
packet.set_trusted_uid(9999);
packet.set_trusted_packet_sequence_id(2);
packet.set_previous_packet_dropped(true);
packet.set_trusted_pid(1085);
packet.set_first_packet_on_sequence(true);
auto* package_list = packet.mutable_packages_list();
AddPackage("com.shannon.qualifiednetworksservice", 10201, 131, package_list);
AddPackage("com.google.android.uvexposurereporter", 10205, 34, package_list);
AddPackage("com.android.internal.display.cutout.emulation.noCutout", 10007, 1,
package_list);
AddPackage("com.google.android.networkstack.tethering", 1073, 34,
package_list);
AddPackage("com.amazon.mShop.android.shopping", 10303, 1241261011,
package_list);
return packet.SerializeAsString();
}
std::string CreateProcessTreePacket() {
protos::gen::TracePacket packet;
packet.set_trusted_uid(9999);
packet.set_timestamp(333724396714922);
packet.set_trusted_packet_sequence_id(3);
packet.set_trusted_pid(1085);
auto* tree = packet.mutable_process_tree();
tree->set_collection_end_timestamp(333724398314653);
AddProcess(tree);
AddThread(6382, 18176, tree);
AddThread(18419, 18176, tree);
AddThread(18434, 18176, tree);
return packet.SerializeAsString();
}
} // namespace
TEST(FindPackageUidTest, FindsUidInPackageList) {
const auto packet = CreatePackageListPacket();
Context context;
context.package_name = "com.google.android.uvexposurereporter";
const FindPackageUid find;
const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
base::Status status = find.Begin(&context);
ASSERT_OK(status) << status.message();
status = find.Collect(decoder, &context);
ASSERT_OK(status) << status.message();
status = find.End(&context);
ASSERT_OK(status) << status.message();
ASSERT_TRUE(context.package_uid.has_value());
// context.package_uid should have been normalized already.
ASSERT_EQ(context.package_uid.value(), NormalizeUid(10205));
}
TEST(FindPackageUidTest, ContinuesOverNonPackageList) {
const auto packet = CreateProcessTreePacket();
Context context;
context.package_name = "com.google.android.uvexposurereporter";
const FindPackageUid find;
const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
base::Status status = find.Begin(&context);
ASSERT_OK(status) << status.message();
status = find.Collect(decoder, &context);
ASSERT_OK(status) << status.message();
// The should not have been found; End() should return an error.
status = find.End(&context);
ASSERT_FALSE(status.ok()) << status.message();
ASSERT_FALSE(context.package_uid.has_value());
}
TEST(FindPackageUidTest, ContinuesOverPackageListWithOutPackageName) {
const auto packet = CreatePackageListPacket();
Context context;
context.package_name = "com.not.a.packagename";
const FindPackageUid find;
const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
base::Status status = find.Begin(&context);
ASSERT_OK(status) << status.message();
status = find.Collect(decoder, &context);
ASSERT_OK(status) << status.message();
// The should not have been found; End() should return an error.
status = find.End(&context);
ASSERT_FALSE(status.ok()) << status.message();
ASSERT_FALSE(context.package_uid.has_value());
}
TEST(FindPackageUidTest, MissingPackageNameReturnsError) {
const auto packet = CreatePackageListPacket();
Context context;
const FindPackageUid find;
const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
base::Status status = find.Begin(&context);
ASSERT_FALSE(status.ok()) << status.message();
}
TEST(FindPackageUidTest, FailsIfUidStartsInitialized) {
const auto packet = CreatePackageListPacket();
Context context;
context.package_name = "com.google.android.uvexposurereporter";
context.package_uid = 1000;
const FindPackageUid find;
const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
base::Status status = find.Begin(&context);
ASSERT_FALSE(status.ok()) << status.message();
}
} // namespace perfetto::trace_redaction