1 // Copyright (C) 2019 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef IORAP_SRC_DB_APP_COMPONENT_NAME_H_ 16 #define IORAP_SRC_DB_APP_COMPONENT_NAME_H_ 17 18 namespace iorap::db { 19 20 struct AppComponentName { 21 std::string package; 22 std::string activity_name; 23 24 // Turns the activity name to the fully qualified name. 25 // For example, if the activity name is ".MainActivity" and the package is 26 // foo.bar. Then the fully qualified name is foo.bar.MainActivity. CanonicalizeAppComponentName27 AppComponentName Canonicalize() const { 28 if (!activity_name.empty() && activity_name[0] == '.') { 29 return {package, package + activity_name}; 30 } 31 return {package, activity_name}; 32 } 33 HasAppComponentNameAppComponentName34 static bool HasAppComponentName(const std::string& s) { 35 return s.find('/') != std::string::npos; 36 } 37 38 // "com.foo.bar/.A" -> {"com.foo.bar", ".A"} FromStringAppComponentName39 static AppComponentName FromString(const std::string& s) { 40 constexpr const char delimiter = '/'; 41 42 if (!HasAppComponentName(s)) { 43 return {std::move(s), ""}; 44 } 45 46 std::string package = s.substr(0, s.find(delimiter)); 47 48 std::string activity_name = s; 49 activity_name.erase(0, s.find(delimiter) + sizeof(delimiter)); 50 51 return {std::move(package), std::move(activity_name)}; 52 } 53 54 // {"com.foo.bar", ".A"} -> "com.foo.bar/.A" ToStringAppComponentName55 std::string ToString() const { 56 return package + "/" + activity_name; 57 } 58 59 /* 60 * '/' is encoded into %2F 61 * '%' is encoded into %25 62 * 63 * This allows the component name to be be used as a file name 64 * ('/' is illegal due to being a path separator) with minimal 65 * munging. 66 */ 67 68 // "com.foo.bar%2F.A%25" -> {"com.foo.bar", ".A%"} FromUrlEncodedStringAppComponentName69 static AppComponentName FromUrlEncodedString(const std::string& s) { 70 std::string cpy = s; 71 Replace(cpy, "%2F", "/"); 72 Replace(cpy, "%25", "%"); 73 74 return FromString(cpy); 75 } 76 77 // {"com.foo.bar", ".A%"} -> "com.foo.bar%2F.A%25" ToUrlEncodedStringAppComponentName78 std::string ToUrlEncodedString() const { 79 std::string s = ToString(); 80 Replace(s, "%", "%25"); 81 Replace(s, "/", "%2F"); 82 return s; 83 } 84 85 /* 86 * '/' is encoded into @@ 87 * '%' is encoded into ^^ 88 * 89 * Two purpose: 90 * 1. This allows the package name to be used as a file name 91 * ('/' is illegal due to being a path separator) with minimal 92 * munging. 93 * 2. This allows the package name to be used in .mk file because 94 * '%' is a special char and cannot be easily escaped in Makefile. 95 * 96 * This is a workround for test purpose. 97 * Only package name is used because activity name varies on 98 * different testing framework. 99 * Hopefully, the double "@@" and "^^" are not used in other cases. 100 */ 101 // {"com.foo.bar", ".A%"} -> "com.foo.bar" ToMakeFileSafeEncodedPkgStringAppComponentName102 std::string ToMakeFileSafeEncodedPkgString() const { 103 std::string s = package; 104 Replace(s, "/", "@@"); 105 Replace(s, "%", "^^"); 106 return s; 107 } 108 109 private: ReplaceAppComponentName110 static bool Replace(std::string& str, const std::string& from, const std::string& to) { 111 // TODO: call in a loop to replace all occurrences, not just the first one. 112 const size_t start_pos = str.find(from); 113 if (start_pos == std::string::npos) { 114 return false; 115 } 116 117 str.replace(start_pos, from.length(), to); 118 119 return true; 120 } 121 }; 122 123 inline std::ostream& operator<<(std::ostream& os, const AppComponentName& name) { 124 os << name.ToString(); 125 return os; 126 } 127 128 } // namespace iorap::db 129 130 #endif // IORAP_SRC_DB_APP_COMPONENT_NAME_H_ 131