Differentiate system and test apis in whitelist
@SystemApi and @TestApi entries in the whitelist can now be
differentiated from the rest of the public apis.
Test: m test-art-host-gtest-hiddenapi_test
Change-Id: I2929cd5d48b760af92fc3cc7061039da9fe94f67
diff --git a/libartbase/base/hiddenapi_flags.h b/libartbase/base/hiddenapi_flags.h
index c468723..e6b1879 100644
--- a/libartbase/base/hiddenapi_flags.h
+++ b/libartbase/base/hiddenapi_flags.h
@@ -25,6 +25,7 @@
#include "base/bit_utils.h"
#include "base/dumpable.h"
#include "base/macros.h"
+#include "base/hiddenapi_stubs.h"
namespace art {
namespace hiddenapi {
@@ -209,6 +210,12 @@
for (std::vector<std::string>::iterator it = begin; it != end; it++) {
ApiList current = FromName(*it);
if (current.IsEmpty() || !api_list.CanCombineWith(current)) {
+ if (ApiStubs::IsStubsFlag(*it)) {
+ // Ignore flags which correspond to the stubs from where the api
+ // originates (i.e. system-api, test-api, public-api), as they are not
+ // relevant at runtime
+ continue;
+ }
return false;
}
api_list |= current;
diff --git a/libartbase/base/hiddenapi_stubs.h b/libartbase/base/hiddenapi_stubs.h
new file mode 100644
index 0000000..94ef95c
--- /dev/null
+++ b/libartbase/base/hiddenapi_stubs.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef ART_LIBARTBASE_BASE_HIDDENAPI_STUBS_H_
+#define ART_LIBARTBASE_BASE_HIDDENAPI_STUBS_H_
+
+#include <set>
+#include <string_view>
+
+namespace art {
+namespace hiddenapi {
+
+class ApiStubs {
+ public:
+ enum class Kind {
+ kPublicApi,
+ kSystemApi,
+ kTestApi,
+ kCorePlatformApi,
+ };
+
+ static const std::string_view ToString(Kind api) {
+ switch (api) {
+ case Kind::kPublicApi:
+ return kPublicApiStr;
+ case Kind::kSystemApi:
+ return kSystemApiStr;
+ case Kind::kTestApi:
+ return kTestApiStr;
+ case Kind::kCorePlatformApi:
+ return kCorePlatformApiStr;
+ }
+ }
+
+ static bool IsStubsFlag(const std::string_view& api_flag_name) {
+ return api_flag_name == kPublicApiStr || api_flag_name == kSystemApiStr ||
+ api_flag_name == kTestApiStr || api_flag_name == kCorePlatformApiStr;
+ }
+
+ private:
+ static constexpr std::string_view kPublicApiStr{"public-api"};
+ static constexpr std::string_view kSystemApiStr{"system-api"};
+ static constexpr std::string_view kTestApiStr{"test-api"};
+ static constexpr std::string_view kCorePlatformApiStr{"core-platform-api"};
+};
+
+} // namespace hiddenapi
+} // namespace art
+
+
+#endif // ART_LIBARTBASE_BASE_HIDDENAPI_STUBS_H_
diff --git a/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java b/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java
index 9c4e57e..01b36a4 100644
--- a/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java
+++ b/tools/class2greylist/src/com/android/class2greylist/Class2Greylist.java
@@ -60,6 +60,8 @@
public static final String FLAG_GREYLIST_MAX_O = "greylist-max-o";
public static final String FLAG_GREYLIST_MAX_P = "greylist-max-p";
+ public static final String FLAG_PUBLIC_API = "public-api";
+
private static final Map<Integer, String> TARGET_SDK_TO_LIST_MAP;
static {
Map<Integer, String> map = new HashMap<>();
@@ -178,7 +180,7 @@
mPublicApis =
Files.readLines(new File(stubApiFlagsFile), Charset.forName("UTF-8")).stream()
.map(s -> Splitter.on(",").splitToList(s))
- .filter(s -> s.contains(FLAG_WHITELIST))
+ .filter(s -> s.contains(FLAG_PUBLIC_API))
.map(s -> s.get(0))
.collect(Collectors.toSet());
} else {
@@ -199,7 +201,7 @@
greylistAnnotationHandler));
CovariantReturnTypeHandler covariantReturnTypeHandler = new CovariantReturnTypeHandler(
- mOutput, mPublicApis, FLAG_WHITELIST);
+ mOutput, mPublicApis, FLAG_PUBLIC_API);
return addRepeatedAnnotationHandlers(builder, CovariantReturnTypeHandler.ANNOTATION_NAME,
CovariantReturnTypeHandler.REPEATED_ANNOTATION_NAME, covariantReturnTypeHandler)
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index 3390a99..937abd1 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -88,6 +88,8 @@
UsageError(" Command \"list\": dump lists of public and private API");
UsageError(" --boot-dex=<filename>: dex file which belongs to boot class path");
UsageError(" --public-stub-classpath=<filenames>:");
+ UsageError(" --system-stub-classpath=<filenames>:");
+ UsageError(" --test-stub-classpath=<filenames>:");
UsageError(" --core-platform-stub-classpath=<filenames>:");
UsageError(" colon-separated list of dex/apk files which form API stubs of boot");
UsageError(" classpath. Multiple classpaths can be specified");
@@ -906,11 +908,19 @@
} else if (StartsWith(option, "--public-stub-classpath=")) {
stub_classpaths_.push_back(std::make_pair(
std::string(option.substr(strlen("--public-stub-classpath="))),
- ApiList::Whitelist()));
+ ApiStubs::Kind::kPublicApi));
+ } else if (StartsWith(option, "--system-stub-classpath=")) {
+ stub_classpaths_.push_back(std::make_pair(
+ std::string(option.substr(strlen("--system-stub-classpath="))),
+ ApiStubs::Kind::kSystemApi));
+ } else if (StartsWith(option, "--test-stub-classpath=")) {
+ stub_classpaths_.push_back(std::make_pair(
+ std::string(option.substr(strlen("--test-stub-classpath="))),
+ ApiStubs::Kind::kTestApi));
} else if (StartsWith(option, "--core-platform-stub-classpath=")) {
stub_classpaths_.push_back(std::make_pair(
std::string(option.substr(strlen("--core-platform-stub-classpath="))),
- ApiList::CorePlatformApi()));
+ ApiStubs::Kind::kCorePlatformApi));
} else if (StartsWith(option, "--out-api-flags=")) {
api_flags_path_ = std::string(option.substr(strlen("--out-api-flags=")));
} else {
@@ -983,15 +993,19 @@
size_t line_number = 1;
for (std::string line; std::getline(api_file, line); line_number++) {
+ // Every line contains a comma separated list with the signature as the
+ // first element and the api flags as the rest
std::vector<std::string> values = android::base::Split(line, ",");
CHECK_GT(values.size(), 1u) << path << ":" << line_number
<< ": No flags found: " << line << kErrorHelp;
const std::string& signature = values[0];
+
CHECK(api_flag_map.find(signature) == api_flag_map.end()) << path << ":" << line_number
<< ": Duplicate entry: " << signature << kErrorHelp;
ApiList membership;
+
bool success = ApiList::FromNames(values.begin() + 1, values.end(), &membership);
CHECK(success) << path << ":" << line_number
<< ": Some flags were not recognized: " << line << kErrorHelp;
@@ -1016,7 +1030,7 @@
// Complete list of boot class path members. The associated boolean states
// whether it is public (true) or private (false).
- std::map<std::string, ApiList> boot_members;
+ std::map<std::string, std::set<std::string_view>> boot_members;
// Deduplicate errors before printing them.
std::set<std::string> unresolved;
@@ -1027,7 +1041,7 @@
// Mark all boot dex members private.
boot_classpath.ForEachDexMember([&](const DexMember& boot_member) {
- boot_members[boot_member.GetApiEntry()] = ApiList();
+ boot_members[boot_member.GetApiEntry()] = {};
});
// Resolve each SDK dex member against the framework and mark it white.
@@ -1035,7 +1049,7 @@
ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"),
/* open_writable= */ false);
Hierarchy stub_hierarchy(stub_classpath);
- const ApiList stub_api_list = cp_entry.second;
+ const ApiStubs::Kind stub_api = cp_entry.second;
stub_classpath.ForEachDexMember(
[&](const DexMember& stub_member) {
@@ -1049,7 +1063,7 @@
std::string entry = boot_member.GetApiEntry();
auto it = boot_members.find(entry);
CHECK(it != boot_members.end());
- it->second |= stub_api_list;
+ it->second.insert(ApiStubs::ToString(stub_api));
});
if (!resolved) {
unresolved.insert(stub_member.GetApiEntry());
@@ -1065,10 +1079,11 @@
// Write into public/private API files.
std::ofstream file_flags(api_flags_path_.c_str());
for (const auto& entry : boot_members) {
- if (entry.second.IsEmpty()) {
+ if (entry.second.empty()) {
file_flags << entry.first << std::endl;
} else {
- file_flags << entry.first << "," << entry.second << std::endl;
+ file_flags << entry.first << ",";
+ file_flags << android::base::Join(entry.second, ",") << std::endl;
}
}
file_flags.close();
@@ -1086,7 +1101,7 @@
// Set of public API stub classpaths. Each classpath is formed by a list
// of DEX/APK files in the order they appear on the classpath.
- std::vector<std::pair<std::string, ApiList>> stub_classpaths_;
+ std::vector<std::pair<std::string, ApiStubs::Kind>> stub_classpaths_;
// Path to CSV file containing the list of API members and their flags.
// This could be both an input and output path.
diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc
index 74feb8a..213692b 100644
--- a/tools/hiddenapi/hiddenapi_test.cc
+++ b/tools/hiddenapi/hiddenapi_test.cc
@@ -706,7 +706,7 @@
ScratchFile flags_csv;
ASSERT_TRUE(RunHiddenapiList(flags_csv));
auto flags = ReadFlagsCsvFile(flags_csv);
- ASSERT_EQ(SafeMapGet("LPackageClass;->publicMethod1()V", flags), "whitelist");
+ ASSERT_EQ(SafeMapGet("LPackageClass;->publicMethod1()V", flags), "public-api");
}
// Test a method declared in PublicInterface, defined in AbstractPackageClass and
@@ -715,7 +715,7 @@
ScratchFile flags_csv;
ASSERT_TRUE(RunHiddenapiList(flags_csv));
auto flags = ReadFlagsCsvFile(flags_csv);
- ASSERT_EQ(SafeMapGet("LAbstractPackageClass;->publicMethod2()V", flags), "whitelist");
+ ASSERT_EQ(SafeMapGet("LAbstractPackageClass;->publicMethod2()V", flags), "public-api");
}
} // namespace art