插件化需要解决的问题
插件化就是动态加载,包括代码和资源的加载。当加载像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];
}
};
}
复制代码
对应的目录结构为:
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();
}
}
}
复制代码