1 /*
2 * Copyright (C) 2020 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 "src/trace_processor/importers/proto/profiler_util.h"
18
19 #include "perfetto/ext/base/optional.h"
20 #include "perfetto/ext/base/string_utils.h"
21 #include "src/trace_processor/storage/trace_storage.h"
22
23 namespace perfetto {
24 namespace trace_processor {
25 namespace {
26
PackageFromApp(base::StringView location)27 base::Optional<base::StringView> PackageFromApp(base::StringView location) {
28 location = location.substr(base::StringView("/data/app/").size());
29 size_t start = 0;
30 if (location.at(0) == '~') {
31 size_t slash = location.find('/');
32 if (slash == std::string::npos) {
33 return base::nullopt;
34 }
35 start = slash + 1;
36 }
37 size_t end = location.find('/', start + 1);
38 if (end == std::string::npos) {
39 return base::nullopt;
40 }
41 location = location.substr(start, end);
42 size_t minus = location.find('-');
43 if (minus == std::string::npos) {
44 return base::nullopt;
45 }
46 return location.substr(0, minus);
47 }
48
49 } // namespace
50
PackageFromLocation(TraceStorage * storage,base::StringView location)51 base::Optional<std::string> PackageFromLocation(TraceStorage* storage,
52 base::StringView location) {
53 // List of some hardcoded apps that do not follow the scheme used in
54 // PackageFromApp. Ask for yours to be added.
55 //
56 // TODO(b/153632336): Get rid of the hardcoded list of system apps.
57 base::StringView sysui(
58 "/system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk");
59 if (location.size() >= sysui.size() &&
60 location.substr(0, sysui.size()) == sysui) {
61 return "com.android.systemui";
62 }
63
64 base::StringView phonesky("/product/priv-app/Phonesky/Phonesky.apk");
65 if (location.size() >= phonesky.size() &&
66 location.substr(0, phonesky.size()) == phonesky) {
67 return "com.android.vending";
68 }
69
70 base::StringView maps("/product/app/Maps/Maps.apk");
71 if (location.size() >= maps.size() &&
72 location.substr(0, maps.size()) == maps) {
73 return "com.google.android.apps.maps";
74 }
75
76 base::StringView launcher(
77 "/system_ext/priv-app/NexusLauncherRelease/NexusLauncherRelease.apk");
78 if (location.size() >= launcher.size() &&
79 location.substr(0, launcher.size()) == launcher) {
80 return "com.google.android.apps.nexuslauncher";
81 }
82
83 base::StringView photos("/product/app/Photos/Photos.apk");
84 if (location.size() >= photos.size() &&
85 location.substr(0, photos.size()) == photos) {
86 return "com.google.android.apps.photos";
87 }
88
89 base::StringView wellbeing(
90 "/product/priv-app/WellbeingPrebuilt/WellbeingPrebuilt.apk");
91 if (location.size() >= wellbeing.size() &&
92 location.substr(0, wellbeing.size()) == wellbeing) {
93 return "com.google.android.apps.wellbeing";
94 }
95
96 if (location.find("DevicePersonalizationPrebuilt") !=
97 base::StringView::npos ||
98 location.find("MatchMaker") != base::StringView::npos) {
99 return "com.google.android.as";
100 }
101
102 base::StringView gm("/product/app/PrebuiltGmail/PrebuiltGmail.apk");
103 if (location.size() >= gm.size() && location.substr(0, gm.size()) == gm) {
104 return "com.google.android.gm";
105 }
106
107 if (location.find("PrebuiltGmsCore") != std::string::npos) {
108 return "com.google.android.gms";
109 }
110
111 base::StringView velvet("/product/priv-app/Velvet/Velvet.apk");
112 if (location.size() >= velvet.size() &&
113 location.substr(0, velvet.size()) == velvet) {
114 return "com.google.android.googlequicksearchbox";
115 }
116
117 base::StringView inputmethod(
118 "/product/app/LatinIMEGooglePrebuilt/LatinIMEGooglePrebuilt.apk");
119 if (location.size() >= inputmethod.size() &&
120 location.substr(0, inputmethod.size()) == inputmethod) {
121 return "com.google.android.inputmethod.latin";
122 }
123
124 base::StringView messaging("/product/app/PrebuiltBugle/PrebuiltBugle.apk");
125 if (location.size() >= messaging.size() &&
126 location.substr(0, messaging.size()) == messaging) {
127 return "com.google.android.apps.messaging";
128 }
129
130 base::StringView data_app("/data/app/");
131 if (location.substr(0, data_app.size()) == data_app) {
132 auto package = PackageFromApp(location);
133 if (!package) {
134 PERFETTO_DLOG("Failed to parse %s", location.ToStdString().c_str());
135 storage->IncrementStats(stats::deobfuscate_location_parse_error);
136 return base::nullopt;
137 }
138 return package->ToStdString();
139 }
140 return base::nullopt;
141 }
142
FullyQualifiedDeobfuscatedName(protos::pbzero::ObfuscatedClass::Decoder & cls,protos::pbzero::ObfuscatedMember::Decoder & member)143 std::string FullyQualifiedDeobfuscatedName(
144 protos::pbzero::ObfuscatedClass::Decoder& cls,
145 protos::pbzero::ObfuscatedMember::Decoder& member) {
146 std::string member_deobfuscated_name =
147 member.deobfuscated_name().ToStdString();
148 if (base::Contains(member_deobfuscated_name, '.')) {
149 // Fully qualified name.
150 return member_deobfuscated_name;
151 } else {
152 // Name relative to class.
153 return cls.deobfuscated_name().ToStdString() + "." +
154 member_deobfuscated_name;
155 }
156 }
157
158 } // namespace trace_processor
159 } // namespace perfetto
160