该类用于具体操作某个Activity的功能,每个Activity内部都有一个该Instrumentation对象的引用。那么该类是如何被初始化的呢?
1,ActivityThread的main方法中创建了ActivityThread对象,然后调用attach方法。在该方法中获取到IActivityManager对象。并且将applicationThread (是个binder)传递到远端的ActivityManger
private void attach(boolean system) {
if (!system) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
}
}
在ActivityManagerNative中getDefault方法调用下方的ServiceManager来获取binder,进行进行间的通讯。
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
// 查询本地是否存在,否则创建新的对象。
static public IActivityManager asInterface(IBinder obj) {
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
调用 ActivityManagerProxy 类的attachApplication方法。 Parcel 进行了跨进程见的数据传递的请求。,根据表示ATTACH_APPLICATION_TRANSACTION来看下传输的目的地。
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
4,在该处进行的数据请求的返回。在第一行,在参数parcel对象中请求enforceInterface方法,enforce(执行)
IActivityManager 类中的
String descriptor = "android.app.IActivityManager";
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);// 标记1
IApplicationThread app = ApplicationThreadNative.asInterface(data.readStrongBinder());// 标记2
if (app != null) {
attachApplication(app); // 标记3
}
reply.writeNoException();
return true;
}
标记1:
调用了native方法,mNativePtr是在obtain方法中进行了初始化
public final void enforceInterface(String interfaceName) {
nativeEnforceInterface(mNativePtr, interfaceName);
}
private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
native方法执行如下
android_os_Parcel.cpp
/frameworks/base/core/jni/android_os_Parcel.cpp
根据传来的地址转换成parcel对象,然后调用了ipc驱动程序。parcel->enforceInterface获取到IPCThreadState传递到parcel.cpp中。
static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const jchar* str = env->GetStringCritical(name, 0);
if (str) {
IPCThreadState* threadState = IPCThreadState::self();
const int32_t oldPolicy = threadState->getStrictModePolicy();
const bool isValid = parcel->enforceInterface(String16(reinterpret_cast<const char16_t*>(str),env->GetStringLength(name)),threadState);
}
}
}
bool Parcel::enforceInterface(const String16& interface,
IPCThreadState* threadState) const
{
int32_t strictPolicy = readInt32();
if (threadState == NULL) {
threadState = IPCThreadState::self();
}
if ((threadState->getLastTransactionBinderFlags() &
IBinder::FLAG_ONEWAY) != 0) {
threadState->setStrictModePolicy(0);
} else {
threadState->setStrictModePolicy(strictPolicy);
}
const String16 str(readString16());
if (str == interface) {
return true;
} else {
return false;
}
}
标记2 在 ActivityManagerService 中 获取到传输过来的binder。即ActivityThread中的ApplicationThread。
标记3 ActivityManagerService 传递到这里来。
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
attachApplicationLocked(thread, callingPid);
}
}
在activityThread中与ActivityManagerService进行通讯,将本类中的ApplicationThread传过去。
调用mainThread 中的 bindApplication
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
return true;
}
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
private void handleBindApplication(AppBindData data) {
if (data.instrumentationName != null) {
InstrumentationInfo ii = null;
try {
ii = appContext.getPackageManager().
getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
throw new RuntimeException(
"Unable to find instrumentation info for: "
+ data.instrumentationName);
}
mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = ii.nativeLibraryDir;
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.splitSourceDirs = ii.splitSourceDirs;
instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
data.instrumentationUiAutomationConnection);
if (mProfiler.profileFile != null && !ii.handleProfiling
&& mProfiler.profileFd == null) {
mProfiler.handlingProfiling = true;
File file = new File(mProfiler.profileFile);
file.getParentFile().mkdirs();
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
} else {
mInstrumentation = new Instrumentation();
}
try {
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}