summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Anna Bauza <annabauza@google.com> 2024-10-02 17:09:48 +0000
committer Anna Bauza <annabauza@google.com> 2024-10-04 05:09:52 +0000
commita0760e36b4551dff8822b1a3ce3c074de901e880 (patch)
tree33a1ebcb2ae28fd69c75b79aba81aa0c4ea04902
parentac36b8cca30f25ff6e3891b6143e0ae9fd6540ab (diff)
Generate Property Invalidated Cache from annotation.
This CL is generating simple code for PropertyInvalidatedCache. It is to simplify caching implementation. To be used internally in manager classes which are making binder calls to the system server. To use annotate the manager class with @CachedPropertyDefaults. By default it has a maximum capacity of 4 and stores in the "system_server" module. both can be overwritten and will be used as default for each property inside of annotated class, eg: @CachedPropertyDefaults(module = "my_custom_module", max=32) Need static PropertyInvalidatedCache use @CachedProperty() or @CachedProperty(modifiers = {Modifier.STATIC}) in front of a method which calls a binder. Need NON-static PropertyInvalidatedCache use @CachedProperty(modifiers = {}) in front of a method which calls a binder. Need to change the max capacity of cache or give custom API name use @CachedProperty( modifiers = {}, max = 1, apiName = "my_unique_key") in front of a method which calls a binder. Bug: 361730767 Change-Id: I87677d102f62753c6e0707741c154c6b65c28949 Test: atest cached-property-annotation-processor-test Flag: EXEMPT bugfix Ignore-AOSP-First: Should not yet be exposed to AOSP
-rw-r--r--Android.bp1
-rw-r--r--tools/processors/property_cache/Android.bp57
-rw-r--r--tools/processors/property_cache/TEST_MAPPING7
-rw-r--r--tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java138
-rw-r--r--tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java40
-rw-r--r--tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java95
-rw-r--r--tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java40
-rw-r--r--tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java152
-rw-r--r--tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java103
-rw-r--r--tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java64
-rw-r--r--tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java134
-rw-r--r--tools/processors/property_cache/test/resources/Custom.java127
-rw-r--r--tools/processors/property_cache/test/resources/CustomCache.java384
-rw-r--r--tools/processors/property_cache/test/resources/Default.java125
-rw-r--r--tools/processors/property_cache/test/resources/DefaultCache.java402
15 files changed, 1869 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp
index 516fc9c55222..811755d0bdaf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -368,6 +368,7 @@ java_defaults {
jarjar_rules: ":framework-jarjar-rules",
javac_shard_size: 150,
plugins: [
+ "cached-property-annotation-processor",
"view-inspector-annotation-processor",
"staledataclass-annotation-processor",
"error_prone_android_framework",
diff --git a/tools/processors/property_cache/Android.bp b/tools/processors/property_cache/Android.bp
new file mode 100644
index 000000000000..81fab7a4c862
--- /dev/null
+++ b/tools/processors/property_cache/Android.bp
@@ -0,0 +1,57 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_framework_android_multiuser",
+}
+
+java_library_host {
+ name: "libcached-property-annotation-processor",
+ srcs: [
+ ":framework-annotations",
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "codegen-version-info",
+ "android.multiuser.flags-aconfig-java-host",
+ "guava",
+ ],
+ use_tools_jar: true,
+}
+
+java_plugin {
+ name: "cached-property-annotation-processor",
+ processor_class: "android.processor.property_cache.CachedPropertyProcessor",
+ static_libs: ["libcached-property-annotation-processor"],
+}
+
+java_aconfig_library {
+ name: "android.multiuser.flags-aconfig-java-host",
+ aconfig_declarations: "android.multiuser.flags-aconfig",
+ host_supported: true,
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+java_test_host {
+ name: "cached-property-annotation-processor-test",
+ srcs: ["test/java/**/*.java"],
+ java_resources: [":CachedPropertyAnnotationJavaTestSource"],
+ static_libs: [
+ "compile-testing-prebuilt",
+ "truth",
+ "junit",
+ "guava",
+ "libcached-property-annotation-processor",
+ ],
+ test_suites: ["general-tests"],
+}
+
+filegroup {
+ name: "CachedPropertyAnnotationJavaTestSource",
+ srcs: ["test/resources/*.java"],
+ path: "test/resources/",
+ visibility: ["//visibility:private"],
+}
diff --git a/tools/processors/property_cache/TEST_MAPPING b/tools/processors/property_cache/TEST_MAPPING
new file mode 100644
index 000000000000..7177abc8c52d
--- /dev/null
+++ b/tools/processors/property_cache/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "cached-property-annotation-processor-test"
+ }
+ ]
+}
diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java
new file mode 100644
index 000000000000..c665c840f376
--- /dev/null
+++ b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache;
+
+import com.android.internal.annotations.CachedProperty;
+import com.android.internal.annotations.CachedPropertyDefaults;
+
+import com.google.common.base.CaseFormat;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+public class CacheConfig {
+ private final CacheModifiers mModifiers;
+ private final int mMaxSize;
+ private final String mModuleName;
+ private final String mApiName;
+ private final String mClassName;
+ private final String mQualifiedName;
+ private String mPropertyName;
+ private String mMethodName;
+ private int mNumberOfParams = 0;
+ private String mInputType = Constants.JAVA_LANG_VOID;
+ private String mResultType;
+
+ public CacheConfig(TypeElement classElement, ExecutableElement method) {
+ CachedPropertyDefaults classAnnotation = classElement.getAnnotation(
+ CachedPropertyDefaults.class);
+ CachedProperty methodAnnotation = method.getAnnotation(CachedProperty.class);
+
+ mModuleName = methodAnnotation.module().isEmpty() ? classAnnotation.module()
+ : methodAnnotation.module();
+ mClassName = classElement.getSimpleName().toString();
+ mQualifiedName = classElement.getQualifiedName().toString();
+ mModifiers = new CacheModifiers(methodAnnotation.modsFlagOnOrNone());
+ mMethodName = method.getSimpleName().toString();
+ mPropertyName = getPropertyName(mMethodName);
+ mApiName = methodAnnotation.api().isEmpty() ? getUniqueApiName(mClassName, mPropertyName)
+ : methodAnnotation.api();
+ mMaxSize = methodAnnotation.max() == -1 ? classAnnotation.max() : methodAnnotation.max();
+ mNumberOfParams = method.getParameters().size();
+ if (mNumberOfParams > 0) {
+ mInputType = primitiveTypeToObjectEquivalent(
+ method.getParameters().get(0).asType().toString());
+ }
+ mResultType = primitiveTypeToObjectEquivalent(method.getReturnType().toString());
+ }
+
+ public CacheModifiers getModifiers() {
+ return mModifiers;
+ }
+
+ public int getMaxSize() {
+ return mMaxSize;
+ }
+
+ public String getApiName() {
+ return mApiName;
+ }
+
+ public String getClassName() {
+ return mClassName;
+ }
+
+ public String getQualifiedName() {
+ return mQualifiedName;
+ }
+
+ public String getModuleName() {
+ return mModuleName;
+ }
+
+ public String getMethodName() {
+ return mMethodName;
+ }
+
+ public String getPropertyName() {
+ return mPropertyName;
+ }
+
+ public String getPropertyVariable() {
+ return (mModifiers.isStatic() ? "s" : "m") + mPropertyName;
+ }
+
+ private String getPropertyName(String methodName) {
+ if (methodName.startsWith("get")) {
+ return methodName.substring(3);
+ } else if (methodName.startsWith("is")) {
+ return methodName.substring(2);
+ } else {
+ return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, methodName);
+ }
+ }
+
+ public int getNumberOfParams() {
+ return mNumberOfParams;
+ }
+
+ public String getInputType() {
+ return mInputType;
+ }
+
+ public String getResultType() {
+ return mResultType;
+ }
+
+ /**
+ * This method returns the unique api name for a given class and property name.
+ * Property name is retrieved from the method name.
+ * Both names are combined and converted to lower snake case.
+ *
+ * @param className The name of the class that contains the property.
+ * @param propertyName The name of the property.
+ * @return The registration name for the property.
+ */
+ private String getUniqueApiName(String className, String propertyName) {
+ return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, className + propertyName);
+ }
+
+ private String primitiveTypeToObjectEquivalent(String simpleType) {
+ // checking against primitive types
+ return Constants.PRIMITIVE_TYPE_MAP.getOrDefault(simpleType, simpleType);
+ }
+}
diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java
new file mode 100644
index 000000000000..fda9b2c40e27
--- /dev/null
+++ b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache;
+
+import com.android.internal.annotations.CacheModifier;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class CacheModifiers {
+ private final boolean mIsStatic;
+ private static final String STATIC_MODIFIER_STRING = "static ";
+
+ CacheModifiers(CacheModifier[] modifierArray) {
+ final List<CacheModifier> modifiers = Arrays.asList(modifierArray);
+ mIsStatic = modifiers.contains(CacheModifier.STATIC);
+ }
+
+ public boolean isStatic() {
+ return mIsStatic;
+ }
+
+ public String getStaticModifier() {
+ return mIsStatic ? STATIC_MODIFIER_STRING : Constants.EMPTY_STRING;
+ }
+}
diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java b/tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java
new file mode 100644
index 000000000000..03610128d269
--- /dev/null
+++ b/tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache;
+
+import com.android.internal.annotations.CachedProperty;
+import com.android.internal.annotations.CachedPropertyDefaults;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
+import javax.tools.JavaFileObject;
+
+public class CachedPropertyProcessor extends AbstractProcessor {
+
+ IpcDataCacheComposer mIpcDataCacheComposer =
+ new IpcDataCacheComposer();
+
+ @Override
+ public Set<String> getSupportedAnnotationTypes() {
+ return new HashSet<String>(
+ ImmutableSet.of(CachedPropertyDefaults.class.getCanonicalName()));
+ }
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ for (Element element : roundEnv.getElementsAnnotatedWith(CachedPropertyDefaults.class)) {
+ try {
+ generateCachedClass((TypeElement) element, processingEnv.getFiler());
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private void generateCachedClass(TypeElement classElement, Filer filer) throws IOException {
+ String packageName =
+ processingEnv
+ .getElementUtils()
+ .getPackageOf(classElement)
+ .getQualifiedName()
+ .toString();
+ String className = classElement.getSimpleName().toString() + "Cache";
+ JavaFileObject jfo = filer.createSourceFile(packageName + "." + className);
+ Writer writer = jfo.openWriter();
+ writer.write("package " + packageName + ";\n\n");
+ writer.write("import android.os.IpcDataCache;\n");
+ writer.write("\n /** \n * This class is auto-generated \n * @hide \n **/");
+ writer.write("\npublic class " + className + " {\n");
+
+ List<ExecutableElement> methods =
+ ElementFilter.methodsIn(classElement.getEnclosedElements());
+ String initCache = String.format(Constants.METHOD_COMMENT,
+ " - initialise all caches for class " + className)
+ + "\npublic static void initCache() {";
+ for (ExecutableElement method : methods) {
+ if (method.getAnnotation(CachedProperty.class) != null) {
+ mIpcDataCacheComposer.generatePropertyCache(writer, classElement, method);
+ initCache += "\n " + mIpcDataCacheComposer.generateInvalidatePropertyCall();
+ }
+ }
+ initCache += "\n}";
+ writer.write(initCache);
+ writer.write("\n}");
+ writer.write("\n");
+ writer.close();
+ }
+}
diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java b/tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java
new file mode 100644
index 000000000000..03961bcaaba0
--- /dev/null
+++ b/tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache;
+
+import com.google.common.collect.ImmutableMap;
+
+public final class Constants {
+ public static final String EMPTY_STRING = "";
+ public static final String JAVA_LANG_VOID = "java.lang.Void";
+ public static final ImmutableMap<String, String> PRIMITIVE_TYPE_MAP =
+ ImmutableMap.of(
+ "int", "java.lang.Integer",
+ "boolean", "java.lang.Boolean",
+ "long", "java.lang.Long",
+ "float", "java.lang.Float",
+ "double", "java.lang.Double",
+ "byte", "java.lang.Byte",
+ "short", "java.lang.Short",
+ "char", "java.lang.Character");
+
+ public static final String METHOD_COMMENT = "\n /**"
+ + "\n * This method is auto-generated%s"
+ + "\n * "
+ + "\n * @hide"
+ + "\n */";
+}
diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java b/tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java
new file mode 100644
index 000000000000..8526a04e9910
--- /dev/null
+++ b/tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+public class IpcDataCacheComposer {
+
+ private static final String PROPERTY_DEFINITION_LINE = "private %s%s %s;\n";
+ private static final String METHOD_NAME_LINE = "\npublic %s%s %s(%s%s%s\n) {\n";
+ private static final String RETURN_IF_NOT_NULL_LINE =
+ "if (%s != null) {\n return %s.%s;\n }";
+
+ private CacheConfig mCacheConfig;
+
+ /**
+ * Generates code for property cache.
+ *
+ * @param writer writer to write code to.
+ * @param classElement class element to generate code for.
+ * @param method method element to generate code for.
+ * @throws IOException if writer throws IOException.
+ */
+ public void generatePropertyCache(Writer writer, TypeElement classElement,
+ ExecutableElement method) throws IOException {
+
+ mCacheConfig = new CacheConfig(classElement, method);
+
+ ParamComposer inputParam = new ParamComposer(null, null);
+ ParamComposer binderParam = new ParamComposer(
+ String.format("IpcDataCache.RemoteCall<%s, %s>", mCacheConfig.getInputType(),
+ mCacheConfig.getResultType()), "binderCall");
+
+ ParamComposer bypassParam = new ParamComposer(null, null); // empty if method have no params
+ String queryCall = "query(null)";
+ if (mCacheConfig.getNumberOfParams() > 0) {
+ bypassParam = new ParamComposer(
+ String.format("IpcDataCache.BypassCall<%s> ", mCacheConfig.getInputType()),
+ "bypassPredicate");
+ inputParam = new ParamComposer(mCacheConfig.getInputType(), "query");
+ queryCall = "query(query)";
+ }
+ String propertyClass =
+ "IpcDataCache<" + mCacheConfig.getInputType() + ", " + mCacheConfig.getResultType()
+ + ">";
+ String invalidateName = "invalidate" + mCacheConfig.getPropertyName();
+ String lockObject = mCacheConfig.getPropertyVariable() + "Lock";
+ writer.write("private " + mCacheConfig.getModifiers().getStaticModifier() + "final Object "
+ + lockObject + " = new Object();\n");
+ writer.write(String.format(PROPERTY_DEFINITION_LINE,
+ mCacheConfig.getModifiers().getStaticModifier(), propertyClass,
+ mCacheConfig.getPropertyVariable()));
+
+ writer.write(propertyInvalidatedCacheMethod(binderParam, bypassParam, inputParam, queryCall,
+ lockObject));
+
+ // If binder param is not empty then generate getter without binder param to be called
+ if (!bypassParam.getParam().isEmpty()) {
+ writer.write(propertyInvalidatedCacheMethod(binderParam, new ParamComposer(null, null),
+ inputParam, queryCall, lockObject));
+ }
+ writer.write(String.format(Constants.METHOD_COMMENT,
+ "- invalidate cache for {@link " + mCacheConfig.getQualifiedName() + "#"
+ + mCacheConfig.getMethodName() + "}"));
+ writer.write("\n public static final void " + invalidateName + "() {");
+ writer.write(
+ "\n IpcDataCache.invalidateCache(\"" + mCacheConfig.getModuleName() + "\", \""
+ + mCacheConfig.getApiName() + "\");");
+ writer.write("\n }");
+ writer.write("\n");
+ writer.write("\n");
+ }
+
+ /**
+ * Generates code to call cache invalidation.
+ *
+ * @return code string calling cache invalidation.
+ */
+ public String generateInvalidatePropertyCall() {
+ String invalidateName = "invalidate" + mCacheConfig.getPropertyName();
+ return mCacheConfig.getClassName() + "Cache." + invalidateName + "();";
+ }
+
+ /**
+ * Generates code for getter that returns cached value or calls binder and caches result.
+ *
+ * @param binderParam parameter for binder call.
+ * @param bypassParam parameter for bypass predicate.
+ * @param inputParam parameter for input value.
+ * @param queryCall cache query call syntax.
+ * @param lockObject object to synchronize on.
+ * @return String with code for method.
+ */
+ private String propertyInvalidatedCacheMethod(ParamComposer binderParam,
+ ParamComposer bypassParam, ParamComposer inputParam, String queryCall,
+ String lockObject) {
+ String result = "\n";
+ CacheModifiers modifiers = mCacheConfig.getModifiers();
+ String paramsComments = binderParam.getParamComment(
+ "lambda for remote call" + " {@link " + mCacheConfig.getQualifiedName() + "#"
+ + mCacheConfig.getMethodName() + " }") + bypassParam.getParamComment(
+ "lambda to bypass remote call") + inputParam.getParamComment(
+ "parameter to call remote lambda");
+ result += String.format(Constants.METHOD_COMMENT, paramsComments);
+ result += String.format(METHOD_NAME_LINE, modifiers.getStaticModifier(),
+ mCacheConfig.getResultType(), mCacheConfig.getMethodName(),
+ binderParam.getParam(), bypassParam.getNextParam(),
+ inputParam.getNextParam());
+ result += String.format(RETURN_IF_NOT_NULL_LINE, mCacheConfig.getPropertyVariable(),
+ mCacheConfig.getPropertyVariable(), queryCall);
+ result += "\n synchronized (" + lockObject + " ) {";
+ result += "\n if (" + mCacheConfig.getPropertyVariable() + " == null) {";
+ result += "\n " + mCacheConfig.getPropertyVariable() + " = new IpcDataCache" + "("
+ + generateCreateIpcConfig() + ", " + binderParam.getName()
+ + bypassParam.getNextName() + ");\n";
+ result += "\n }";
+ result += "\n }";
+ result += "\n return " + mCacheConfig.getPropertyVariable() + "." + queryCall + ";";
+ result += "\n }";
+ result += "\n";
+ return result;
+ }
+
+ /**
+ * Generates code for new IpcDataCache.Config object for given configuration.
+ *
+ * @return String with code for new IpcDataCache.Config object.
+ */
+ public String generateCreateIpcConfig() {
+ return "new IpcDataCache.Config(" + mCacheConfig.getMaxSize() + ", " + "\""
+ + mCacheConfig.getModuleName() + "\"" + ", " + "\"" + mCacheConfig.getApiName()
+ + "\"" + ", " + "\"" + mCacheConfig.getPropertyName() + "\"" + ")";
+ }
+}
diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java b/tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java
new file mode 100644
index 000000000000..307443aea730
--- /dev/null
+++ b/tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache;
+
+public class ParamComposer {
+ private String mType;
+ private String mName;
+
+ /** Creates ParamComposer with given type and name.
+ *
+ * @param type type of parameter.
+ * @param name name of parameter.
+ */
+ public ParamComposer(String type, String name) {
+ mType = type;
+ mName = name;
+ }
+
+ /** Returns name of parameter.
+ *
+ * @return name of parameter.
+ */
+ public String getName() {
+ if (mName != null) {
+ return mName;
+ }
+ return Constants.EMPTY_STRING;
+ }
+
+ /** Returns name of parameter for next parameter followed by comma.
+ *
+ * @return name of parameter for next parameter if exists, empty string otherwise.
+ */
+ public String getNextName() {
+ if (!getName().isEmpty()) {
+ return ", " + getName();
+ }
+ return Constants.EMPTY_STRING;
+ }
+
+ /**
+ * Returns type of parameter.
+ *
+ * @return type of parameter.
+ */
+ public String getType() {
+ if (mType != null) {
+ return mType;
+ }
+ return Constants.EMPTY_STRING;
+ }
+
+ /**
+ * Returns type and name of parameter.
+ *
+ * @return type and name of parameter if exists, empty string otherwise.
+ */
+ public String getParam() {
+ if (!getType().isEmpty() && !getName().isEmpty()) {
+ return getType() + " " + getName();
+ }
+ return Constants.EMPTY_STRING;
+ }
+
+ /**
+ * Returns type and name of parameter for next parameter followed by comma.
+ *
+ * @return type and name of parameter for next parameter if exists, empty string otherwise.
+ */
+ public String getNextParam() {
+ if (!getType().isEmpty() && !getName().isEmpty()) {
+ return ", " + getParam();
+ }
+ return Constants.EMPTY_STRING;
+ }
+
+ /**
+ * Returns comment for parameter.
+ *
+ * @param description of parameter.
+ * @return comment for parameter if exists, empty string otherwise.
+ */
+ public String getParamComment(String description) {
+ if (!getType().isEmpty() && !getName().isEmpty()) {
+ return "\n * @param " + getName() + " - " + description;
+ }
+ return Constants.EMPTY_STRING;
+ }
+}
diff --git a/tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java b/tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java
new file mode 100644
index 000000000000..1e23c78d4816
--- /dev/null
+++ b/tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache.test;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.testing.compile.CompilationSubject.assertThat;
+
+import android.processor.property_cache.CachedPropertyProcessor;
+
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.Compiler;
+import com.google.testing.compile.JavaFileObjects;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+
+/** Tests the {@link CachedPropertyProcessor}. */
+@RunWith(JUnit4.class)
+public class CachedPropertyProcessorTest {
+ private final Compiler mCompiler =
+ Compiler.javac().withProcessors(new CachedPropertyProcessor());
+
+ @Test
+ public void testDefaultValues() {
+ JavaFileObject expectedJava = JavaFileObjects.forResource("DefaultCache.java");
+
+ Compilation compilation = mCompiler.compile(JavaFileObjects.forResource("Default.java"));
+ assertThat(compilation).succeeded();
+ assertThat(compilation)
+ .generatedFile(StandardLocation.SOURCE_OUTPUT,
+ "android/processor/property_cache/test/DefaultCache.java")
+ .hasSourceEquivalentTo(expectedJava);
+ }
+
+ @Test
+ public void testCustomValues() {
+ JavaFileObject expectedJava = JavaFileObjects.forResource("CustomCache.java");
+
+ Compilation compilation = mCompiler.compile(JavaFileObjects.forResource("Custom.java"));
+ assertThat(compilation).succeeded();
+ assertThat(compilation)
+ .generatedFile(StandardLocation.SOURCE_OUTPUT,
+ "android/processor/property_cache/test/CustomCache.java")
+ .hasSourceEquivalentTo(expectedJava);
+ }
+}
diff --git a/tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java b/tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java
new file mode 100644
index 000000000000..e5ef48c14436
--- /dev/null
+++ b/tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+// Mocked class for generation compilation tests purposes only.
+public class IpcDataCache<Input, Output> {
+ public static class Config {
+ public Config(int max, String module, String api, String name) {
+ }
+ }
+
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - shadow parameter from IpcDataCache in Frameworks.
+ * @return null
+ */
+ public Output query(Input query) {
+ return null;
+ }
+
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param key - shadow parameter from IpcDataCache in Frameworks;
+ */
+ public static void invalidateCache(String key) {
+ }
+
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - shadow parameter from IpcDataCache in Frameworks;
+ * @return null
+ */
+ public Output recompute(Input query) {
+ return null;
+ }
+
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - parameter equivalent to IpcDataCache in android framework.
+ * @param query - shadow parameter from IpcDataCache in Frameworks;
+ * @return false
+ */
+ public boolean bypass(Input query) {
+ return false;
+ }
+
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param module - parameter equivalent to IpcDataCache in android framework.
+ * @param key - parameter equivalent to IpcDataCache in android framework.
+ * @return module + key sttring
+ */
+ public static String createPropertyName(String module, String key) {
+ return module + key;
+ }
+
+ public abstract static class QueryHandler<Input, Output> {
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - parameter equivalent to IpcDataCache.QueryHandler in android framework.
+ * @return expected value
+ */
+ public abstract Output apply(Input query);
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - parameter equivalent to IpcDataCache.QueryHandler in android framework.
+ */
+ public boolean shouldBypassCache(Input query) {
+ return false;
+ }
+ }
+
+ public interface RemoteCall<Input, Output> {
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - parameter equivalent to IpcDataCache.RemoteCall in android framework.
+ */
+ Output apply(Input query);
+ }
+
+ public interface BypassCall<Input> {
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param query - parameter equivalent to IpcDataCache.BypassCall in android framework.
+ */
+ boolean apply(Input query);
+ }
+
+ public IpcDataCache(
+ int maxEntries,
+ String module,
+ String api,
+ String cacheName,
+ QueryHandler<Input, Output> computer) {
+ }
+
+ public IpcDataCache(Config config, QueryHandler<Input, Output> computer) {
+ }
+
+ public IpcDataCache(Config config, RemoteCall<Input, Output> computer) {
+ }
+
+ public IpcDataCache(Config config, RemoteCall<Input, Output> computer,
+ BypassCall<Input> bypassCall) {
+ }
+
+ /** Shadow method for generated code compilation tests purposes only.*/
+ public void invalidateCache() {
+ }
+
+
+ /** Shadow method for generated code compilation tests purposes only.
+ *
+ * @param module - shadow parameter from IpcDataCache in Frameworks.
+ * @param api - shadow parameter from IpcDataCache in Frameworks.
+ */
+ public static void invalidateCache(String module, String api) {
+ }
+
+}
diff --git a/tools/processors/property_cache/test/resources/Custom.java b/tools/processors/property_cache/test/resources/Custom.java
new file mode 100644
index 000000000000..05024da67e6c
--- /dev/null
+++ b/tools/processors/property_cache/test/resources/Custom.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache.test;
+
+import com.android.internal.annotations.CacheModifier;
+import com.android.internal.annotations.CachedProperty;
+import com.android.internal.annotations.CachedPropertyDefaults;
+
+import java.util.Date;
+
+@CachedPropertyDefaults(max = 4, module = "bluetooth")
+public class Custom {
+ BirthdayManagerService mService = new BirthdayManagerService();
+ Object mCache = new CustomCache();
+
+ public Custom() {
+ CustomCache.initCache();
+ }
+
+ /**
+ * Testing custom class values to generate static IpcDataCache
+ *
+ * @param userId - user Id
+ * @return birthday date of given user Id
+ */
+ @CachedProperty()
+ public Date getBirthday(int userId) {
+ return CustomCache.getBirthday(mService::getBirthday, userId);
+ }
+
+ /**
+ * Testing custom class values to generate static IpcDataCache
+ *
+ * @param userId - user Id
+ * @return number of days till birthday of given user Id
+ */
+ @CachedProperty(modsFlagOnOrNone = {CacheModifier.STATIC})
+ public int getDaysTillBirthday(int userId) {
+ return CustomCache.getDaysTillBirthday(mService::getDaysTillBirthday, userId);
+ }
+
+ /**
+ * Testing custom class values to generate non-static IpcDataCache
+ *
+ * @param userId - user Id
+ * @return number of days since birthday of given user Id
+ */
+ @CachedProperty(modsFlagOnOrNone = {})
+ public int getDaysSinceBirthday(int userId) {
+ return ((CustomCache) mCache).getDaysSinceBirthday(mService::getDaysSinceBirthday, userId);
+ }
+
+ /**
+ * Testing custom class values to generate static IpcDataCache with max capasity of 1
+ *
+ * @return number of days till birthay of current user
+ */
+ @CachedProperty(modsFlagOnOrNone = {CacheModifier.STATIC}, max = 1)
+ public int getDaysTillMyBirthday() {
+ return CustomCache.getDaysTillMyBirthday((Void) -> mService.getDaysTillMyBirthday());
+ }
+
+ /**
+ * Testing custom class values to generate static IpcDataCache with max capasity of 1 and custom
+ * api
+ *
+ * @return number of days since birthay of current user
+ */
+ @CachedProperty(modsFlagOnOrNone = {}, max = 1, api = "my_unique_key")
+ public int getDaysSinceMyBirthday() {
+ return ((CustomCache) mCache).getDaysSinceMyBirthday(
+ (Void) -> mService.getDaysSinceMyBirthday());
+ }
+
+ /**
+ * Testing custom class values to generate static IpcDataCache with custom module name
+ *
+ * @return birthday wishes of given user Id
+ */
+ @CachedProperty(module = "telephony")
+ public String getBirthdayWishesFromUser(int userId) {
+ return CustomCache.getBirthdayWishesFromUser(mService::getBirthdayWishesFromUser,
+ userId);
+ }
+
+ class BirthdayManagerService {
+ int mDaysTillBirthday = 182;
+
+ public Date getBirthday(int userId) {
+ return new Date(2024, 6, 1 + userId);
+ }
+
+ public int getDaysTillBirthday(int userId) {
+ return mDaysTillBirthday + userId;
+ }
+
+ public int getDaysSinceBirthday(int userId) {
+ return 365 - getDaysTillBirthday(userId);
+ }
+
+ public int getDaysTillMyBirthday() {
+ return 0;
+ }
+
+ public int getDaysSinceMyBirthday() {
+ return 365;
+ }
+
+ public String getBirthdayWishesFromUser(int userId) {
+ return "Happy Birthday!\n- " + userId;
+ }
+ }
+}
diff --git a/tools/processors/property_cache/test/resources/CustomCache.java b/tools/processors/property_cache/test/resources/CustomCache.java
new file mode 100644
index 000000000000..326467fb5639
--- /dev/null
+++ b/tools/processors/property_cache/test/resources/CustomCache.java
@@ -0,0 +1,384 @@
+/*
+ * 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.
+ */
+package android.processor.property_cache.test;
+
+import android.os.IpcDataCache;
+
+/**
+ * This class is auto-generated
+ *
+ * @hide
+ **/
+public class CustomCache {
+ private static final Object sBirthdayLock = new Object();
+ private static IpcDataCache<java.lang.Integer, java.util.Date> sBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Custom#getBirthday }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.util.Date getBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) {
+ if (sBirthday != null) {
+ return sBirthday.query(query);
+ }
+ synchronized (sBirthdayLock) {
+ if (sBirthday == null) {
+ sBirthday = new IpcDataCache(
+ new IpcDataCache.Config(4, "bluetooth", "custom_birthday", "Birthday"),
+ binderCall, bypassPredicate);
+
+ }
+ }
+ return sBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Custom#getBirthday }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.util.Date getBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall,
+ java.lang.Integer query) {
+ if (sBirthday != null) {
+ return sBirthday.query(query);
+ }
+ synchronized (sBirthdayLock) {
+ if (sBirthday == null) {
+ sBirthday = new IpcDataCache(
+ new IpcDataCache.Config(4, "bluetooth", "custom_birthday", "Birthday"),
+ binderCall);
+ }
+ }
+ return sBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Custom#getBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateBirthday() {
+ IpcDataCache.invalidateCache("bluetooth", "custom_birthday");
+ }
+
+ private static final Object sDaysTillBirthdayLock = new Object();
+ private static IpcDataCache<java.lang.Integer, java.lang.Integer> sDaysTillBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Custom#getDaysTillBirthday }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.Integer getDaysTillBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) {
+ if (sDaysTillBirthday != null) {
+ return sDaysTillBirthday.query(query);
+ }
+ synchronized (sDaysTillBirthdayLock) {
+ if (sDaysTillBirthday == null) {
+ sDaysTillBirthday = new IpcDataCache(
+ new IpcDataCache.Config(4, "bluetooth", "custom_days_till_birthday",
+ "DaysTillBirthday"), binderCall, bypassPredicate);
+
+ }
+ }
+ return sDaysTillBirthday.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Custom#getDaysTillBirthday }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.Integer getDaysTillBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ java.lang.Integer query) {
+ if (sDaysTillBirthday != null) {
+ return sDaysTillBirthday.query(query);
+ }
+ synchronized (sDaysTillBirthdayLock) {
+ if (sDaysTillBirthday == null) {
+ sDaysTillBirthday = new IpcDataCache(
+ new IpcDataCache.Config(4, "bluetooth", "custom_days_till_birthday",
+ "DaysTillBirthday"), binderCall);
+
+ }
+ }
+ return sDaysTillBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Custom#getDaysTillBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysTillBirthday() {
+ IpcDataCache.invalidateCache("bluetooth", "custom_days_till_birthday");
+ }
+
+ private final Object mDaysSinceBirthdayLock = new Object();
+ private IpcDataCache<java.lang.Integer, java.lang.Integer> mDaysSinceBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Custom#getDaysSinceBirthday }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public java.lang.Integer getDaysSinceBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) {
+ if (mDaysSinceBirthday != null) {
+ return mDaysSinceBirthday.query(query);
+ }
+ synchronized (mDaysSinceBirthdayLock) {
+ if (mDaysSinceBirthday == null) {
+ mDaysSinceBirthday = new IpcDataCache(
+ new IpcDataCache.Config(4, "bluetooth", "custom_days_since_birthday",
+ "DaysSinceBirthday"), binderCall, bypassPredicate);
+
+ }
+ }
+ return mDaysSinceBirthday.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Custom#getDaysSinceBirthday
+ * }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public java.lang.Integer getDaysSinceBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ java.lang.Integer query) {
+ if (mDaysSinceBirthday != null) {
+ return mDaysSinceBirthday.query(query);
+ }
+ synchronized (mDaysSinceBirthdayLock) {
+ if (mDaysSinceBirthday == null) {
+ mDaysSinceBirthday = new IpcDataCache(
+ new IpcDataCache.Config(4, "bluetooth", "custom_days_since_birthday",
+ "DaysSinceBirthday"), binderCall);
+
+ }
+ }
+ return mDaysSinceBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Custom#getDaysSinceBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysSinceBirthday() {
+ IpcDataCache.invalidateCache("bluetooth", "custom_days_since_birthday");
+ }
+
+ private static final Object sDaysTillMyBirthdayLock = new Object();
+ private static IpcDataCache<java.lang.Void, java.lang.Integer> sDaysTillMyBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Custom#getDaysTillMyBirthday
+ * }
+ * @hide
+ */
+ public static java.lang.Integer getDaysTillMyBirthday(
+ IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall) {
+ if (sDaysTillMyBirthday != null) {
+ return sDaysTillMyBirthday.query(null);
+ }
+ synchronized (sDaysTillMyBirthdayLock) {
+ if (sDaysTillMyBirthday == null) {
+ sDaysTillMyBirthday = new IpcDataCache(
+ new IpcDataCache.Config(1, "bluetooth", "custom_days_till_my_birthday",
+ "DaysTillMyBirthday"), binderCall);
+
+ }
+ }
+ return sDaysTillMyBirthday.query(null);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Custom#getDaysTillMyBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysTillMyBirthday() {
+ IpcDataCache.invalidateCache("bluetooth", "custom_days_till_my_birthday");
+ }
+
+ private final Object mDaysSinceMyBirthdayLock = new Object();
+ private IpcDataCache<java.lang.Void, java.lang.Integer> mDaysSinceMyBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Custom#getDaysSinceMyBirthday
+ * }
+ * @hide
+ */
+ public java.lang.Integer getDaysSinceMyBirthday(
+ IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall) {
+ if (mDaysSinceMyBirthday != null) {
+ return mDaysSinceMyBirthday.query(null);
+ }
+ synchronized (mDaysSinceMyBirthdayLock) {
+ if (mDaysSinceMyBirthday == null) {
+ mDaysSinceMyBirthday = new IpcDataCache(
+ new IpcDataCache.Config(1, "bluetooth", "my_unique_key",
+ "DaysSinceMyBirthday"), binderCall);
+
+ }
+ }
+ return mDaysSinceMyBirthday.query(null);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Custom#getDaysSinceMyBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysSinceMyBirthday() {
+ IpcDataCache.invalidateCache("bluetooth", "my_unique_key");
+ }
+
+ private static final Object sBirthdayWishesFromUserLock = new Object();
+ private static IpcDataCache<java.lang.Integer, java.lang.String> sBirthdayWishesFromUser;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Custom#getBirthdayWishesFromUser
+ * }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.String getBirthdayWishesFromUser(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) {
+ if (sBirthdayWishesFromUser != null) {
+ return sBirthdayWishesFromUser.query(query);
+ }
+ synchronized (sBirthdayWishesFromUserLock) {
+ if (sBirthdayWishesFromUser == null) {
+ sBirthdayWishesFromUser = new IpcDataCache(
+ new IpcDataCache.Config(4, "telephony", "custom_birthday_wishes_from_user",
+ "BirthdayWishesFromUser"), binderCall, bypassPredicate);
+
+ }
+ }
+ return sBirthdayWishesFromUser.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Custom#getBirthdayWishesFromUser }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.String getBirthdayWishesFromUser(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall,
+ java.lang.Integer query) {
+ if (sBirthdayWishesFromUser != null) {
+ return sBirthdayWishesFromUser.query(query);
+ }
+ synchronized (sBirthdayWishesFromUserLock) {
+ if (sBirthdayWishesFromUser == null) {
+ sBirthdayWishesFromUser = new IpcDataCache(
+ new IpcDataCache.Config(4, "telephony", "custom_birthday_wishes_from_user",
+ "BirthdayWishesFromUser"), binderCall);
+
+ }
+ }
+ return sBirthdayWishesFromUser.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Custom#getBirthdayWishesFromUser}
+ *
+ * @hide
+ */
+ public static final void invalidateBirthdayWishesFromUser() {
+ IpcDataCache.invalidateCache("telephony", "custom_birthday_wishes_from_user");
+ }
+
+
+ /**
+ * This method is auto-generated - initialise all caches for class CustomCache
+ *
+ * @hide
+ */
+ public static void initCache() {
+ CustomCache.invalidateBirthday();
+ CustomCache.invalidateDaysTillBirthday();
+ CustomCache.invalidateDaysSinceBirthday();
+ CustomCache.invalidateDaysTillMyBirthday();
+ CustomCache.invalidateDaysSinceMyBirthday();
+ CustomCache.invalidateBirthdayWishesFromUser();
+ }
+}
diff --git a/tools/processors/property_cache/test/resources/Default.java b/tools/processors/property_cache/test/resources/Default.java
new file mode 100644
index 000000000000..d2449aad656c
--- /dev/null
+++ b/tools/processors/property_cache/test/resources/Default.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+package android.processor.property_cache.test;
+
+import com.android.internal.annotations.CacheModifier;
+import com.android.internal.annotations.CachedProperty;
+import com.android.internal.annotations.CachedPropertyDefaults;
+
+import java.util.Date;
+
+@CachedPropertyDefaults()
+public class Default {
+ BirthdayManagerService mService = new BirthdayManagerService();
+ Object mCache = new DefaultCache();
+
+ /** Testing default class values to generate static IpcDataCache
+ *
+ * @param userId - user Id
+ * @return birthday date of given user Id
+ */
+ @CachedProperty()
+ public Date getBirthday(int userId) {
+ return DefaultCache.getBirthday(mService::getBirthday, userId);
+ }
+
+ /** Testing default class values to generate static IpcDataCache
+ *
+ * @param userId - user Id
+ * @return number of days till birthday of given user Id
+ */
+ @CachedProperty(modsFlagOnOrNone = {CacheModifier.STATIC})
+ public int getDaysTillBirthday(int userId) {
+ return DefaultCache.getDaysTillBirthday(mService::getDaysTillBirthday, userId);
+ }
+
+ /** Testing generate non-static IpcDataCache
+ *
+ * @param userId - user Id
+ * @return number of days since birthday of given user Id
+ */
+ @CachedProperty(modsFlagOnOrNone = {})
+ public int getDaysSinceBirthday(int userId) {
+ return ((DefaultCache) mCache).getDaysSinceBirthday(mService::getDaysSinceBirthday, userId);
+ }
+
+ /** Testing default class values to generate static IpcDataCache with max capacity of 1
+ *
+ * @return number of days till birthay of current user
+ */
+ @CachedProperty(
+ modsFlagOnOrNone = {CacheModifier.STATIC},
+ max = 1)
+ public int getDaysTillMyBirthday() {
+ return DefaultCache.getDaysTillMyBirthday((Void) -> mService.getDaysTillMyBirthday());
+ }
+
+ /** Testing default class values to generate static IpcDataCache with max capacity of 1 and
+ custom api
+ *
+ * @return number of days since birthay of current user
+ */
+ @CachedProperty(
+ modsFlagOnOrNone = {},
+ max = 1,
+ api = "my_unique_key")
+ public int getDaysSinceMyBirthday() {
+ return ((DefaultCache) mCache).getDaysSinceMyBirthday(
+ (Void) -> mService.getDaysSinceMyBirthday());
+ }
+
+ /** Testing default class values to generate static IpcDataCache with custom module name
+ *
+ * @return birthday wishes of given user Id
+ */
+ @CachedProperty(module = "telephony")
+ public String getBirthdayWishesFromUser(int userId) {
+ return DefaultCache.getBirthdayWishesFromUser(mService::getBirthdayWishesFromUser,
+ userId);
+ }
+
+ class BirthdayManagerService {
+
+ BirthdayManagerService() {
+ DefaultCache.initCache();
+ }
+
+ public Date getBirthday(int userId) {
+ return new Date();
+ }
+
+ public int getDaysTillBirthday(int userId) {
+ return 0;
+ }
+
+ public int getDaysSinceBirthday(int userId) {
+ return 0;
+ }
+
+ public int getDaysTillMyBirthday() {
+ return 0;
+ }
+
+ public int getDaysSinceMyBirthday() {
+ return 0;
+ }
+
+ public String getBirthdayWishesFromUser(int userId) {
+ return "Happy Birthday!\n- " + userId;
+ }
+ }
+}
diff --git a/tools/processors/property_cache/test/resources/DefaultCache.java b/tools/processors/property_cache/test/resources/DefaultCache.java
new file mode 100644
index 000000000000..9531118752bb
--- /dev/null
+++ b/tools/processors/property_cache/test/resources/DefaultCache.java
@@ -0,0 +1,402 @@
+/*
+ * 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.
+ */
+package android.processor.property_cache.test;
+
+import android.os.IpcDataCache;
+
+/**
+ * This class is auto-generated
+ *
+ * @hide
+ **/
+public class DefaultCache {
+ private static final Object sBirthdayLock = new Object();
+ private static IpcDataCache<java.lang.Integer, java.util.Date> sBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Default#getBirthday }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.util.Date getBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query
+ ) {
+ if (sBirthday != null) {
+ return sBirthday.query(query);
+ }
+ synchronized (sBirthdayLock) {
+ if (sBirthday == null) {
+ sBirthday = new IpcDataCache(
+ new IpcDataCache.Config(32, "system_server",
+ "default_birthday", "Birthday"),
+ binderCall, bypassPredicate);
+
+ }
+ }
+ return sBirthday.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Default#getBirthday }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.util.Date getBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall,
+ java.lang.Integer query
+ ) {
+ if (sBirthday != null) {
+ return sBirthday.query(query);
+ }
+ synchronized (sBirthdayLock) {
+ if (sBirthday == null) {
+ sBirthday = new IpcDataCache(
+ new IpcDataCache.Config(32, "system_server",
+ "default_birthday", "Birthday"),
+ binderCall);
+
+ }
+ }
+ return sBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Default#getBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateBirthday() {
+ IpcDataCache.invalidateCache("system_server", "default_birthday");
+ }
+
+ private static final Object sDaysTillBirthdayLock = new Object();
+ private static IpcDataCache<java.lang.Integer, java.lang.Integer> sDaysTillBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Default#getDaysTillBirthday }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.Integer getDaysTillBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query
+ ) {
+ if (sDaysTillBirthday != null) {
+ return sDaysTillBirthday.query(query);
+ }
+ synchronized (sDaysTillBirthdayLock) {
+ if (sDaysTillBirthday == null) {
+ sDaysTillBirthday = new IpcDataCache(
+ new IpcDataCache.Config(32, "system_server", "default_days_till_birthday",
+ "DaysTillBirthday"), binderCall, bypassPredicate);
+
+ }
+ }
+ return sDaysTillBirthday.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Default#getDaysTillBirthday
+ * }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.Integer getDaysTillBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ java.lang.Integer query
+ ) {
+ if (sDaysTillBirthday != null) {
+ return sDaysTillBirthday.query(query);
+ }
+ synchronized (sDaysTillBirthdayLock) {
+ if (sDaysTillBirthday == null) {
+ sDaysTillBirthday = new IpcDataCache(
+ new IpcDataCache.Config(32, "system_server", "default_days_till_birthday",
+ "DaysTillBirthday"), binderCall);
+
+ }
+ }
+ return sDaysTillBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Default#getDaysTillBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysTillBirthday() {
+ IpcDataCache.invalidateCache("system_server", "default_days_till_birthday");
+ }
+
+ private final Object mDaysSinceBirthdayLock = new Object();
+ private IpcDataCache<java.lang.Integer, java.lang.Integer> mDaysSinceBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Default#getDaysSinceBirthday }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public java.lang.Integer getDaysSinceBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query
+ ) {
+ if (mDaysSinceBirthday != null) {
+ return mDaysSinceBirthday.query(query);
+ }
+ synchronized (mDaysSinceBirthdayLock) {
+ if (mDaysSinceBirthday == null) {
+ mDaysSinceBirthday = new IpcDataCache(
+ new IpcDataCache.Config(32, "system_server", "default_days_since_birthday",
+ "DaysSinceBirthday"), binderCall, bypassPredicate);
+
+ }
+ }
+ return mDaysSinceBirthday.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Default#getDaysSinceBirthday
+ * }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public java.lang.Integer getDaysSinceBirthday(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall,
+ java.lang.Integer query
+ ) {
+ if (mDaysSinceBirthday != null) {
+ return mDaysSinceBirthday.query(query);
+ }
+ synchronized (mDaysSinceBirthdayLock) {
+ if (mDaysSinceBirthday == null) {
+ mDaysSinceBirthday = new IpcDataCache(
+ new IpcDataCache.Config(32, "system_server", "default_days_since_birthday",
+ "DaysSinceBirthday"), binderCall);
+
+ }
+ }
+ return mDaysSinceBirthday.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Default#getDaysSinceBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysSinceBirthday() {
+ IpcDataCache.invalidateCache("system_server", "default_days_since_birthday");
+ }
+
+ private static final Object sDaysTillMyBirthdayLock = new Object();
+ private static IpcDataCache<java.lang.Void, java.lang.Integer> sDaysTillMyBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link android.processor.property_cache.test.Default#getDaysTillMyBirthday
+ * }
+ * @hide
+ */
+ public static java.lang.Integer getDaysTillMyBirthday(
+ IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall
+ ) {
+ if (sDaysTillMyBirthday != null) {
+ return sDaysTillMyBirthday.query(null);
+ }
+ synchronized (sDaysTillMyBirthdayLock) {
+ if (sDaysTillMyBirthday == null) {
+ sDaysTillMyBirthday = new IpcDataCache(
+ new IpcDataCache.Config(1, "system_server", "default_days_till_my_birthday",
+ "DaysTillMyBirthday"), binderCall);
+
+ }
+ }
+ return sDaysTillMyBirthday.query(null);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Default#getDaysTillMyBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysTillMyBirthday() {
+ IpcDataCache.invalidateCache("system_server", "default_days_till_my_birthday");
+ }
+
+ private final Object mDaysSinceMyBirthdayLock = new Object();
+ private IpcDataCache<java.lang.Void, java.lang.Integer> mDaysSinceMyBirthday;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Default#getDaysSinceMyBirthday }
+ * @hide
+ */
+ public java.lang.Integer getDaysSinceMyBirthday(
+ IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall
+ ) {
+ if (mDaysSinceMyBirthday != null) {
+ return mDaysSinceMyBirthday.query(null);
+ }
+ synchronized (mDaysSinceMyBirthdayLock) {
+ if (mDaysSinceMyBirthday == null) {
+ mDaysSinceMyBirthday = new IpcDataCache(
+ new IpcDataCache.Config(1, "system_server", "my_unique_key",
+ "DaysSinceMyBirthday"), binderCall);
+
+ }
+ }
+ return mDaysSinceMyBirthday.query(null);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Default#getDaysSinceMyBirthday}
+ *
+ * @hide
+ */
+ public static final void invalidateDaysSinceMyBirthday() {
+ IpcDataCache.invalidateCache("system_server", "my_unique_key");
+ }
+
+ private static final Object sBirthdayWishesFromUserLock = new Object();
+ private static IpcDataCache<java.lang.Integer, java.lang.String> sBirthdayWishesFromUser;
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ *
+ * android.processor.property_cache.test.Default#getBirthdayWishesFromUser
+ * }
+ * @param bypassPredicate - lambda to bypass remote call
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.String getBirthdayWishesFromUser(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall,
+ IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query
+ ) {
+ if (sBirthdayWishesFromUser != null) {
+ return sBirthdayWishesFromUser.query(query);
+ }
+ synchronized (sBirthdayWishesFromUserLock) {
+ if (sBirthdayWishesFromUser == null) {
+ sBirthdayWishesFromUser = new IpcDataCache(
+ new IpcDataCache.Config(32, "telephony",
+ "default_birthday_wishes_from_user",
+ "BirthdayWishesFromUser"), binderCall, bypassPredicate);
+
+ }
+ }
+ return sBirthdayWishesFromUser.query(query);
+ }
+
+
+ /**
+ * This method is auto-generated
+ *
+ * @param binderCall - lambda for remote call
+ * {@link
+ * android.processor.property_cache.test.Default#getBirthdayWishesFromUser }
+ * @param query - parameter to call remote lambda
+ * @hide
+ */
+ public static java.lang.String getBirthdayWishesFromUser(
+ IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall,
+ java.lang.Integer query
+ ) {
+ if (sBirthdayWishesFromUser != null) {
+ return sBirthdayWishesFromUser.query(query);
+ }
+ synchronized (sBirthdayWishesFromUserLock) {
+ if (sBirthdayWishesFromUser == null) {
+ sBirthdayWishesFromUser = new IpcDataCache(
+ new IpcDataCache.Config(32, "telephony",
+ "default_birthday_wishes_from_user",
+ "BirthdayWishesFromUser"), binderCall);
+
+ }
+ }
+ return sBirthdayWishesFromUser.query(query);
+ }
+
+ /**
+ * This method is auto-generated- invalidate cache for
+ * {@link android.processor.property_cache.test.Default#getBirthdayWishesFromUser}
+ *
+ * @hide
+ */
+ public static final void invalidateBirthdayWishesFromUser() {
+ IpcDataCache.invalidateCache("telephony", "default_birthday_wishes_from_user");
+ }
+
+
+ /**
+ * This method is auto-generated - initialise all caches for class DefaultCache
+ *
+ * @hide
+ */
+ public static void initCache() {
+ DefaultCache.invalidateBirthday();
+ DefaultCache.invalidateDaysTillBirthday();
+ DefaultCache.invalidateDaysSinceBirthday();
+ DefaultCache.invalidateDaysTillMyBirthday();
+ DefaultCache.invalidateDaysSinceMyBirthday();
+ DefaultCache.invalidateBirthdayWishesFromUser();
+ }
+}