package me.barrasso.android.volume.utils; import java.lang.reflect.Method; import android.os.IInterface; import android.os.IBinder; import android.util.Log; import me.barrasso.android.volume.LogUtils; /** * Utility class mostly for interfacing with low-level or hidden APIs. */ public final class ReflectionUtils { // Cached system Context and ServiceManager. private static IInterface sServiceManager; private static IBinder sContext; private static Object wManagerGlobal; /** @return A global, system {@link IBinder} object. */ public static IBinder getContext() { if (sContext != null) return sContext; try { Class<?> mBinder = Class.forName("com.android.internal.os.BinderInternal"); if (mBinder == null) return null; Method mMethod = mBinder.getDeclaredMethod("getContextObject"); if (mMethod == null) return null; mMethod.setAccessible(true); sContext = (IBinder) mMethod.invoke(null); } catch (Throwable e) { LogUtils.LOGE("Reflection", "Error obtaining global Context.", e); } return sContext; } /** @return A WindowManagerGlobal instance. */ public static Object getWindowManagerGlobal() { if (wManagerGlobal != null) return wManagerGlobal; try { Class<?> mWindowManagerGlobal = Class.forName("android.view.WindowManagerGlobal"); if (null == mWindowManagerGlobal) return null; Method mMethod = mWindowManagerGlobal.getDeclaredMethod("getInstance"); if (null == mMethod) return null; mMethod.setAccessible(true); wManagerGlobal = mMethod.invoke(null); } catch (Throwable t) { LogUtils.LOGE("ReflectionUtils", "Error accessing WindowManagerGlobal.", t); } return wManagerGlobal; } /** * Obtain the IServiceManager reference for obtaining * system services and such. */ public static IInterface getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager try { Class<?> mManager = Class.forName("android.os.ServiceManagerNative"); if (mManager == null) return null; Method mMethod = mManager.getDeclaredMethod("asInterface", IBinder.class); if (mMethod == null) return null; mMethod.setAccessible(true); sServiceManager = (IInterface) mMethod.invoke(null, getContext()); } catch (Throwable e) { LogUtils.LOGE("Reflection", "Error accessing ServiceManagerNative.", e); } return sServiceManager; } /** * ServiceManager.getService(String name) * Obtains an {@link IBinder} reference of a system service. */ public static IBinder getService(String name) { try { final IInterface mService = ReflectionUtils.getIServiceManager(); Method mMethod = mService.getClass().getDeclaredMethod( "getService", new Class[] { String.class }); if (mMethod == null) return null; mMethod.setAccessible(true); return (IBinder) mMethod.invoke(mService, name); } catch (Throwable e) { LogUtils.LOGE("Reflection", "Error accessing ServiceManager.getService().", e); } return null; } /** * Obtain the ServiceManager reference for obtaining * system services and such. */ public static IBinder getServiceManager(String name) { // Find the service manager try { Class<?> mManager = Class.forName("android.os.ServiceManager"); if (mManager == null) return null; Method mMethod = mManager.getMethod("getService", String.class); if (mMethod == null) return null; mMethod.setAccessible(true); return (IBinder) mMethod.invoke(null, name); } catch (Throwable e) { LogUtils.LOGE("Reflection", "Error getServiceManager(" + name + ")", e); } return null; } /** * Obtain an {@link IInterface} reference for communicating * with a system service. */ public static IInterface getIInterface(String name, String serviceName) { try { Class<?> mManager = Class.forName(serviceName); if (mManager == null) return null; IInterface mService = ReflectionUtils.getIServiceManager(); Method mMethod = mManager.getMethod("asInterface", IBinder.class); if (mMethod == null) return null; mMethod.setAccessible(true); return (IInterface) mMethod.invoke(null, getService(name)); } catch (Throwable e) { LogUtils.LOGE("Reflection", "Error accessing " + name + " IInteface.", e); } return null; } }