插件化 学习笔记

插件化需要解决的问题

插件化就是动态加载,包括代码和资源的加载。当加载像Activity这样的代码时还需要解决生命周期的问题。

插件化 Binder机制

Binder从IPC的角度看是一种通信机制,时android的framework层中各种ServiceManager的链接桥梁。ServiceManager与我们APP不在同一个进程,Binder的存在为跨进程通信提供了支撑,我们可以通过AIDL进行跨进程交互。

IPC通讯过程

  • 客户端要链接服务端
  • 服务端会返回一个客户端的对象(代理对象)
  • 客户端使用这个代理对象其中的方法时,系统会先调用服务端的方法,然后将运算的结果返回给客户端(要知道其实并不是用了这个对象的方法,而是去服务端里运算,然后在返回给客户端的)

我们通过创建AIDL的文件来看一下如何与ServiceManager进行交互。

// IMyAidlInterface.aidl
package com.zpw.plugin;

// Declare any non-default types here with import statements
import com.zpw.plugin.bean.TestAIDLBean;

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);

    String getS(in TestAIDLBean s);

    TestAIDLBean getBean(out TestAIDLBean bean);
}
复制代码
//TestAIDLBean.aidl
package com.zpw.plugin.bean;

parcelable TestAIDLBean;
复制代码
//TestAIDLBean.java
package com.zpw.plugin.bean;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by zpw on 2018/6/5.
 */

public class TestAIDLBean implements Parcelable {
    public TestAIDLBean() {
    }

    protected TestAIDLBean(Parcel in) {
    }

    public void readFromParcel(Parcel in){
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<TestAIDLBean> CREATOR = new Creator<TestAIDLBean>() {
        @Override
        public TestAIDLBean createFromParcel(Parcel in) {
            return new TestAIDLBean(in);
        }

        @Override
        public TestAIDLBean[] newArray(int size) {
            return new TestAIDLBean[size];
        }
    };
}
复制代码

对应的目录结构为:

然后编译项目,会生成/build/generated/source/aidl/debug/com.zpw.plugin.IMyAidlInterface文件:

package com.zpw.plugin;
public interface IMyAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.zpw.plugin.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.zpw.plugin.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.zpw.plugin.IMyAidlInterface interface,
 * generating a proxy if needed.
 */
public static com.zpw.plugin.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.zpw.plugin.IMyAidlInterface))) {
return ((com.zpw.plugin.IMyAidlInterface)iin);
}
return new com.zpw.plugin.IMyAidlInterface.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_basicTypes:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_getS:
{
data.enforceInterface(DESCRIPTOR);
com.zpw.plugin.bean.TestAIDLBean _arg0;
if ((0!=data.readInt())) {
_arg0 = com.zpw.plugin.bean.TestAIDLBean.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
java.lang.String _result = this.getS(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getBean:
{
data.enforceInterface(DESCRIPTOR);
com.zpw.plugin.bean.TestAIDLBean _arg0;
_arg0 = new com.zpw.plugin.bean.TestAIDLBean();
com.zpw.plugin.bean.TestAIDLBean _result = this.getBean(_arg0);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.zpw.plugin.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public java.lang.String getS(com.zpw.plugin.bean.TestAIDLBean s) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((s!=null)) {
_data.writeInt(1);
s.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_getS, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public com.zpw.plugin.bean.TestAIDLBean getBean(com.zpw.plugin.bean.TestAIDLBean bean) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.zpw.plugin.bean.TestAIDLBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBean, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.zpw.plugin.bean.TestAIDLBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
if ((0!=_reply.readInt())) {
bean.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getS = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getBean = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
/**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
public java.lang.String getS(com.zpw.plugin.bean.TestAIDLBean s) throws android.os.RemoteException;
public com.zpw.plugin.bean.TestAIDLBean getBean(com.zpw.plugin.bean.TestAIDLBean bean) throws android.os.RemoteException;
}
复制代码
  • 编译时创建的类为IMyAidlInterface接口,继承自android.os.IInterface:
package android.os;

/**
 * Base class for Binder interfaces.  When defining a new interface,
 * you must derive it from IInterface.
 */
public interface IInterface
{
    /**
     * Retrieve the Binder object associated with this interface.
     * You must use this instead of a plain cast, so that proxy objects
     * can return the correct result.
     */
    public IBinder asBinder();
}
复制代码

接口中声明了三个方法:

public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
public java.lang.String getS(com.zpw.plugin.bean.TestAIDLBean s) throws android.os.RemoteException;
public com.zpw.plugin.bean.TestAIDLBean getBean(com.zpw.plugin.bean.TestAIDLBean bean) throws android.os.RemoteException;
复制代码
  • 内部类Stub继承android.os.Binder,并实现了编译时创建的接口com.zpw.plugin.IMyAidlInterface。 首先实现了android.os.IInterface的asBinder()方法:
@Override public android.os.IBinder asBinder()
{
return this;
}
复制代码

构造方法调用了父类的构造方法:

private static final java.lang.String DESCRIPTOR = "com.zpw.plugin.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
复制代码

看看android.os.Binder中实现的方法:

    /**
     * Convenience method for associating a specific interface with the Binder.
     * After calling, queryLocalInterface() will be implemented for you
     * to return the given owner IInterface when the corresponding
     * descriptor is requested.
     */
    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }
复制代码

asInterface方法中判断如果ServiceManager与APP不是一个进程会返回代理类:

/**
 * Cast an IBinder object into an com.zpw.plugin.IMyAidlInterface interface,
 * generating a proxy if needed.
 */
public static com.zpw.plugin.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.zpw.plugin.IMyAidlInterface))) {
return ((com.zpw.plugin.IMyAidlInterface)iin);
}
return new com.zpw.plugin.IMyAidlInterface.Stub.Proxy(obj);
}
复制代码

每个方法都对应一个id,用于在跨进程访问时确定访问的是哪个方法,通过transact方法再调用服务端的onTransact方法:

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_basicTypes:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_getS:
{
data.enforceInterface(DESCRIPTOR);
com.zpw.plugin.bean.TestAIDLBean _arg0;
if ((0!=data.readInt())) {
_arg0 = com.zpw.plugin.bean.TestAIDLBean.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
java.lang.String _result = this.getS(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getBean:
{
data.enforceInterface(DESCRIPTOR);
com.zpw.plugin.bean.TestAIDLBean _arg0;
_arg0 = new com.zpw.plugin.bean.TestAIDLBean();
com.zpw.plugin.bean.TestAIDLBean _result = this.getBean(_arg0);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
复制代码

这里面对应了很多实现Parcelable接口需要实现的方法。需要在对应的Bean中实现。 每个方法对应的id时递增的:

static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getS = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getBean = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
复制代码

生成的代理类将数据包装好传递给远端的Binder的transact()方法处理。然后会在服务端调用到上面实现的onTransact()方法。

private static class Proxy implements com.zpw.plugin.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public java.lang.String getS(com.zpw.plugin.bean.TestAIDLBean s) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((s!=null)) {
_data.writeInt(1);
s.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_getS, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public com.zpw.plugin.bean.TestAIDLBean getBean(com.zpw.plugin.bean.TestAIDLBean bean) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.zpw.plugin.bean.TestAIDLBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBean, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.zpw.plugin.bean.TestAIDLBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
if ((0!=_reply.readInt())) {
bean.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
复制代码

看看APP如何与ServiceManager交互。ActivityManager其实是ActivityManagerService在我们进程中的一个代理包装类,他内部全部使用 ActivityManagerNative.getDefault()去进程操作

    /**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
复制代码

asInterface():

/** {@hide} */
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }
复制代码

onTransact():

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
    case START_ACTIVITY_TRANSACTION:
    {
        data.enforceInterface(IActivityManager.descriptor);
        IBinder b = data.readStrongBinder();
        IApplicationThread app = ApplicationThreadNative.asInterface(b);
        String callingPackage = data.readString();
        Intent intent = Intent.CREATOR.createFromParcel(data);
        String resolvedType = data.readString();
        IBinder resultTo = data.readStrongBinder();
        String resultWho = data.readString();
        int requestCode = data.readInt();
        int startFlags = data.readInt();
        ProfilerInfo profilerInfo = data.readInt() != 0
                ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
        Bundle options = data.readInt() != 0
                ? Bundle.CREATOR.createFromParcel(data) : null;
        int result = startActivity(app, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
        reply.writeNoException();
        reply.writeInt(result);
        return true;
    }
复制代码

虽然叫做ActivityManagerNative,其实他就是我们自己写的aidl里的内部类Stub。

AILD的运行流程

如果是远程的话返回了代理对象,我们看代理对象的方法:

@Override public com.zpw.plugin.bean.TestAIDLBean getBean(com.zpw.plugin.bean.TestAIDLBean bean) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.zpw.plugin.bean.TestAIDLBean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBean, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.zpw.plugin.bean.TestAIDLBean.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
if ((0!=_reply.readInt())) {
bean.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
复制代码

客户端发起请求:

  • 首先创建输出类型data
  • 创建接受类型reply
  • 创建需要的参数
  • 将参数写入data中
  • 发起远程调用,当前线程挂起调用mRemote.transact()方法,这个方法的实现在Binder中,他会调用服务端的onTransact方法,直到有返回结果
  • 从 _result中取回返回结果 _result

服务端接到请求会走到onTransact方法,这个方法运行在服务端的Binder线程池中:

case TRANSACTION_getBean:
{
data.enforceInterface(DESCRIPTOR);
com.zpw.plugin.bean.TestAIDLBean _arg0;
_arg0 = new com.zpw.plugin.bean.TestAIDLBean();
com.zpw.plugin.bean.TestAIDLBean _result = this.getBean(_arg0);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
复制代码
  • 通过id确定访问哪个方法
  • 然后从目标参数data取出需要的参数
  • 然后调用请求的相应方法
  • 将返回值写入reply
  • 返回true,这里需要说一下,如果返回false,代表客户端访问失败,我们实际当中可根据这个特性来做远程的校检,毕竟我们的远程方法并是不想让任何人都可以访问的。 ,通过id确定访问哪个方法,然后从目标参数data取出需要的参数,然后调用相应方法,将返回值写入reply,

插件化如何支持activity

通过反射替换 Instrumentation

Activity 启动过程

startActivity()最终都会调用到startActivityForResult(),然后调用Instrument.execStartActivity()。

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
		//从Launcher启动应用时requestCode为-1代表不需要返回结果
        if (mParent == null) {
			//mToken: 数据类型为IBinder.
			//通过mMainThread.getApplicationThread()方法获取数据类型为ApplicationThread.
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
        }
        ...
    }
复制代码

再由ActivityManagerNative.startActivity() 通过 IPC AMS所在进程,ActivityManagerService.startActivity()。

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {//启动应用的Activity的路线
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
			//ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, //当前应用的ApplicationThread对象mAppThread;
							   who.getBasePackageName(), //调用当前ContextImpl.getBasePackageName(),获取当前Activity所在包名;
							   intent,//启动Activity时,传递过来的参数;
							   intent.resolveTypeIfNeeded(who.getContentResolver()),//调用intent.resolveTypeIfNeeded而获取;
							   token, //当前Activity.mToken
							   target != null ? target.mEmbeddedID : null,//当前Activity.mEmbeddedID
                               requestCode, //-1;
							   0, 
							   null, 
							   options//null;
							  );//这里实际会调用到ActivityManagerService类的startActivity方法
			//检查activity是否启动成功
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
复制代码

最后 ActivityStackSupervisor.realStartActivityLocked(),权限以及安全检查mService.checkPermission。Activity如果不注册就会在这个检查时返回一个没有注册的错误,最后回到应用进程的时候抛出这个没注册的异常。

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            ...
            //开始执行创建Activity的流程
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
            ...    
            }
复制代码

安全校验完成以后,会调用ApplicationThread.scheduleLaunchActivity()。

case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
复制代码

handleLaunchActivity()又调用了performLaunchActivity(r, customIntent);

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    //通过反射实例化Activity
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    ...
}
复制代码

在这里创建了Activity,所以可以判断这边适合作为hook点。

替换Activity加载过程

通过替换掉Instrumentation类来加载我们插件中的Activity。

// 先获取到当前的ActivityThread对象
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object currentActivityThread = currentActivityThreadMethod.invoke(null);

// 拿到原始的 mInstrumentation字段
Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
mInstrumentationField.setAccessible(true);
Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);

//如果没有注入过,就执行替换
if (!(mInstrumentation instanceof PluginInstrumentation)) {
    PluginInstrumentation pluginInstrumentation = new PluginInstrumentation(mInstrumentation);
    mInstrumentationField.set(currentActivityThread, pluginInstrumentation);
}
复制代码

而在Instrumentation中,有一个方法叫newActivity() 这个方法就是实际创建Activity的方法,它的返回值就是我们应用中实际使用的 activity。 我们就可以在这里,判断到如果即将加载的 className 是一个插件中的Activity,那么就通过 ClassLoader.load(className).newInstance(); 创建插件 Activity 并返回来替换掉原本系统要创建的 Activity 了。

@Override
public Activity newActivity(ClassLoader cl, String className, Intent intent)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    if (intent != null) {
        isPlugin = intent.getBooleanExtra(HJPlugin.FLAG_ACTIVITY_FROM_PLUGIN, false);
    }
    if (isPlugin && intent != null) {
        className = intent.getStringExtra(HJPlugin.FLAG_ACTIVITY_CLASS_NAME);
    } else {
        isPlugin = HJPlugin.getInstance().getPluginAtySet().contains(className);
    }
    return super.newActivity(cl, className, intent);
}
复制代码

### 通过java动态代理Ibinder中的ActivityManager,通过反射设置Handler的mCallback,预埋Activity,使用Activity代理

Class<?> ActivityManagerNativeClss = Class.forName("android.app.ActivityManagerNative");
            Field defaultFiled = ActivityManagerNativeClss.getDeclaredField("gDefault");
            defaultFiled.setAccessible(true);
            Object defaultValue = defaultFiled.get(null);
            //反射SingleTon
            Class<?> SingletonClass = Class.forName("android.util.Singleton");
            Field mInstance = SingletonClass.getDeclaredField("mInstance");
            mInstance.setAccessible(true);
            //到这里已经拿到ActivityManager对象
            Object iActivityManagerObject = mInstance.get(defaultValue);


            //开始动态代理,用代理对象替换掉真实的ActivityManager,瞒天过海
            Class<?> IActivityManagerIntercept = Class.forName("android.app.IActivityManager");

            AmsInvocationHandler handler = new AmsInvocationHandler(iActivityManagerObject);

            Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{IActivityManagerIntercept}, handler);

            //现在替换掉这个对象
            mInstance.set(defaultValue, proxy);
复制代码
private class AmsInvocationHandler implements InvocationHandler {

        private Object iActivityManagerObject;

        private AmsInvocationHandler(Object iActivityManagerObject) {
            this.iActivityManagerObject = iActivityManagerObject;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            Log.i("HookUtil", method.getName());
            //我要在这里搞点事情
            if ("startActivity".contains(method.getName())) {
                Log.e("HookUtil", "Activity已经开始启动");

                //替换Intent 先找到原始的intent,然后直接伪造一个Intent 给AMS
                Intent intent = null;
                int index = 0;
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof Intent) {
                        //说明找到了startActivity的Intent参数
                        intent = (Intent) args[i];
                        //这个意图是不能被启动的,因为Acitivity没有在清单文件中注册
                        index = i;
                    }
                }

                Intent proxyIntent = new Intent();
                ComponentName componentName = new ComponentName(context, proxyActivity);
                proxyIntent.setComponent(componentName);
                proxyIntent.putExtra(DLConstants.EXTRA_CLASS, intent.getStringExtra(DLConstants.EXTRA_CLASS));
                proxyIntent.putExtra(DLConstants.EXTRA_PACKAGE, intent.getStringExtra(DLConstants.EXTRA_PACKAGE));

                proxyIntent.putExtra("oldIntent", intent);
                args[index] = proxyIntent;
            }

            return method.invoke(iActivityManagerObject, args);
        }
    }
复制代码

给ActivityThread中的H设置mCallback。你就可以拦截message拿到其中的msg.obj,然后修改里面的值。

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
复制代码

这段代码说明mCallback的执行在handleMessage之前,那么就可以给Handler设置mCallback来实现拦截消息的效果。

try {
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Method currentActivityThread = activityThreadClass.getDeclaredMethod("currentActivityThread");
            currentActivityThread.setAccessible(true);
            //获取主线程对象
            Object activityThread = currentActivityThread.invoke(null);

            Field mH = activityThreadClass.getDeclaredField("mH");
            mH.setAccessible(true);
            Handler handler = (Handler) mH.get(activityThread);
            Field mActivityThreadHandler = Handler.class.getField("mCallback");
            mActivityThreadHandler.setAccessible(true);
            //设置自己实现的CallBack
            mActivityThreadHandler.set(handler, new ActivityThreadHandlerCallback(handler));

        } catch (Exception e) {
            e.printStackTrace();
        }
复制代码
    class ActivityThreadHandlerCallback implements Handler.Callback {
        @Override
    public boolean handleMessage(Message msg) {
        //代表ActivityThread mH中的launch_activity
        if(msg.what == 100){
            handleLaunchActivity(msg);
        }
        handler.handleMessage(msg);
        return true;
    }

    private void handleLaunchActivity(Message msg) {
        //ActivityClientRecord
        Object obj = msg.obj;
        try {
            Field intentField  = obj.getClass().getDeclaredField("intent");
            intentField .setAccessible(true);
            Intent proxyInent  = (Intent) intentField.get(obj);
            Intent realIntent = proxyInent.getParcelableExtra("oldIntent");
            if (realIntent != null) {
                proxyInent.setComponent(realIntent.getComponent());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
    }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值