aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKolin Lu <kolinlu@google.com>2023-04-27 16:17:19 -0700
committerGitHub <noreply@github.com>2023-04-27 16:17:19 -0700
commit1d3fa077dd023d0174ce282bdbf9d2c9bd9f4b83 (patch)
treee516d5d795675fc71b5ff5410faf8f5f8d84c07c
parent20d9d3dfda778f8394c6468f5793f14a824a8f06 (diff)
downloadmobly-snippet-lib-1d3fa077dd023d0174ce282bdbf9d2c9bd9f4b83.tar.gz
Support `@RpcOptional`
With this annotation, arguments which are not present when calling will be assign `null` value by default. Usage: ```java @Rpc(description = "Returns true if value is null, false otherwise.") public boolean isValueNull(@RpcOptional Integer value) { return value == null; } ``` ```python assert mbs.isValueNull()==True assert mbs.isValueNull(0)==False ```
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java39
-rw-r--r--third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/RpcOptional.java34
2 files changed, 73 insertions, 0 deletions
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
index b9c8a7a..506fae9 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
@@ -22,6 +22,7 @@ import com.google.android.mobly.snippet.Snippet;
import com.google.android.mobly.snippet.manager.SnippetManager;
import com.google.android.mobly.snippet.manager.SnippetObjectConverterManager;
import com.google.android.mobly.snippet.util.AndroidUtil;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -68,6 +69,7 @@ public final class MethodDescriptor {
* @throws Throwable the exception raised from executing the RPC method.
*/
public Object invoke(SnippetManager manager, final JSONArray parameters) throws Throwable {
+ final Annotation annotations[][] = getParameterAnnotations();
final Type[] parameterTypes = getGenericParameterTypes();
final Object[] args = new Object[parameterTypes.length];
@@ -79,6 +81,8 @@ public final class MethodDescriptor {
final Type parameterType = parameterTypes[i];
if (i < parameters.length()) {
args[i] = convertParameter(parameters, i, parameterType);
+ } else if (MethodDescriptor.hasDefaultValue(annotations[i])) {
+ args[i] = MethodDescriptor.getDefaultValue(parameterType, annotations[i]);
} else {
throw new RpcError("Argument " + (i + 1) + " is not present");
}
@@ -218,6 +222,10 @@ public final class MethodDescriptor {
return mClass;
}
+ public Annotation[][] getParameterAnnotations() {
+ return mMethod.getParameterAnnotations();
+ }
+
private String getAnnotationDescription() {
if (isAsync()) {
AsyncRpc annotation = mMethod.getAnnotation(AsyncRpc.class);
@@ -226,6 +234,7 @@ public final class MethodDescriptor {
Rpc annotation = mMethod.getAnnotation(Rpc.class);
return annotation.description();
}
+
/**
* Returns a human-readable help text for this RPC, based on annotations in the source code.
*
@@ -249,4 +258,34 @@ public final class MethodDescriptor {
mMethod.getReturnType().getSimpleName(),
getAnnotationDescription());
}
+
+ /**
+ * Returns the default value for a specific parameter.
+ *
+ * @param parameterType parameterType
+ * @param annotations annotations of the parameter
+ */
+ public static Object getDefaultValue(Type parameterType, Annotation[] annotations) {
+ for (Annotation a : annotations) {
+ if (a instanceof RpcOptional) {
+ return null;
+ }
+ }
+ throw new IllegalStateException("No default value for " + parameterType);
+ }
+
+ /**
+ * Determines whether or not this parameter has default value.
+ *
+ * @param annotations annotations of the parameter
+ */
+ public static boolean hasDefaultValue(Annotation[] annotations) {
+ for (Annotation a : annotations) {
+ if (a instanceof RpcOptional) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/RpcOptional.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/RpcOptional.java
new file mode 100644
index 0000000..b4b43aa
--- /dev/null
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/RpcOptional.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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 com.google.android.mobly.snippet.rpc;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to mark RPC parameter as optional.
+ *
+ * <p>The parameter marked as optional has no explicit default value. {@code null} is used as
+ * default value.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+@Documented
+public @interface RpcOptional {}