diff options
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(); + } +} |