设计模式学习之代理模式

代理模式,可以分为两种,一种是静态代理,一种是动态代理。
两种代理从虚拟机加载类的角度来讲,本质上都是一样的,都是在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有的行为。在我们平时写代码的过程中,代理模式可以说是随处可见,所以,本篇博客就将给大家介绍代理模式。

基本概念

代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。

UML图

Subject:抽象主题类,声明真实主题与代理的共同接口方法。
RealSubject:真实主题类,定义了代理所表示的真实对象,客户端通过代理类间接的调用真实主题类的方法。
Proxy:代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
Client:客户端类。

静态代理

静态代理一般具有如下特点:
1.代理类一般要持有一个被代理的对象的引用
2.对于我们不关心的方法,全部委托给被代理
3.自己处理我们关心的方法

静态代理的简单示例:
我们都知道网上代购的例子,假设小明想要购买外星人电脑,他委托在美国的好朋友帮他购买。

抽象主题类(Subject)
抽象主题类具有真实主题类和代理的共同接口方法,在这里共同的方法就是购买:

public interface IShop {
    //购买
    void buy();
}

真实主题类(RealSubject)
例子中就是小明,他需要实现IShop接口提供的 buy()方法

public class XiaoMing implements IShop{
    @Override
    public void buy() {
        System.out.println("小明进行购买");
    }
}

代理类(Proxy)
小明的朋友,也就是代理类同样也要实现IShop接口,并且要持有被代理者,在buy()方法中调用了被代理者的buy()方法

public class ProxyBuyer implements IShop{
    private IShop mShop;
    public ProxyBuyer(IShop shop){
        mShop=shop;
    }
    @Override
    public void buy() {
        mShop.buy();
    }
}

客户端类(Client)

public class Client {
    public static void main(String[] args) {

        IShop xiaoMing = new XiaoMing();
        //创建代购者并将xiaoMing作为构造函数传
        IShop proxyBuyer = new ProxyBuyer(xiaoMing);
        proxyBuyer.buy();
    }
}

代码很简单,就是代理类包含了真实主题类(被代理者),最终调用的都是真实主题类(被代理者)实现的方法,上面的例子中,代理类的购买方法调用了真实主题类的购买方法,完成了“代购”的过程,这就是代理模式最简单的用法,归结为一句话:代理类和被代理类实现相同的接口,代理类持有被代理类的引用,代理方法执行时,同步调用被代理类的相同方法。

静态代理在项目中的应用

理解了最简单的静态代理的使用方法后,我介绍一下,在我写项目过程中,应用到静态代理的一个例子。线程在安卓开发中几乎随处可见,线程的管理显得格外重要,所以在项目中我创建一个ThreadPoolManager来管理线程池。

public class ThreadPoolManager {

    private static HashMap sThreadPoolManagerhHashMap = new HashMap();

    private final static int DEFAULT_COREPOOL_SIZE = 4;
    private final static int DEFAULT_MAXIMUMPOOL_SIZE = 4;
    private final static long DEFAULT_KEEPALIVE_TIME = 0;
    private final static TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS;
    private static ScheduledExecutorService sScheduledExecutorService = null; // 调度线程池
    private static ScheduledRunnable sScheduledRunnable = null; // 调度Runnable
    private ThreadPoolExecutor mWorkThreadPool = null; // 线程池
    private Queue mWaitTasksQueue = null; // 等待任务队列
    private RejectedExecutionHandler mRejectedExecutionHandler = null; // 任务被拒绝执行的处理器
    private Object mLock = new Object();
    private String mName;

    private ThreadPoolManager() {
        this(DEFAULT_COREPOOL_SIZE, DEFAULT_MAXIMUMPOOL_SIZE, DEFAULT_KEEPALIVE_TIME,
                DEFAULT_TIMEUNIT, false, null);
    }

    private ThreadPoolManager(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                              TimeUnit unit, boolean isPriority, final ITaskExecuteListener listener) {
        mWaitTasksQueue = new ConcurrentLinkedQueue();
        if (sScheduledRunnable == null) {
            sScheduledRunnable = new ScheduledRunnable();
            sScheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
            sScheduledExecutorService.scheduleAtFixedRate(sScheduledRunnable, 0, 1500,
                    TimeUnit.MILLISECONDS);
        }
        initRejectedExecutionHandler();
        BlockingQueue queue = isPriority
                ? new PriorityBlockingQueue(16)
                : new LinkedBlockingQueue(16);
        if (listener == null) {
            mWorkThreadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
                    unit, queue, mRejectedExecutionHandler);
        } else {
            mWorkThreadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
                    unit, queue, mRejectedExecutionHandler) {
                @Override
                protected void beforeExecute(Thread t, Runnable r) {
                    listener.beforeExecute(t, r);
                }

                @Override
                protected void afterExecute(Runnable r, Throwable t) {
                    listener.afterExecute(r, t);
                }
            };
        }
    }

    public static ThreadPoolManager getInstance(String threadPoolManagerName) {
        ThreadPoolManager threadPoolManager = null;
        if (threadPoolManagerName != null && !"".equals(threadPoolManagerName.trim())) {
            synchronized (sThreadPoolManagerhHashMap) {
                threadPoolManager = sThreadPoolManagerhHashMap.get(threadPoolManagerName);
                if (null == threadPoolManager) {
                    threadPoolManager = new ThreadPoolManager();
                    threadPoolManager.mName = threadPoolManagerName;
                    sThreadPoolManagerhHashMap.put(threadPoolManagerName, threadPoolManager);
                }
            }
        }
        return threadPoolManager;
    }

    public static ThreadPoolManager buildInstance(String threadPoolManagerName,
                                                  int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
                                                  boolean isPriority, ITaskExecuteListener listener) {
        if (threadPoolManagerName == null || "".equals(threadPoolManagerName.trim())
                || corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize
                || keepAliveTime < 0) {
            return null;
        } else {
            ThreadPoolManager threadPoolManager = new ThreadPoolManager(corePoolSize,
                    maximumPoolSize, keepAliveTime, unit, isPriority, listener);
            threadPoolManager.mName = threadPoolManagerName;
            synchronized (sThreadPoolManagerhHashMap) {
                sThreadPoolManagerhHashMap.put(threadPoolManagerName, threadPoolManager);
            }
            return threadPoolManager;
        }
    }

    /**
     * 初始化调度Runable
     */
    private static class ScheduledRunnable implements Runnable {
        @Override
        public void run() {
            synchronized (sThreadPoolManagerhHashMap) {
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
                Collection values = sThreadPoolManagerhHashMap.values();
                for (ThreadPoolManager manager : values) {
                    manager.executeWaitTask();
                }
            }
        }
    }

    private void executeWaitTask() {
        synchronized (mLock) {
            if (hasMoreWaitTask()) {
                Runnable runnable = mWaitTasksQueue.poll();
                if (runnable != null) {
                    execute(runnable);
                }
            }
        }
    }

    /**
     * 初始化任务被拒绝执行的处理器的方法
     */
    private void initRejectedExecutionHandler() {
        mRejectedExecutionHandler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                // 把被拒绝的任务重新放入到等待队列中
                synchronized (mLock) {
                    mWaitTasksQueue.offer(r);
                }
            }
        };
    }

    /**
     * 是否还有等待任务的方法
     *
     * @return
     */
    public boolean hasMoreWaitTask() {
        boolean result = false;
        if (!mWaitTasksQueue.isEmpty()) {
            result = true;
        }
        return result;
    }

    /**
     * 执行任务的方法
     *
     * @param task
     */
    public void execute(Runnable task) {
        if (task != null) {
            mWorkThreadPool.execute(task);
        }
    }

    /**
     * 取消任务
     *
     * @param task
     */
    public void cancel(Runnable task) {
        if (task != null) {
            synchronized (mLock) {
                if (mWaitTasksQueue.contains(task)) {
                    mWaitTasksQueue.remove(task);
                }
            }
            mWorkThreadPool.remove(task);
        }
    }

    public void removeAllTask() {
        // 如果取task过程中task队列数量改变了会抛异常
        try {
            if (!mWorkThreadPool.isShutdown()) {
                BlockingQueue tasks = mWorkThreadPool.getQueue();
                for (Runnable task : tasks) {
                    mWorkThreadPool.remove(task);
                }
            }
        } catch (Throwable e) {
            Log.e("ThreadPoolManager", "removeAllTask " + e.getMessage());
        }
    }

    public boolean isShutdown() {
        return mWorkThreadPool.isShutdown();
    }

    /**
     * 清理方法
     */
    private void cleanUp() {
        if (!mWorkThreadPool.isShutdown()) {
            try {
                mWorkThreadPool.shutdownNow();
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
        mRejectedExecutionHandler = null;
        synchronized (mLock) {
            mWaitTasksQueue.clear();
        }
    }

    /**
     * 销毁全部ThreadPoolManager
     */
    public static void destroyAll() {
        synchronized (sThreadPoolManagerhHashMap) {
            Set keySet = sThreadPoolManagerhHashMap.keySet();
            if (keySet != null && keySet.size() > 0) {
                ThreadPoolManager threadPoolManager = null;
                for (String key : keySet) {
                    threadPoolManager = sThreadPoolManagerhHashMap.get(key);
                    if (threadPoolManager != null) {
                        threadPoolManager.cleanUp();
                    }
                }
            }
            sThreadPoolManagerhHashMap.clear();
        }
        if (sScheduledExecutorService != null) {
            if (!sScheduledExecutorService.isShutdown()) {
                try {
                    sScheduledExecutorService.shutdownNow();
                } catch (Exception e) {
                    // do nothing
                }
            }
            sScheduledExecutorService = null;
        }
        if (sScheduledRunnable != null) {
            sScheduledRunnable = null;
        }
    }

    /**
     * 销毁某个ThreadPoolManager
     * @param threadPoolManagerName
     */
    public static void destroy(String threadPoolManagerName) {
        synchronized (sThreadPoolManagerhHashMap) {
            ThreadPoolManager threadPoolManager = sThreadPoolManagerhHashMap
                    .get(threadPoolManagerName);
            if (threadPoolManager != null) {
                threadPoolManager.cleanUp();
            }
        }
    }

    /**
     * 
     */
    public static interface ITaskExecuteListener {
        public void beforeExecute(Thread thread, Runnable task);
        public void afterExecute(Runnable task, Throwable throwable);
    }
}

ThreadPoolManager主要有以下逻辑:
1.ScheduledRunnable对象负责调度sThreadPoolManagerhHashMap中的ThreadPoolManager执行任务

 private static class ScheduledRunnable implements Runnable {
        @Override
        public void run() {
            synchronized (sThreadPoolManagerhHashMap) {
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
                Collection values = sThreadPoolManagerhHashMap.values();
                for (ThreadPoolManager manager : values) {
                    manager.executeWaitTask();
                }
            }
        }
    }

2.sThreadPoolManagerhHashMap是一个HashMap,以ThreadPoolManager的名字为key,ThreadPoolManager为值对ThreadPoolManager进行管理,保证同名的ThreadPoolManager只有一个。

  public static ThreadPoolManager getInstance(String threadPoolManagerName) {
        ThreadPoolManager threadPoolManager = null;
        if (threadPoolManagerName != null && !"".equals(threadPoolManagerName.trim())) {
            synchronized (sThreadPoolManagerhHashMap) {
                threadPoolManager = sThreadPoolManagerhHashMap.get(threadPoolManagerName);
                if (null == threadPoolManager) {
                    threadPoolManager = new ThreadPoolManager();
                    threadPoolManager.mName = threadPoolManagerName;
                    sThreadPoolManagerhHashMap.put(threadPoolManagerName, threadPoolManager);
                }
            }
        }
        return threadPoolManager;
    }

3.mWorkThreadPool是线程池ThreadPoolExecutor,每一个ThreadPoolManager维护着一个ThreadPoolExecutor,ThreadPoolManager执行Runnable时,都调用ThreadPoolExecutor执行Runnable,同时提供Runnable执行时的监听。

public static interface ITaskExecuteListener {
        public void beforeExecute(Thread thread, Runnable task);
        public void afterExecute(Runnable task, Throwable throwable);
    }
 if (listener == null) {
            mWorkThreadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
                    unit, queue, mRejectedExecutionHandler);
        } else {
            mWorkThreadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
                    unit, queue, mRejectedExecutionHandler) {
                @Override
                protected void beforeExecute(Thread t, Runnable r) {
                    listener.beforeExecute(t, r);
                }

                @Override
                protected void afterExecute(Runnable r, Throwable t) {
                    listener.afterExecute(r, t);
                }
            };
        }

接下来是创建抽象的线程管理类,以静态代理的方式来代理ThreadPoolManager

public abstract class AbstractThreadExecutor {

    protected ThreadPoolManager mManager;

    private byte[] mLock = new byte[0];

    protected abstract ThreadPoolManager initThreadPoolManager();

    protected ThreadPoolManager.ITaskExecuteListener getTaskExecuteListener() {
        return new ThreadPoolManager.ITaskExecuteListener() {

            @Override
            public void beforeExecute(Thread thread, Runnable task) {

            }

            @Override
            public void afterExecute(Runnable task, Throwable throwable) {

            }

        };
    }
    /**
     * 执行一个异步任务
     * @param task 需要执行的任务
     */
    public void execute(Runnable task) {
        if (mManager == null) {
            synchronized (mLock) {
                if (mManager == null) {
                    mManager = initThreadPoolManager();
                }
            }
        }
        mManager.execute(task);
    }

    /**
     * 取消指定的任务
     * @param task
     */
    public void cancel(final Runnable task) {
        if (mManager != null) {
            mManager.cancel(task);
        }
    }

    /**
     * 销毁对象
     */
    public void destroy() {
        if (mManager != null) {
            ThreadPoolManager.destroy(mManager.getManagerName());
            mManager = null;
        }
    }

}

可以看出静态代理的逻辑,AbstractThreadExecutor 中执行,取消Runnable的方法通过ThreadPoolManager来完成,而ThreadPoolManager的初始化交给子类去实现,保证拓展性。

AbstractThreadExecutor 的实现ThreadExecutorProxy

public class ThreadExecutorProxy {

    private final static String POOL_NAME = "thread_pool";
    private final static int DEFAULT_CORE_POOL_SIZE = 1;
    private final static int DEFAULT_MAX_POOL_SIZE = 6;
    private final static int KEEP_ALIVE_TIME = 60;
    private final static String ASYNC_THREAD_NAME = "single-async-thread";
    private static ThreadExecutor sExecutor;
    private static boolean sIsInit;
    private static int sCorePoolSize = DEFAULT_CORE_POOL_SIZE;

    private static HandlerThread sSingleAsyncThread;

    private static Handler sSingleAsyncHandler;

    private static Handler sMainHandler;

    private static MessageQueue sMsgQueue;

    public static void init() {
        if (sIsInit) {
            return;
        }
        sCorePoolSize = CpuManager.getCpuCoreNums() - 1;
        if (sCorePoolSize < DEFAULT_CORE_POOL_SIZE) {
            sCorePoolSize = DEFAULT_CORE_POOL_SIZE;
        }
        if (sCorePoolSize > DEFAULT_MAX_POOL_SIZE) {
            sCorePoolSize = DEFAULT_MAX_POOL_SIZE;
        }
        sExecutor = new ThreadExecutor();

        sSingleAsyncThread = new HandlerThread(ASYNC_THREAD_NAME);
        sSingleAsyncThread.start();
        sSingleAsyncHandler = new Handler(sSingleAsyncThread.getLooper());

        sMainHandler = new Handler(Looper.getMainLooper());

        sMsgQueue = Looper.myQueue();
        sIsInit = true;
    }

    /**
     * 提交异步任务到线程池中执行
     *
     * @param task 需要执行的任务
     */
    public static void execute(Runnable task) {
        sExecutor.execute(task);
    }

    /**
     * 取消指定的任务
     *
     * @param task
     */
    public static void cancel(final Runnable task) {
        sExecutor.cancel(task);
        sSingleAsyncHandler.removeCallbacks(task);
        sMainHandler.removeCallbacks(task);
    }

    /**
     * 销毁对象
     */
    public static void destroy() {
        sExecutor.destroy();
        sSingleAsyncHandler.removeCallbacksAndMessages(null);
        sMainHandler.removeCallbacksAndMessages(null);
    }

    /**
     * 提交一个Runable到异步线程队列,该异步线程为单队列
     *
     * @param r
     */
    public static void runOnAsyncThread(Runnable r) {
        sSingleAsyncHandler.post(r);
    }

    /**
     * 提交一个Runable到异步线程队列,该异步线程为单队列
     *
     * @param r
     * @param delay
     */
    public static void runOnAsyncThread(Runnable r, long delay) {
        sSingleAsyncHandler.postDelayed(r, delay);
    }

    /**
     * 提交一个Runable到主线程队列
     *
     * @param r
     */
    public static void runOnMainThread(Runnable r) {
        sMainHandler.post(r);
    }

    /**
     * 提交一个Runable到主线程队列
     *
     * @param r
     * @param delay
     */
    public static void runOnMainThread(Runnable r, long delay) {
        sMainHandler.postDelayed(r, delay);
    }

    /**
     * 提交一个Runnable到主线程空闲时执行
     *
     * @param r
     */
    public static void runOnIdleTime(final Runnable r) {
        IdleHandler handler = new IdleHandler() {

            @Override
            public boolean queueIdle() {
                r.run();
                return false;
            }
        };
        sMsgQueue.addIdleHandler(handler);
    }

    private static class ThreadExecutor extends AbstractThreadExecutor {

        private ThreadExecutor() {

        }

        @Override
        protected ThreadPoolManager initThreadPoolManager() {
            ThreadPoolManager manager = ThreadPoolManager.buildInstance(POOL_NAME, sCorePoolSize,
                    DEFAULT_MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, false,
                    getTaskExecuteListener());
            return manager;
        }
    }
}

可以看到通过ThreadExecutorProxy可以任意的在子线程和主线程中进行切换来执行Runnable,而线程池的管理,线程的执行都封装在ThreadPoolManager中,而调用者根本不需要关心。

动态代理

静态代理是死的,不会在运行时动态创建,相当于在编译期,就给被代理的对象生成了一个不可动态改变的代理类。

静态代理中,被代理的对象很固定,我们只需要去代理一个类或者若干固定的类,数量不是太多的时候,可以使用,而且其实效果比动态代理更好,因为动态代理就是在运行期间动态生成代理类,所以需要消耗的时间会更久一点。

下面介绍下动态代理,动态代理是JDK自带的功能,它需要你去实现一个InvocationHandler接口,并且调用Proxy的静态方法去产生代理类,还是以前面代购的例子。

public class DynamicProxy implements InvocationHandler{

    private final Object mTarget;//被代理对象的引用

    public DynamicProxy(Object target) {
        mTarget = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用被代理对象的方法

        return method.invoke(mTarget,args);
    }
}
public class Client {
    public static void main(String[] args) {
        //构造被代理类小明
        IShop xiaoMing = new XiaoMing();
       //构造一个动态代理
        DynamicProxy dynamicProxy = new DynamicProxy(xiaoMing);
        //获取被代理类小明的classLoader
        ClassLoader classLoader = xiaoMing.getClass().getClassLoader();
        //动态构建代购的人
        IShop proxyBuyer = (IShop) Proxy.newProxyInstance(classLoader,new Class[]{IShop.class},dynamicProxy);
        //进行代购
        proxyBuyer.buy();
    }
}

动态代理在项目中的应用

动态代理在项目中的使用,那就是在插件化中通过代理的方式来进行hook,这里我就介绍一下如何通过动态代理去hook service.首先看一下ServiceManager 的 getService(String name) 方法

public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;
    private static HashMap sCache = new HashMap();

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

    /**
     * Returns a reference to a service with the given name.
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or null if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    public static void addService(String name, IBinder service) {
    ...
    }
    ....
}

getService 内部首先会去 sCache 这个 map 中根据 Service 的名字获取这个 Service 的 IBinder 对象,如果获取到为空,则会通过 ServiceManagerNative 通过跨进程通信获取这个 Service 的 IBinder 对象,这里我们以 sCache 这个 map 为切入点,反射该对象,对其进行修改,由于系统的 Android.os.ServiceManager 类是 @hide 的,所以只能使用反射,所以这里我们需要自己写一个ServiceManagerProxy类,然后其getService方法是通过反射调用系统ServiceManager的getService方法

public class ServiceManagerProxy {
    private static Method sGetServiceMethod;
    private static Map sCacheService;
    private static Class sServiceManagerClass;

    static {
        try {
            sServiceManagerClass = Class.forName("android.os.ServiceManagerProxy");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static IBinder getService(String serviceName) {
        if (sServiceManagerClass == null) {
            return null;
        }

        if (sGetServiceMethod == null) {
            try {
                sGetServiceMethod = sServiceManagerClass.getDeclaredMethod("getService", String.class);
                sGetServiceMethod.setAccessible(true);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }

        if (sGetServiceMethod != null) {
            try {
                return (IBinder) sGetServiceMethod.invoke(null, serviceName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    public static void setService(String serviceName, IBinder service) {
        if (sServiceManagerClass == null) {
            return;
        }

        if (sCacheService == null) {
            try {
                Field sCache = sServiceManagerClass.getDeclaredField("sCache");
                sCache.setAccessible(true);
                sCacheService = (Map) sCache.get(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        sCacheService.remove(serviceName);
        sCacheService.put(serviceName, service);
    }
}

而ServiceManagerProxy的setService方法则是通过反射获取ServiceManager中的sCache ,移除系统 Service,然后将我们自己改造过的 Service put 进去,这样就能实现当调用 ServiceManager 的 getService(String name) 方法的时候,返回的是我们改造过的 Service 而不是系统原本的 Service。

接下来以hook ClipboardService 为例

public class ClipboardHook {

    private static final String TAG = ClipboardHook.class.getSimpleName();

    public static void hookService(Context context) {
        IBinder clipboardService = ServiceManagerProxy.getService(Context.CLIPBOARD_SERVICE);
        String IClipboard = "android.content.IClipboard";

        if (clipboardService != null) {
            //生成动态代理类hookClipboardService,其方法都会调用ServiceHook的invoke方法
            IBinder hookClipboardService =
                    (IBinder) Proxy.newProxyInstance(IBinder.class.getClassLoader(),
                            new Class[]{IBinder.class},
                            new ServiceHook(clipboardService, IClipboard, true, new ClipboardHookHandler()));
            ServiceManagerProxy.setService(Context.CLIPBOARD_SERVICE, hookClipboardService);
        } else {
            Log.e(TAG, "ClipboardService hook failed!");
        }
    }

    public static class ClipboardHookHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            String methodName = method.getName();
            int argsLength = args.length;
            //每次从本应用复制的文本,后面都加上haha
            if ("setPrimaryClip".equals(methodName)) {
                if (argsLength >= 2 && args[0] instanceof ClipData) {
                    ClipData data = (ClipData) args[0];
                    String text = data.getItemAt(0).getText().toString();
                    text += "haha";
                    args[0] = ClipData.newPlainText(data.getDescription().getLabel(), text);
                }
            }
            return method.invoke(proxy, args);
        }
    }
}

ClipboardHook 中做了以下事情:
1.通过我们之前创建的ServiceManagerProxy
,反射获取clipboard的IBinder
2.创建一个ClipboardHookHandler实现InvocationHandler,并在其invoke方法中,修改”setPrimaryClip”方法的逻辑
3.将clipboard的IBinder和ClipboardHookHandler传入ServiceHook中,并利用其创建一个动态代理,然后调用ServiceManagerProxy的setService方法替换掉真正ServiceManager中的clipboard

经过以上的几步后,当客户端调用ClipboardService的方法的时候,就会调用到ServiceHook中的invoke方法,所以接下来就是ServiceHook中的逻辑

public class ServiceHook implements InvocationHandler {
    private static final String TAG = "yyy";
    private IBinder mBase;
    private Class mStub;
    private Class mInterface;
    private InvocationHandler mInvocationHandler;

    public ServiceHook(IBinder base,  String iInterfaceName,boolean isStub, InvocationHandler invocationHandler) {
        mBase = base;
        mInvocationHandler = invocationHandler;

        try {
            mInterface = Class.forName(iInterfaceName);
            mStub = Class.forName(String.format("%s%s", iInterfaceName, isStub ? "$Stub" : ""));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("queryLocalInterface".equals(method.getName())) {
            //mInterface就是"android.content.IClipboard"
            //mBase是clipboardService
            //mInvocationHandler是ClipboardHookHandler
            return Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[]{mInterface},
                    new HookServiceHandler(mBase, mStub, mInvocationHandler));
        }

        return method.invoke(mBase, args);

    }

    private static class HookServiceHandler implements InvocationHandler {
        private Object mBase;
        private InvocationHandler mInvocationHandler;

可以看到,ServiceHook 的 invoke 函数中,只有当函数为 queryLocalInterface 方法的时候返回一个 HookServiceHandler的对象,其他的情况直接调用 method.invoke 系统的 ClipboardService 功能,只处理 queryLocalInterface 方法的原因是,asInterface 方法最终会调用到 queryLocalInterface 方法,queryLocalInterface 方法最后的返回结果会作为 asInterface 的结果而返回给 Service 的调用方,所以 queryLocalInterface 方法的最后返回的对象是会被外部直接调用的,所以第一次调用到 queryLocalInterface 函数之后,后续的所有调用都到了 HookHandler 对象中,动态生成的对象中只需要有 IBinder 的 queryLocalInterface 方法即可,而不需要 IClipboard 接口的其他方法;所以queryLocalInterface 方法会返回通过HookServiceHandler生成的代理类,接下来就是HookServiceHandler的逻辑了

 private static class HookServiceHandler implements InvocationHandler {
        private Object mBase;
        private InvocationHandler mInvocationHandler;

        public HookServiceHandler(IBinder base, Class stubClass,
                                  InvocationHandler InvocationHandler) {
            mInvocationHandler = InvocationHandler;

            try {
                Method asInterface = stubClass.getDeclaredMethod("asInterface", IBinder.class);
                this.mBase = asInterface.invoke(null, base);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (mInvocationHandler != null) {
                //调用ClipboardHookHandler的invoke方法
                return mInvocationHandler.invoke(mBase, method, args);
            }
            return method.invoke(mBase, args);
        }
    }

在HookServiceHandler 的构造函数中,反射调用IClipboard$Stub的 asInterface 的方法,通过反射 asInterface 方法然后将 IClipboard的IBinder 对象变成 IInterface 对象,这是因为通过 ServiceManager.getService 方法获取的 IBinder 对象不能直接调用,必须要通过 asInterface 方法转成对应的 IInterface 对象才可以使用,所以 HookServiceHandler 中的mBase 对象其实是一个 IInterface 对象

接下来就是HookServiceHandler的invoke方法会调用前面ClipboardHookHandler的invoke方法,从而对IClipboard的setPrimaryClip达到了hook的作用,可以看到hook 的过程中完美使用了动态代理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值