Implement legacy_prop_name am: 3f452c00b7 am: 70aa221e57
Change-Id: I74ee1941d185fe08d3ad0aaa1d8461eeddb10051
diff --git a/Android.bp b/Android.bp
index 2768156..96eae8b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -69,7 +69,7 @@
java_defaults {
name: "sysprop-library-stub-defaults",
srcs: [
- "stub/android/os/SystemProperties.java",
+ "stub/**/*.java",
],
installable: false,
sdk_version: "core_current",
diff --git a/ApiChecker.cpp b/ApiChecker.cpp
index a628787..2b21ba9 100644
--- a/ApiChecker.cpp
+++ b/ApiChecker.cpp
@@ -76,6 +76,10 @@
err += "Integer-as-bool of prop " + latest_prop.api_name() +
" has been changed\n";
}
+ if (latest_prop.legacy_prop_name() != current_prop.legacy_prop_name()) {
+ err += "Legacy prop of prop " + latest_prop.api_name() +
+ " has been changed\n";
+ }
}
if (!latest_empty) {
diff --git a/Common.cpp b/Common.cpp
index f81aa59..462b625 100644
--- a/Common.cpp
+++ b/Common.cpp
@@ -141,6 +141,11 @@
return Errorf("Invalid prop name \"{}\"", prop.prop_name());
}
+ std::string legacy_name = prop.legacy_prop_name();
+ if (!legacy_name.empty() && !IsCorrectPropertyName(legacy_name)) {
+ return Errorf("Invalid legacy prop name \"{}\"", legacy_name);
+ }
+
static const std::regex vendor_regex(
"(init\\.svc\\.|ro\\.|persist\\.)?vendor\\..+|ro\\.hardware\\..+");
static const std::regex odm_regex(
diff --git a/CppGen.cpp b/CppGen.cpp
index 51e2f51..9c1602f 100644
--- a/CppGen.cpp
+++ b/CppGen.cpp
@@ -191,19 +191,23 @@
}
template <typename T>
-T GetProp(const char* key) {
+T GetProp(const char* key, const char* legacy = nullptr) {
+ std::string value;
#ifdef __BIONIC__
- T ret;
auto pi = __system_property_find(key);
if (pi != nullptr) {
__system_property_read_callback(pi, [](void* cookie, const char*, const char* value, std::uint32_t) {
- *static_cast<T*>(cookie) = TryParse<T>(value);
- }, &ret);
+ *static_cast<std::string*>(cookie) = value;
+ }, &value);
}
- return ret;
#else
- return TryParse<T>(android::base::GetProperty(key, "").c_str());
+ value = android::base::GetProperty(key, "");
#endif
+ if (value.empty() && legacy) {
+ ALOGD("prop %s doesn't exist; fallback to legacy prop %s", key, legacy);
+ return GetProp<T>(legacy);
+ }
+ return TryParse<T>(value.c_str());
}
)";
@@ -398,11 +402,18 @@
const sysprop::Property& prop = props.prop(i);
std::string prop_id = ApiNameToIdentifier(prop.api_name());
std::string prop_type = GetCppPropTypeName(prop);
+ std::string prop_name = prop.prop_name();
+ std::string legacy_name = prop.legacy_prop_name();
writer.Write("%s %s() {\n", prop_type.c_str(), prop_id.c_str());
writer.Indent();
- writer.Write("return GetProp<%s>(\"%s\");\n", prop_type.c_str(),
- prop.prop_name().c_str());
+ if (legacy_name.empty()) {
+ writer.Write("return GetProp<%s>(\"%s\");\n", prop_type.c_str(),
+ prop_name.c_str());
+ } else {
+ writer.Write("return GetProp<%s>(\"%s\", \"%s\");\n", prop_type.c_str(),
+ prop_name.c_str(), legacy_name.c_str());
+ }
writer.Dedent();
writer.Write("}\n");
diff --git a/JavaGen.cpp b/JavaGen.cpp
index 5912607..9b22f80 100644
--- a/JavaGen.cpp
+++ b/JavaGen.cpp
@@ -39,6 +39,7 @@
constexpr const char* kJavaFileImports =
R"(import android.os.SystemProperties;
+import android.util.Log;
import java.lang.StringBuilder;
import java.util.ArrayList;
@@ -209,17 +210,18 @@
std::string GetParsingExpression(const sysprop::Property& prop) {
switch (prop.type()) {
case sysprop::Boolean:
- return "tryParseBoolean(value)";
+ return "Optional.ofNullable(tryParseBoolean(value))";
case sysprop::Integer:
- return "tryParseInteger(value)";
+ return "Optional.ofNullable(tryParseInteger(value))";
case sysprop::Long:
- return "tryParseLong(value)";
+ return "Optional.ofNullable(tryParseLong(value))";
case sysprop::Double:
- return "tryParseDouble(value)";
+ return "Optional.ofNullable(tryParseDouble(value))";
case sysprop::String:
- return "tryParseString(value)";
+ return "Optional.ofNullable(tryParseString(value))";
case sysprop::Enum:
- return "tryParseEnum(" + GetJavaEnumTypeName(prop) + ".class, value)";
+ return "Optional.ofNullable(tryParseEnum(" + GetJavaEnumTypeName(prop) +
+ ".class, value))";
case sysprop::EnumList:
return "tryParseEnumList(" + GetJavaEnumTypeName(prop) +
".class, "
@@ -352,23 +354,31 @@
if (IsListProp(prop)) {
writer.Write("public static %s %s() {\n", prop_type.c_str(),
prop_id.c_str());
- writer.Indent();
- writer.Write("String value = SystemProperties.get(\"%s\");\n",
- prop.prop_name().c_str());
- writer.Write("return %s;\n", GetParsingExpression(prop).c_str());
- writer.Dedent();
- writer.Write("}\n");
} else {
writer.Write("public static Optional<%s> %s() {\n", prop_type.c_str(),
prop_id.c_str());
+ }
+ writer.Indent();
+ writer.Write("String value = SystemProperties.get(\"%s\");\n",
+ prop.prop_name().c_str());
+ if (!prop.legacy_prop_name().empty()) {
+ // SystemProperties.get() returns "" (empty string) when the property
+ // doesn't exist
+ writer.Write("if (\"\".equals(value)) {\n");
writer.Indent();
- writer.Write("String value = SystemProperties.get(\"%s\");\n",
- prop.prop_name().c_str());
- writer.Write("return Optional.ofNullable(%s);\n",
- GetParsingExpression(prop).c_str());
+ writer.Write(
+ "Log.d(\"%s\", \"prop %s doesn't exist; fallback to legacy prop "
+ "%s\");\n",
+ class_name.c_str(), prop.prop_name().c_str(),
+ prop.legacy_prop_name().c_str());
+ writer.Write("value = SystemProperties.get(\"%s\");\n",
+ prop.legacy_prop_name().c_str());
writer.Dedent();
writer.Write("}\n");
}
+ writer.Write("return %s;\n", GetParsingExpression(prop).c_str());
+ writer.Dedent();
+ writer.Write("}\n");
if (prop.access() != sysprop::Readonly) {
writer.Write("\n");
diff --git a/stub/android/util/Log.java b/stub/android/util/Log.java
new file mode 100644
index 0000000..a47ff84
--- /dev/null
+++ b/stub/android/util/Log.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package android.util;
+
+// Stub for cutting dependency from sysprop_library to framework.jar
+public class Log {
+ public static int d(String tag, String msg) {
+ return 0;
+ }
+ private Log() {
+ }
+}
diff --git a/sysprop.proto b/sysprop.proto
index 4bb850a..4833603 100644
--- a/sysprop.proto
+++ b/sysprop.proto
@@ -61,6 +61,7 @@
string enum_values = 6;
bool integer_as_bool = 7;
bool deprecated = 8;
+ string legacy_prop_name = 9;
}
message Properties {
diff --git a/tests/CppGenTest.cpp b/tests/CppGenTest.cpp
index 6fc6466..1038680 100644
--- a/tests/CppGenTest.cpp
+++ b/tests/CppGenTest.cpp
@@ -49,6 +49,7 @@
prop_name: "android.test.string"
scope: Public
access: ReadWrite
+ legacy_prop_name: "legacy.android.test.string"
}
prop {
api_name: "test_enum"
@@ -57,6 +58,7 @@
enum_values: "a|b|c|D|e|f|G"
scope: Internal
access: ReadWrite
+ legacy_prop_name: "android.test.old.enum"
}
prop {
api_name: "test_BOOLeaN"
@@ -405,19 +407,23 @@
}
template <typename T>
-T GetProp(const char* key) {
+T GetProp(const char* key, const char* legacy = nullptr) {
+ std::string value;
#ifdef __BIONIC__
- T ret;
auto pi = __system_property_find(key);
if (pi != nullptr) {
__system_property_read_callback(pi, [](void* cookie, const char*, const char* value, std::uint32_t) {
- *static_cast<T*>(cookie) = TryParse<T>(value);
- }, &ret);
+ *static_cast<std::string*>(cookie) = value;
+ }, &value);
}
- return ret;
#else
- return TryParse<T>(android::base::GetProperty(key, "").c_str());
+ value = android::base::GetProperty(key, "");
#endif
+ if (value.empty() && legacy) {
+ ALOGD("prop %s doesn't exist; fallback to legacy prop %s", key, legacy);
+ return GetProp<T>(legacy);
+ }
+ return TryParse<T>(value.c_str());
}
} // namespace
@@ -441,7 +447,7 @@
}
std::optional<std::string> test_string() {
- return GetProp<std::optional<std::string>>("android.test.string");
+ return GetProp<std::optional<std::string>>("android.test.string", "legacy.android.test.string");
}
bool test_string(const std::optional<std::string>& value) {
@@ -449,7 +455,7 @@
}
std::optional<test_enum_values> test_enum() {
- return GetProp<std::optional<test_enum_values>>("android.test.enum");
+ return GetProp<std::optional<test_enum_values>>("android.test.enum", "android.test.old.enum");
}
bool test_enum(const std::optional<test_enum_values>& value) {
diff --git a/tests/JavaGenTest.cpp b/tests/JavaGenTest.cpp
index 4dd8973..86a5689 100644
--- a/tests/JavaGenTest.cpp
+++ b/tests/JavaGenTest.cpp
@@ -57,6 +57,7 @@
enum_values: "a|b|c|D|e|f|G"
scope: Internal
access: ReadWrite
+ legacy_prop_name: "vendor.old.test_enum"
}
prop {
api_name: "test_BOOLeaN"
@@ -106,6 +107,7 @@
package com.somecompany;
import android.os.SystemProperties;
+import android.util.Log;
import java.lang.StringBuilder;
import java.util.ArrayList;
@@ -289,6 +291,7 @@
package com.somecompany;
import android.os.SystemProperties;
+import android.util.Log;
import java.lang.StringBuilder;
import java.util.ArrayList;
@@ -454,6 +457,10 @@
public static Optional<test_enum_values> test_enum() {
String value = SystemProperties.get("vendor.test.enum");
+ if ("".equals(value)) {
+ Log.d("TestProperties", "prop vendor.test.enum doesn't exist; fallback to legacy prop vendor.old.test_enum");
+ value = SystemProperties.get("vendor.old.test_enum");
+ }
return Optional.ofNullable(tryParseEnum(test_enum_values.class, value));
}