/****************************************************************************
**
** Copyright (C) 2010-2012 UC Mobile Ltd. All Rights Reserved
** File : ViewRootHelper.java
**
** Description : Use reflection to call methods on ViewRoot/ViewRootImpl above Android 2.2
**
** Creation : 2012/11/13
** Author : Roger (yixx@ucweb.com)
** History :
** Creation, 2012/11/13, Roger, Create the file
**
****************************************************************************/
package com.uc.webkit.helper;
import java.lang.reflect.Method;
import android.graphics.Rect;
import android.util.Log;
import android.view.KeyEvent;
public class ViewRootHelper {
private static final String TAG = "ViewRootHelper";
private static Class<?> viewRootImplClass;
private static Method methodDetachFunctorInt = null;
private static Method methodAttachFunctorInt = null;
private static Method methodDetachFunctorLong = null;
private static Method methodInvalidate = null;
private static Method methodInvalidateChildInParent = null;
private static Method methodDispatchUnhandledKey = null;
static {
try {
viewRootImplClass = Class.forName("android.view.ViewRootImpl");
// In Android L, to support 64bits, the native-ptr pass through JNI
// has been changed from Integer to Long type,
// and attachFunctor method has been removed
try {
methodDetachFunctorInt = viewRootImplClass.getMethod("detachFunctor", new Class<?>[] {Integer.TYPE});
methodAttachFunctorInt = viewRootImplClass.getMethod("attachFunctor", new Class<?>[] {Integer.TYPE});
} catch (Throwable t) {
methodDetachFunctorLong = viewRootImplClass.getMethod("detachFunctor", new Class<?>[] {Long.TYPE});
}
methodInvalidate = viewRootImplClass.getDeclaredMethod("invalidate");
if (methodInvalidate != null)
methodInvalidate.setAccessible(true);
methodInvalidateChildInParent = viewRootImplClass.getMethod(
"invalidateChildInParent",
new Class<?>[] {int[].class, Rect.class});
try {
methodDispatchUnhandledKey = viewRootImplClass.getMethod("dispatchUnhandledKey", KeyEvent.class);
} catch (Throwable t) {
Log.e(TAG, "android.view.ViewRootImpl can not get method dispatchUnhandledKey!");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
public static void detachFunctor(Object viewRoot, long functor) {
if (viewRootImplClass != null && methodDetachFunctorInt != null) {
try {
methodDetachFunctorInt.invoke(viewRoot, (int) functor);
} catch (Throwable t) {
t.printStackTrace();
}
}
if (viewRootImplClass != null && methodDetachFunctorLong != null) {
try {
methodDetachFunctorLong.invoke(viewRoot, functor);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
public static boolean attachFunctor(Object viewRoot, long functor) {
if (viewRootImplClass != null && methodAttachFunctorInt != null) {
try {
Object result = methodAttachFunctorInt.invoke(viewRoot, (int) functor);
return (Boolean) result;
} catch (Throwable t) {
t.printStackTrace();
}
}
return false;
}
public static boolean invalidate(Object viewRoot) {
if (viewRootImplClass != null && methodInvalidate != null) {
try {
methodInvalidate.invoke(viewRoot);
return true;
} catch (Throwable t) {
t.printStackTrace();
}
}
return false;
}
public static boolean invalidateChildInParent(Object viewRoot, Rect dirty) {
if (viewRootImplClass != null && methodInvalidateChildInParent != null) {
try {
methodInvalidateChildInParent.invoke(viewRoot, null, dirty);
return true;
} catch (Throwable t) {
t.printStackTrace();
}
}
return false;
}
public static void dispatchUnhandledKey(Object viewRoot, KeyEvent event) {
if (viewRootImplClass != null && methodDispatchUnhandledKey != null) {
try {
methodDispatchUnhandledKey.invoke(viewRoot, event);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}