| /* |
| * Copyright (C) 2014 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.hardware.camera2.dispatch; |
| |
| import java.lang.reflect.Method; |
| |
| import static com.android.internal.util.Preconditions.*; |
| |
| /** |
| * A dispatcher that replaces one argument with another; replaces any argument at an index |
| * with another argument. |
| * |
| * <p>For example, we can override an {@code void onSomething(int x)} calls to have {@code x} always |
| * equal to 1. Or, if using this with a duck typing dispatcher, we could even overwrite {@code x} to |
| * be something |
| * that's not an {@code int}.</p> |
| * |
| * @param <T> |
| * source dispatch type, whose methods with {@link #dispatch} will be called |
| * @param <TArg> |
| * argument replacement type, args in {@link #dispatch} matching {@code argumentIndex} |
| * will be overriden to objects of this type |
| */ |
| public class ArgumentReplacingDispatcher<T, TArg> implements Dispatchable<T> { |
| |
| private final Dispatchable<T> mTarget; |
| private final int mArgumentIndex; |
| private final TArg mReplaceWith; |
| |
| /** |
| * Create a new argument replacing dispatcher; dispatches are forwarded to {@code target} |
| * after the argument is replaced. |
| * |
| * <p>For example, if a method {@code onAction(T1 a, Integer b, T2 c)} is invoked, and we wanted |
| * to replace all occurrences of {@code b} with {@code 0xDEADBEEF}, we would set |
| * {@code argumentIndex = 1} and {@code replaceWith = 0xDEADBEEF}.</p> |
| * |
| * <p>If a method dispatched has less arguments than {@code argumentIndex}, it is |
| * passed through with the arguments unchanged.</p> |
| * |
| * @param target destination dispatch type, methods will be redirected to this dispatcher |
| * @param argumentIndex the numeric index of the argument {@code >= 0} |
| * @param replaceWith arguments matching {@code argumentIndex} will be replaced with this object |
| */ |
| public ArgumentReplacingDispatcher(Dispatchable<T> target, int argumentIndex, |
| TArg replaceWith) { |
| mTarget = checkNotNull(target, "target must not be null"); |
| mArgumentIndex = checkArgumentNonnegative(argumentIndex, |
| "argumentIndex must not be negative"); |
| mReplaceWith = checkNotNull(replaceWith, "replaceWith must not be null"); |
| } |
| |
| @Override |
| public Object dispatch(Method method, Object[] args) throws Throwable { |
| |
| if (args.length > mArgumentIndex) { |
| args = arrayCopy(args); // don't change in-place since it can affect upstream dispatches |
| args[mArgumentIndex] = mReplaceWith; |
| } |
| |
| return mTarget.dispatch(method, args); |
| } |
| |
| private static Object[] arrayCopy(Object[] array) { |
| int length = array.length; |
| Object[] newArray = new Object[length]; |
| for (int i = 0; i < length; ++i) { |
| newArray[i] = array[i]; |
| } |
| return newArray; |
| } |
| } |