深入理解IActivityController

一、研究背景

最近在学习别人代码,在代码中使用IActivityController.aidl统计设备中所有app的状态,包括activityStarting、activityResuming、appCrashed、appEarlyNotResponding、appNotResponding、systemNotResponding。后面我们会对这些方法单独介绍。发现这个写法很神奇,故想学习一下,这里对这个方法进行源码级分析,深入理解。

二、IActivityController.aidl简介

IActivityController.aidl是系统自带的aidl,在Am的内部类MyActivityController有实现这个aidl接口,主要用于app状态监听控制。对于应用开发者来说,此接口为给我们提供了各种可能性,比如统计每个app启动次数,crash次数等。这里我们先看下他的方法:

  • activityStarting:当系统正在启动一个activity时会触发,当返回true,表示允许启动。当返回状态noraml/false分别表示停止/拒绝启动activity
  • activityResuming:当系统正在返回一个activity时会触发,当返回true,表示允许返回。当返回状态noraml/false分别表示停止/拒绝返回activity
  • appCrashed:当一个应用进程已经崩溃会触发,当返回true时,表示可以重启,当返回false时,表示立即杀死它(进程)。
  • appEarlyNotResponding:当一鉴定为ANR时就很早触发;
  • appNotResponding:当一个应用进程出现ANR时就会触发,当返回0时,表示会弹出应用无响应的dialog,如果返回1时,表示继续等待,如果返回-1时,表示立即杀死进程。
  • systemNotResponding:当系统看门狗已经监测到系统似乎挂起就会触发,如果放回1时,表示继续等待,如果返回-1时,就让系统进行正常的自杀(这里的正常自杀,我的理解是系统自己主动自杀,该保存的数据先保存等然后就自杀,并不是因为其他原因导致的自杀)

三、系统内部IActivityController.class如何编译生成

我们应用开发知道aidl文件只有生成java或者class才可以给其他应用调用,由于系统在编译时就已经将IActivityController.aidl编译成IActivityController.class并打包到framework.jar中。先看下源码中如何将IActivityController.aidl编译的。
在源码的framworks/base/Android.mk中:

LOCAL_SRC_FILES += \
    core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
    core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
    core/java/android/accounts/IAccountManager.aidl \
    core/java/android/accounts/IAccountManagerResponse.aidl \
    core/java/android/accounts/IAccountAuthenticator.aidl \
    core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
    core/java/android/app/IActivityContainer.aidl \
    core/java/android/app/IActivityContainerCallback.aidl \
    core/java/android/app/IActivityController.aidl \
    core/java/android/app/IActivityPendingResult.aidl \
    core/java/android/app/IAlarmManager.aidl \
    core/java/android/app/IAppTask.aidl \
    core/java/android/app/ITaskStackListener.aidl \
    ....................................................\



# FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)

LOCAL_INTERMEDIATE_SOURCES := \
            $(framework_res_source_path)/android/R.java \
            $(framework_res_source_path)/android/Manifest.java \
            $(framework_res_source_path)/com/android/internal/R.java

LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-libart conscrypt okhttp core-junit bouncycastle ext

LOCAL_MODULE := framework

LOCAL_DX_FLAGS := --core-library --multi-dex

LOCAL_RMTYPEDEFS := true

include $(BUILD_JAVA_LIBRARY)
framework_module := $(LOCAL_INSTALLED_MODULE)

# Make sure that R.java and Manifest.java are built before we build
# the source for this library.
framework_res_R_stamp := \
    $(call intermediates-dir-for,APPS,framework-res,,COMMON)/src/R.stamp
$(full_classes_compiled_jar): $(framework_res_R_stamp)

$(framework_module): | $(dir $(framework_module))framework-res.apk

framework_built := $(call java-lib-deps,framework)

文件中我们可以看到

core/java/android/app/IActivityController.aidl \

IActivityController.aidl已经被添加到LOCAL_SRC_FILES,接下来就被打包jar。

LOCAL_MODULE := framework

LOCAL_DX_FLAGS := --core-library --multi-dex

LOCAL_RMTYPEDEFS := true

include $(BUILD_JAVA_LIBRARY)
framework_module := $(LOCAL_INSTALLED_MODULE)

这里可以看到最终会被编译到framework.jar中去。

编译后framework.jar我们打开就会发现:


IActivityController.class.png

四、IActivityController源码分析

想要完全理解IActivityController的使用,必须要对源码有所了解,在源码中这四个类对其使用理解尤为重要,这四个类分别是IActivityManager、ActivityManagerProxy、ActivityManagerNative、ActivityManagerService。接下来先看下这四个类分别是做什么的。

  • IActivityManager:主要是提供Activity管理的一些接口
  • ActivityManagerProxy:是ActivityManagerNative的内部类,实现了IActivityManager的接口
  • ActivityManagerNative:其实是实现了IActivityManager.aidl的java文件,这里并不是自动生成的,而是按照aidl生成java格式写的,后面我们比较一下自动生成的java的。其他类通过集成此类就可以获取到响应的binder,然后对activity进行管理操作,我们从上图中也可以看到生成的class文件在framework.jar,也就是说系统级别的应用是可以调用到这个接口。
  • ActivityManagerService:继承了ActivityManagerNative类,通过ActivityManagerNative可以拿到binder。

1. ActivityManagerNative文件对比
先看下我自己实现的aidl文件

package com.tcl.myaidl;
interface IMyAidlInterface{
    void sayHello(String string);
    String getHello();
}

再看下自动生成的java文件

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\MyAndroid\\MyAidlTestDemo\\src\\com\\tcl\\aidl\\IMyAidlInterface.aidl
 */
package com.tcl.aidl;
public interface IMyAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.tcl.aidl.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.tcl.aidl.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.tcl.aidl.IMyAidlInterface interface,
 * generating a proxy if needed.
 */
public static com.tcl.aidl.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.tcl.aidl.IMyAidlInterface))) {
return ((com.tcl.aidl.IMyAidlInterface)iin);
}
return new com.tcl.aidl.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_setHello:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.setHello(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getHello:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getHello();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.tcl.aidl.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;
}
@Override public void setHello(java.lang.String string) 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.writeString(string);
mRemote.transact(Stub.TRANSACTION_setHello, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public java.lang.String getHello() 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);
mRemote.transact(Stub.TRANSACTION_getHello, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void setHello(java.lang.String string) throws android.os.RemoteException;
public java.lang.String getHello() throws android.os.RemoteException;
}

再看下ActivityManagerNative.java文件,这里只贴出一部分对比一下。

/** {@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);
    }


    ....................
    
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
            ..............
        }
    }
    
     public IBinder asBinder() {
        return this;
    }

    class ActivityManagerProxy implements IActivityManager
    {
        public ActivityManagerProxy(IBinder remote)
        {
            mRemote = remote;
        }

        public IBinder asBinder()
        {
            return mRemote;
        }
        ................
        
       private IBinder mRemote;
    }
}

对比后发现,这个ActivityManagerNative.java文件就是IActivityManager.aidl对应的文件,供外部调用的。

2. ActivityManagerNative.java分析

在ActivityManagerNative.java文件中有两个class,分别是ActivityManagerNative和ActivityManagerProxy:

  • ActivityManagerNative类,其主要实现是在service端实现的.
  • ActivityManagerProxy内部类主要是作为service端的一个代理类。

在这两个类中有这几个方法和变量尤为重要,ActivityManagerProxy类内部的==asBinder()== 和对象==mRemote== 、ActivityManagerNative类内部的==onTransact()== 。

我们可以先看下ActivityManagerProxy的==mRemote== 其赋值在这里:

 public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }

外部其他类也可以通过以下方法获取==mRemote== :

 public IBinder asBinder()
    {
        return mRemote;
    }

==mRemote== 其实就是service的一个实体对象,当客户端拿到这个代理类内部的实体对象,就可以调用远程service的方法,主要方法有startActivity等等。

就拿startActivity举个列子,可以看到会调用mRemote发送一个消息START_ACTIVITY_TRANSACTION给service端:

 public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

在service端,有处理这个消息的方法,也就是==onTransact()== 。可以看下具体的如何处理的:

 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;
        }
            
    }

可以看到不同的消息有不同的处理方式,那我们回过头来想想我们主要是要看IActivityController如何调用的。
在==onTransact()== 方法中,我们恰好也看到这样一个消息:

        case SET_ACTIVITY_CONTROLLER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IActivityController watcher = IActivityController.Stub.asInterface(
                    data.readStrongBinder());
            setActivityController(watcher);
            reply.writeNoException();
            return true;
        }

根据我们之前的分析,service端有处理这个信息的地方,相应的ActivityManagerProxy就有发送这个消息的地方:

  public void setActivityController(IActivityController watcher) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
        mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

IActivityController调用的地方找到的,处理的地方也找到了。

五、在ActivityManagerNative类内部有关IActivityController的消息是如何被处理的

回过头我们看下被处理的地方:

  case SET_ACTIVITY_CONTROLLER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IActivityController watcher = IActivityController.Stub.asInterface(
                    data.readStrongBinder());
            setActivityController(watcher);
            reply.writeNoException();
            return true;
        }

我们看到service端会从data里面解析一个Binder,而且会通过IActivityController.Stub.asInterface()的方法,将此data中数据转换成IActivityController的一个Binder,这里也就是参数watcher,其实就是IActivityController的一个代理。

上述代码由将watcher对象作为参数传给setActivityController()方法,我们再追溯setActivityController(),发现其最终调用到ActivityManagerService的setActivityController()方法,也就是说最终使用IActivityController代理的地方是在ActivityManagerService类内部。 我们看下ActivityManagerService的setActivityController()方法源码:

    @Override
    public void setActivityController(IActivityController controller) {
        enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                "setActivityController()");
        synchronized (this) {
            mController = controller;
            Watchdog.getInstance().setActivityController(controller);
        }
    }

在ActivityManagerNative的获取到的对象watcher,最终会在ActivityManagerService类内部赋给mController和调用到Watchdog.getInstance().setActivityController()方法。看下Watchdog.java的源码:

  public void setActivityController(IActivityController controller) {
        synchronized (this) {
            mController = controller;
        }
    }

Watchdog也会将其赋给类内部的变量mController。

结论:在ActivityManagerNative类内部有关IActivityController的消息被处理后,最终会调用到ActivityManagerService和Watchdog。在ActivityManagerService类和Watchdog类内部都有获得一个IActivityController的代理对象

六、在ActivityManagerProxy类内部有关IActivityController的消息是被触发的

在ActivityManagerProxy类内部可以看到这样一个方法:

    public void setActivityController(IActivityController watcher) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
        mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

外部类拿到IActivityManager的代理类对象(也就是ActivityManagerProxy对象)时,通过该对象调用时,会发送一个消息SET_ACTIVITY_CONTROLLER_TRANSACTION给service端。

结论:综合来看,外部类拿到IActivityManager的代理对象,通过其代理对象的setActivityController()方法,会将IActivityControllerd代理对象序列化打包,发送到Binder通信的Service端,Service端接收到这消息,会将解析出IActivityControllerd代理对象,分别将其赋给ActivityManagerService和Watchdog类内部的mController的对象。

七、通过源码分析方式分析StartActivity如何触发IActivityController的activityStarting方法

我们先从Context.StartActivity看起,Context的StartActivity的源码:

    /**
     * Launch a new activity.  You will not receive any information about when
     * the activity exits.
     *
     * <p>Note that if this method is being called from outside of an
     * {@link android.app.Activity} Context, then the Intent must include
     * the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag.  This is because,
     * without being started from an existing Activity, there is no existing
     * task in which to place the new activity and thus it needs to be placed
     * in its own separate task.
     *
     * <p>This method throws {@link ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param intent The description of the activity to start.
     * @param options Additional options for how the Activity should be started.
     * May be null if there are no options.  See {@link android.app.ActivityOptions}
     * for how to build the Bundle supplied here; there are no supported definitions
     * for building it manually.
     *
     * @throws ActivityNotFoundException &nbsp;
     *
     * @see #startActivity(Intent)
     * @see PackageManager#resolveActivity
     */
    public abstract void startActivity(Intent intent, @Nullable Bundle options);

我们可以看到这个方法是个虚方法,必须由子类实现,我们接下来看下子类ContextImpl的StartActivity的实现:


    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity)null, intent, -1, options);
    }

再继续追踪,我们会发现会调用到Instrumentation类的execStartActivity的方法:

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options, UserHandle user) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options, user.getIdentifier());
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

我们可以看到这个方法可以调用到ActivityManagerNative.getDefault().startActivityAsUser()方法。先看下ActivityManagerNative.getDefault()的方法实现:

 /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    
   private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

可以看到ActivityManagerNative.getDefault()得到的是IActivityManager代理对象,由于ActivityManagerNative是个虚类,具体的方法实现是在ActivityManagerService类中,上面我们看到调用到startActivityAsUser(),我们也可以猜到此方法具体实现是在ActivityManagerService类中:


    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, userId, null, null);
    }

继续追踪代码,发现调用的ActivityStackSupervisor类的startActivityMayWait()方法:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        boolean componentSpecified = intent.getComponent() != null;

        // Don't modify the client's object!
        intent = new Intent(intent);

        // Collect information about the target of the Intent.
        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profilerInfo, userId);

        ActivityContainer container = (ActivityContainer)iContainer;
        synchronized (mService) {
            final int realCallingPid = Binder.getCallingPid();
            final int realCallingUid = Binder.getCallingUid();
            int callingPid;
            if (callingUid >= 0) {
                callingPid = -1;
            } else if (caller == null) {
                callingPid = realCallingPid;
                callingUid = realCallingUid;
            } else {
                callingPid = callingUid = -1;
            }

            final ActivityStack stack;
            if (container == null || container.mStack.isOnHomeDisplay()) {
                stack = getFocusedStack();
            } else {
                stack = container.mStack;
            }
            stack.mConfigWillChange = config != null
                    && mService.mConfiguration.diff(config) != 0;
            if (DEBUG_CONFIGURATION) Slog.v(TAG,
                    "Starting activity when config will change = " + stack.mConfigWillChange);

            final long origId = Binder.clearCallingIdentity();
            ...............................................
            ...........................................
            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options,
                    componentSpecified, null, container, inTask);

            Binder.restoreCallingIdentity(origId);

            .........................................
            ....................................

            return res;
        }
    }

上述代码中可以看到调用到startActivityLocked方法,追踪代码需要有点耐心。

 final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
            TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;

       
        ...............................
        .............................

        if (mService.mController != null) {
            try {
                // The Intent we give to the watcher has the extra data
                // stripped off, since it can contain private information.
                Intent watchIntent = intent.cloneFilter();
                abort |= !mService.mController.activityStarting(watchIntent,
                        aInfo.applicationInfo.packageName);
            } catch (RemoteException e) {
                mService.mController = null;
            }
        }

        ...............................
        .............................
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        if (err < 0) {
            // If someone asked to have the keyguard dismissed on the next
            // activity start, but we are not actually doing an activity
            // switch...  just dismiss the keyguard now, because we
            // probably want to see whatever is behind it.
            notifyActivityDrawnForKeyguard();
        }
        return err;
    }

经过千辛万苦终于找到他了,我们发现此段代码中,我们找到了mController。这个变量应该不是很陌生吧,我们再看下是mController是哪个类内部的,我们会发现是ActivityManagerService类内部的变量。

结论:当我们通过外部类拿到IActivityManager的代理对象,通过其代理对象的setActivityController()后,此时ActivityManagerService和Watchdog会给类内部mController变量赋值,当调用Context.startActivity()方法是会调用到mController的activityStarting。此时实现了IActivityController接口的类就会回调此方法

==注意:其他几个方法也是可以同样的方式追踪到,这里就不多介绍了==

八、应用如何使用IActivityController

应用如果实现此接口,必须这个应用是个系统级别的应用,因为这些接口默认是hide。我们具体看下实现步骤:
1.自定义类实现IActivityController.Stub
由于IActivityController.class已经编译生成,并打包在framework.jar,故这里只需要继承IActivityController.Stub这个虚类,并实现其方法,由于其方法都被hide,这里需要手动添加这些方法:

class MyActivityController extends IActivityController.Stub {
        
        public boolean activityResuming(String pkgName) throws RemoteException {
            synchronized (this) {
//              SoftwareManagerLog.show(TAG, "Activity resuming: " + pkgName);
                if (prePackageName.equals(pkgName)) {
                } else {
                    prePackageName = pkgName;
                    // pushAppToHistory(curActivityInfo);
                }
            }
            return true;
        }

        public boolean activityStarting(Intent intent, String pkgName)
                throws RemoteException {
            synchronized (this) {
                ActivityInfo activityinfo = new ActivityInfo();
                activityinfo.setIntent(intent);
                activityinfo.setPackageName(pkgName);
                Log.i(TAG, "** Activity Starting: " + pkgName);
                Message message = new Message();
                message.what = ACTVITY_START;
                message.obj = activityinfo;
                mHandler.sendMessage(message);
            }
            return true;
        }

        public boolean appCrashed(String arg0, int arg1, String arg2,
                String arg3, long arg4, String arg5) throws RemoteException {
            return false;
        }

        public int appEarlyNotResponding(String arg0, int arg1, String arg2)
                throws RemoteException {
            return 0;
        }

        public int appNotResponding(String arg0, int arg1, String arg2)
                throws RemoteException {
            return 0;
        }
        
        public int systemNotResponding(String arg0) 
                throws RemoteException {
            return 0;
        }

    }

2.获取IActivityManager代理对象并调用setActivityController

mIActivityManager = ActivityManagerNative.getDefault();
mIActivityManager.setActivityController(new MyActivityController());

这里MyActivityController类对象就相当于一个回调,当有其他应用启动、崩溃等场景下,就会回调MyActivityController类的方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容