Am.java
1.执行main方法
这里通过mAm去启动相应的类,属于跨进程调用,调用ServiceManager进程中注册的ActivityManagerService服务,
所以我们这里会看到startInstrumentation的最后一个参数是一个userId,这个参数的作用就是检测调用方是否有权限
调用被调用方。
在PendingIntentTest包中,我们添加了AndroidManifest.xml
上面看到targetPackage=”FrameworkTestStub”,所以上面得到的ai就是FrameworkTestStub的ApplicationInfo
1.执行main方法
public static void main(String[] args) {
try {
(new Am()).run(args);
} catch (IllegalArgumentException e) {
showUsage();
System.err.println("Error: " + e.getMessage());
} catch (Exception e) {
e.printStackTrace(System.err);
System.exit(1);
}
}
new一个Am自身的对象去执行run方法。
2.执行run方法
private void run(String[] args) throws Exception {
if (args.length < 1) {
showUsage();
return;
}
//获取IActivityManager接口的对象,通过它调用ActivityManagerService中的方法
mAm = ActivityManagerNative.getDefault();
if (mAm == null) {
System.err.println(NO_SYSTEM_ERROR_CODE);
throw new AndroidException("Can't connect to activity manager; is the system running?");
}
mArgs = args;
String op = args[0];
mNextArg = 1;
if (op.equals("start")) {
runStart();
} else if (op.equals("startservice")) {
runStartService();
} else if (op.equals("force-stop")) {
runForceStop();
} else if (op.equals("kill")) {
runKill();
} else if (op.equals("kill-all")) {
runKillAll();
} else if (op.equals("instrument")) {
runInstrument();
}
......
}
从am的启动指令中看出op等于instrument,所以这里会去启动runInstrument()
3.执行runInstrument()
private void runInstrument() throws Exception {
String profileFile = null;
boolean wait = false;
boolean rawMode = false;
boolean no_window_animation = false;
int userId = UserHandle.USER_CURRENT;
Bundle args = new Bundle();
String argKey = null, argValue = null;
IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
String opt;
//获取instrument后面的参数
while ((opt=nextOption()) != null) {
if (opt.equals("-p")) {
profileFile = nextArgRequired();
} else if (opt.equals("-w")) {
wait = true;
} else if (opt.equals("-r")) {
rawMode = true;
} else if (opt.equals("-e")) {
argKey = nextArgRequired();
argValue = nextArgRequired();
args.putString(argKey, argValue);
} else if (opt.equals("--no_window_animation")
|| opt.equals("--no-window-animation")) {
no_window_animation = true;
} else if (opt.equals("--user")) {
userId = parseUserArg(nextArgRequired());
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
if (userId == UserHandle.USER_ALL) {
System.err.println("Error: Can't start instrumentation with user 'all'");
return;
}
String cnArg = nextArgRequired();//这里拿到的应该PendingIntentTest/Elastos.Droid.Test.CInstrumentationTestRunner
//获取到要启动的类的名称
//会解析成packageName == PendingIntentTest
//className == Elastos.Droid.Test.CInstrumentationTestRunner
ComponentName cn = ComponentName.unflattenFromString(cnArg);
if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
InstrumentationWatcher watcher = null;
if (wait) {
watcher = new InstrumentationWatcher();
watcher.setRawOutput(rawMode);
}
float[] oldAnims = null;
if (no_window_animation) {
oldAnims = wm.getAnimationScales();
wm.setAnimationScale(0, 0.0f);
wm.setAnimationScale(1, 0.0f);
}
//在ActivityManagerService中启动相应的类
//这里就是去启动PendingIntentTest包中的Elastos.Droid.Test.CInstrumentationTestRunner
if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, userId)) {
throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
}
if (watcher != null) {
if (!watcher.waitForFinish()) {
System.out.println("INSTRUMENTATION_ABORTED: System has crashed.");
}
}
if (oldAnims != null) {
wm.setAnimationScales(oldAnims);
}
}
这里通过mAm去启动相应的类,属于跨进程调用,调用ServiceManager进程中注册的ActivityManagerService服务,
所以我们这里会看到startInstrumentation的最后一个参数是一个userId,这个参数的作用就是检测调用方是否有权限
调用被调用方。
4.执行startInstrumentation
public boolean startInstrumentation(ComponentName className,
String profileFile, int flags, Bundle arguments,
IInstrumentationWatcher watcher, int userId) {
enforceNotIsolatedCaller("startInstrumentation");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, true, "startInstrumentation", null);
// Refuse possible leaked file descriptors
if (arguments != null && arguments.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Bundle");
}
synchronized(this) {
InstrumentationInfo ii = null;
ApplicationInfo ai = null;
try {
//获取启动的Instrumentation信息
ii = mContext.getPackageManager().getInstrumentationInfo(
className, STOCK_PM_FLAGS);
//根据要获取到的InstrumentationInfo去得到要启动的ApplicationInfo
ai = AppGlobals.getPackageManager().getApplicationInfo(
ii.targetPackage, STOCK_PM_FLAGS, userId);
} catch (PackageManager.NameNotFoundException e) {
} catch (RemoteException e) {
}
if (ii == null) {
reportStartInstrumentationFailure(watcher, className,
"Unable to find instrumentation info for: " + className);
return false;
}
if (ai == null) {
reportStartInstrumentationFailure(watcher, className,
"Unable to find instrumentation target package: " + ii.targetPackage);
return false;
}
int match = mContext.getPackageManager().checkSignatures(
ii.targetPackage, ii.packageName);
if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
String msg = "Permission Denial: starting instrumentation "
+ className + " from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingPid()
+ " not allowed because package " + ii.packageName
+ " does not have a signature matching the target "
+ ii.targetPackage;
reportStartInstrumentationFailure(watcher, className, msg);
throw new SecurityException(msg);
}
//下面涉及到同一进程不同Service的远程调用,
//所以调用clearCallingIdentity把incoming calling id,
//即把调用方的id重置成当前进程的id(其中包括pid, uid)
//然后返回origin id, 以便执行完后,调用restoreCallingIdentity重新设置回来
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
//这里会先停止前一次启动的进程
forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId);
//执行addAppLocked,启动ai对应的应用
ProcessRecord app = addAppLocked(ai, false);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
app.instrumentationProfileFile = profileFile;
app.instrumentationArguments = arguments;
app.instrumentationWatcher = watcher;
app.instrumentationResultClass = className;
Binder.restoreCallingIdentity(origId);
}
return true;
}
在PendingIntentTest包中,我们添加了AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ActionBarTest"
android:exported="true">
<instrumentation android:name="Elastos.Droid.Test.CInstrumentationTestRunner"
android:targetPackage="FrameworkTestStub"
android:label="Tests for ActionBarTest"/>
</manifest>
上面看到targetPackage=”FrameworkTestStub”,所以上面得到的ai就是FrameworkTestStub的ApplicationInfo
5.执行addAppLocked
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(info.processName, info.uid);
} else {
app = null;
}
if (app == null) {
app = newProcessRecordLocked(null, info, null, isolated);
mProcessNames.put(info.processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
updateLruProcessLocked(app, true);
}
// This package really, really can not be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
info.packageName, false, UserHandle.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ info.packageName + ": " + e);
}
if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
//根据ProcessRecord启动一个进程去运行对应的应用
startProcessLocked(app, "added application", app.processName);
}
return app;
}
6.执行startProcessLocked
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
if (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
"startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
updateCpuStats();
System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
mProcDeaths[0] = 0;
try {
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName);
if (Environment.isExternalStorageEmulated()) {
if (pm.checkPermission(
android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
app.info.packageName) == PERMISSION_GRANTED) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
}
}
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
/*
* Add shared application GID so applications can share some
* resources like shared libraries
*/
if (permGids == null) {
gids = new int[1];
} else {
gids = new int[permGids.length + 1];
System.arraycopy(permGids, 0, gids, 1, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
}
if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
&& mTopComponent != null
&& app.processName.equals(mTopComponent.getPackageName())) {
uid = 0;
}
if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
&& (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
uid = 0;
}
}
int debugFlags = 0;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
// Also turn on CheckJNI for debuggable apps. It's quite
// awkward to turn on otherwise.
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
Zygote.systemInSafeMode == true) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
}
if ("1".equals(SystemProperties.get("debug.assert"))) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);
......
}
通过上面的Process.start去启动一个以第二个参数app.processName命名的进程,并且去执行android.app.ActivityThread
的main方法。
至此,对应的instrumentation的应用就启动了,然后am进程运行到结束。