1b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar/* 264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar * Copyright (C) 2017 The Android Open Source Project 3b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * 4b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * you may not use this file except in compliance with the License. 6b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * You may obtain a copy of the License at 7b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * 8b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * 10b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * See the License for the specific language governing permissions and 14b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * limitations under the License. 15b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar */ 16b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 1764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarpackage android.arch.lifecycle; 18b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 19b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinetsimport android.arch.lifecycle.Lifecycle.Event; 20b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 2119b41105359a52aeb80070dec40247241231f05dYigit Boyarimport java.lang.reflect.InvocationTargetException; 22b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyarimport java.lang.reflect.Method; 23b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyarimport java.util.ArrayList; 24b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyarimport java.util.HashMap; 25b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyarimport java.util.List; 26b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyarimport java.util.Map; 27daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinetsimport java.util.Map.Entry; 28b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 29b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar/** 30b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar * An internal implementation of {@link GenericLifecycleObserver} that relies on reflection. 31b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar */ 32b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyarclass ReflectiveGenericLifecycleObserver implements GenericLifecycleObserver { 33b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar private final Object mWrapped; 34b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar private final CallbackInfo mInfo; 35b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar @SuppressWarnings("WeakerAccess") 36b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar static final Map<Class, CallbackInfo> sInfoCache = new HashMap<>(); 37b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 38b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar ReflectiveGenericLifecycleObserver(Object wrapped) { 39b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar mWrapped = wrapped; 40b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar mInfo = getInfo(mWrapped.getClass()); 41b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 42b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 43b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar @Override 44b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets public void onStateChanged(LifecycleOwner source, Event event) { 450bc2a6a0aae3c50591dd09ba324d884a902187caSergey Vasilinets invokeCallbacks(mInfo, source, event); 46b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 47b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 48044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets private void invokeMethodsForEvent(List<MethodReference> handlers, LifecycleOwner source, 49044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets Event event) { 50044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets if (handlers != null) { 51044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets for (int i = handlers.size() - 1; i >= 0; i--) { 52044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets MethodReference reference = handlers.get(i); 530bc2a6a0aae3c50591dd09ba324d884a902187caSergey Vasilinets invokeCallback(reference, source, event); 54b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 55b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 56044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets } 57044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets 58044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets @SuppressWarnings("ConstantConditions") 59044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets private void invokeCallbacks(CallbackInfo info, LifecycleOwner source, Event event) { 60daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets invokeMethodsForEvent(info.mEventToHandlers.get(event), source, event); 61daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets invokeMethodsForEvent(info.mEventToHandlers.get(Event.ON_ANY), source, event); 62b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 63b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 640bc2a6a0aae3c50591dd09ba324d884a902187caSergey Vasilinets private void invokeCallback(MethodReference reference, LifecycleOwner source, Event event) { 65044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets //noinspection TryWithIdenticalCatches 66044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets try { 67044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets switch (reference.mCallType) { 68044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets case CALL_TYPE_NO_ARG: 69044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets reference.mMethod.invoke(mWrapped); 70044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets break; 71044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets case CALL_TYPE_PROVIDER: 72044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets reference.mMethod.invoke(mWrapped, source); 73044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets break; 74044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets case CALL_TYPE_PROVIDER_WITH_EVENT: 75044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets reference.mMethod.invoke(mWrapped, source, event); 76044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets break; 77b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 78044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets } catch (InvocationTargetException e) { 79044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets throw new RuntimeException("Failed to call observer method", e.getCause()); 80044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets } catch (IllegalAccessException e) { 81044fe16ec17aeb265ad988fe601cbac6e6bd39a4Sergey Vasilinets throw new RuntimeException(e); 82b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 83b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 84b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 85b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar private static CallbackInfo getInfo(Class klass) { 86b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar CallbackInfo existing = sInfoCache.get(klass); 87b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar if (existing != null) { 88b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar return existing; 89b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 90b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar existing = createInfo(klass); 91b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar return existing; 92b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 93b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 94daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets private static void verifyAndPutHandler(Map<MethodReference, Event> handlers, 95daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets MethodReference newHandler, Event newEvent, Class klass) { 96daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets Event event = handlers.get(newHandler); 97daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (event != null && newEvent != event) { 98daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets Method method = newHandler.mMethod; 99daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets throw new IllegalArgumentException( 100daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets "Method " + method.getName() + " in " + klass.getName() 101daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets + " already declared with different @OnLifecycleEvent value: previous" 102daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets + " value " + event + ", new value " + newEvent); 103daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 104daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (event == null) { 105daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets handlers.put(newHandler, newEvent); 106daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 107daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 108daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 109b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar private static CallbackInfo createInfo(Class klass) { 110daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets Class superclass = klass.getSuperclass(); 111daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets Map<MethodReference, Event> handlerToEvent = new HashMap<>(); 112daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (superclass != null) { 113daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets CallbackInfo superInfo = getInfo(superclass); 114daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (superInfo != null) { 115daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets handlerToEvent.putAll(superInfo.mHandlerToEvent); 116daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 117daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 118daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 119b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar Method[] methods = klass.getDeclaredMethods(); 120daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 121daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets Class[] interfaces = klass.getInterfaces(); 122daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets for (Class intrfc : interfaces) { 123daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets for (Entry<MethodReference, Event> entry : getInfo(intrfc).mHandlerToEvent.entrySet()) { 124daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass); 125daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 126daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 127daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 128b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar for (Method method : methods) { 1294c90a591fe9521ebf90a319bb90846f5c193f4eaYigit Boyar OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class); 130b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar if (annotation == null) { 131b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar continue; 132b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 133b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar Class<?>[] params = method.getParameterTypes(); 134b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar int callType = CALL_TYPE_NO_ARG; 135b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar if (params.length > 0) { 136b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar callType = CALL_TYPE_PROVIDER; 137e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets if (!params[0].isAssignableFrom(LifecycleOwner.class)) { 138b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar throw new IllegalArgumentException( 139e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets "invalid parameter type. Must be one and instanceof LifecycleOwner"); 140b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 141b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 1425ef35b172e9d0e082ba0e544f0c591bf6e1507f0Sergey Vasilinets Event event = annotation.value(); 1435ef35b172e9d0e082ba0e544f0c591bf6e1507f0Sergey Vasilinets 144b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar if (params.length > 1) { 1454c90a591fe9521ebf90a319bb90846f5c193f4eaYigit Boyar callType = CALL_TYPE_PROVIDER_WITH_EVENT; 146b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets if (!params[1].isAssignableFrom(Event.class)) { 147b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar throw new IllegalArgumentException( 1484c90a591fe9521ebf90a319bb90846f5c193f4eaYigit Boyar "invalid parameter type. second arg must be an event"); 149b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 1505ef35b172e9d0e082ba0e544f0c591bf6e1507f0Sergey Vasilinets if (event != Event.ON_ANY) { 1515ef35b172e9d0e082ba0e544f0c591bf6e1507f0Sergey Vasilinets throw new IllegalArgumentException( 1525ef35b172e9d0e082ba0e544f0c591bf6e1507f0Sergey Vasilinets "Second arg is supported only for ON_ANY value"); 1535ef35b172e9d0e082ba0e544f0c591bf6e1507f0Sergey Vasilinets } 154b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 155b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar if (params.length > 2) { 156b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar throw new IllegalArgumentException("cannot have more than 2 params"); 157b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 158daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets MethodReference methodReference = new MethodReference(callType, method); 159daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets verifyAndPutHandler(handlerToEvent, methodReference, event, klass); 160b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 161daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets CallbackInfo info = new CallbackInfo(handlerToEvent); 162b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar sInfoCache.put(klass, info); 163b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar return info; 164b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 165b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 166b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar @SuppressWarnings("WeakerAccess") 167b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar static class CallbackInfo { 168daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets final Map<Event, List<MethodReference>> mEventToHandlers; 169daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets final Map<MethodReference, Event> mHandlerToEvent; 170daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 171daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets CallbackInfo(Map<MethodReference, Event> handlerToEvent) { 172daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets mHandlerToEvent = handlerToEvent; 173daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets mEventToHandlers = new HashMap<>(); 174daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets for (Entry<MethodReference, Event> entry : handlerToEvent.entrySet()) { 175daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets Event event = entry.getValue(); 176daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets List<MethodReference> methodReferences = mEventToHandlers.get(event); 177daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (methodReferences == null) { 178daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets methodReferences = new ArrayList<>(); 179daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets mEventToHandlers.put(event, methodReferences); 180daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 181daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets methodReferences.add(entry.getKey()); 182daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 183b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 184b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 185b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 186b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar @SuppressWarnings("WeakerAccess") 187b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar static class MethodReference { 188b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar final int mCallType; 189b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar final Method mMethod; 190b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 191daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets MethodReference(int callType, Method method) { 192b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar mCallType = callType; 193b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar mMethod = method; 194b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets mMethod.setAccessible(true); 195b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 196daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 197daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets @Override 198daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets public boolean equals(Object o) { 199daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (this == o) { 200daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets return true; 201daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 202daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets if (o == null || getClass() != o.getClass()) { 203daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets return false; 204daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 205daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 206daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets MethodReference that = (MethodReference) o; 207daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets return mCallType == that.mCallType && mMethod.getName().equals(that.mMethod.getName()); 208daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 209daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets 210daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets @Override 211daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets public int hashCode() { 212daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets return 31 * mCallType + mMethod.getName().hashCode(); 213daa68aab1adbf8c5b5c64d2b34a60955da742f1dSergey Vasilinets } 214b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar } 215b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar 216b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar private static final int CALL_TYPE_NO_ARG = 0; 217b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar private static final int CALL_TYPE_PROVIDER = 1; 2184c90a591fe9521ebf90a319bb90846f5c193f4eaYigit Boyar private static final int CALL_TYPE_PROVIDER_WITH_EVENT = 2; 219b18b96e1ff52c6ee522b592005f0525511e5d083Yigit Boyar} 220