• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.nearby.common.bluetooth.fastpair;
18 
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 
22 /**
23  * Utilities for calling methods using reflection. The main benefit of using this helper is to avoid
24  * complications around exception handling when calling methods reflectively. It's not safe to use
25  * Java 8's multicatch on such exceptions, because the java compiler converts multicatch into
26  * ReflectiveOperationException in some instances, which doesn't work on older sdk versions.
27  * Instead, use these utilities and catch ReflectionException.
28  *
29  * <p>Example usage:
30  *
31  * <pre>{@code
32  * try {
33  *   Reflect.on(btAdapter)
34  *       .withMethod("setScanMode", int.class)
35  *       .invoke(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE)
36  * } catch (ReflectionException e) { }
37  * }</pre>
38  */
39 // TODO(b/202549655): remove existing Reflect usage. New usage is not allowed! No exception!
40 public final class Reflect {
41     private final Object mTargetObject;
42 
Reflect(Object targetObject)43     private Reflect(Object targetObject) {
44         this.mTargetObject = targetObject;
45     }
46 
47     /** Creates an instance of this helper to invoke methods on the given target object. */
on(Object targetObject)48     public static Reflect on(Object targetObject) {
49         return new Reflect(targetObject);
50     }
51 
52     /** Finds a method with the given name and parameter types. */
withMethod(String methodName, Class<?>... paramTypes)53     public ReflectionMethod withMethod(String methodName, Class<?>... paramTypes)
54             throws ReflectionException {
55         try {
56             return new ReflectionMethod(mTargetObject.getClass().getMethod(methodName, paramTypes));
57         } catch (NoSuchMethodException e) {
58             throw new ReflectionException(e);
59         }
60     }
61 
62     /** Represents an invokable method found reflectively. */
63     public final class ReflectionMethod {
64         private final Method mMethod;
65 
ReflectionMethod(Method method)66         private ReflectionMethod(Method method) {
67             this.mMethod = method;
68         }
69 
70         /**
71          * Invokes this instance method with the given parameters. The called method does not return
72          * a value.
73          */
invoke(Object... parameters)74         public void invoke(Object... parameters) throws ReflectionException {
75             try {
76                 mMethod.invoke(mTargetObject, parameters);
77             } catch (IllegalAccessException e) {
78                 throw new ReflectionException(e);
79             } catch (InvocationTargetException e) {
80                 throw new ReflectionException(e);
81             }
82         }
83 
84         /**
85          * Invokes this instance method with the given parameters. The called method returns a non
86          * null value.
87          */
get(Object... parameters)88         public Object get(Object... parameters) throws ReflectionException {
89             Object value;
90             try {
91                 value = mMethod.invoke(mTargetObject, parameters);
92             } catch (IllegalAccessException e) {
93                 throw new ReflectionException(e);
94             } catch (InvocationTargetException e) {
95                 throw new ReflectionException(e);
96             }
97             if (value == null) {
98                 throw new ReflectionException(new NullPointerException());
99             }
100             return value;
101         }
102     }
103 }
104