最全面试必备:Android(9,2024年最新安卓ui界面设计尺寸规范

最后

文章所有资料全部已经打包整理好,另外小编手头上整理了大量Android架构师全套学习资料,Android核心高级技术PDF文档+全套高级学习资料+视频+2021 BAT 大厂面试真题解析

资料展示:

image

image

image

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


}

从上面代码可以发现startActivity的最终实现是startActivityForResult,startActivity()第二个参数为-1表示Launcher不需要知道根Activity的启动结果,然后在startActivityForResult中由于此时根Activity还没有创建,故mParent=null,所以我们只需要关注mParent=null的情况。在这种情况中会调用Instrumentation的execStartActivity。这时候也许你就会问这个Instrumentation是什么?为什么要交给她弄呢?其实Instrumentation这个类很重要,重要体现在对Activity生命周期的调用根本离不开她。每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。回归正题,让我们瞧瞧Instrumentation的execStartActivity这个方法。

frameworks/base/core/java/android/app/Instrumentation.java

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {

try {

//获取AMS的代理对象
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException(“Failure from system”, e);
}
return null;
}

在这个方法会调用ActivityManager的getService方法来得到AMS的代理对象,然后调用这个代理对象的

startActivity方法,那么这个代理对象是谁呢?让我们一探究竟

@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}

@UnsupportedAppUsage
private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
//得到activity的service引用,即IBinder类型的AMS引用
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//转换成IActivityManager对象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};

可以发现在Singleton中的create方法中由于b是AMS引用作为服务端处于SystemServer进程中,与当前Launcher进程作为客户端与服务端不在同一个进程,所以am返回的是IActivityManager.Stub的代理对象,此时如果要实现客户端与服务端进程间的通信,只需要在AMS继承了IActivityManager.Stub类并实现了相应的方法,而通过下面的代码可以发现AMS刚好是继承了IActivityManager.Stub类的,这样Launcher进程作为客户端就拥有了服务端AMS的代理对象,然后就可以调用AMS的方法来实现具体功能了,就这样Launcher的工作就交给AMS实现了。

public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

}

二、AMS发送创建应用进程请求

通过上面的分析,我们已经知道现在任务已经交给了AMS,入口是AMS的startActivity。

1. 时序图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 详细过程

2.1 AMS将请求任务转移给Process

首先来看看在AMS中的startActivity方法:

源码:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /validateIncomingUser/);
}

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {

//判断调用者的进程是否隔离
enforceNotIsolatedCaller(“startActivity”);
//检查调用者权限
userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), “startActivityAsUser”);

// TODO: Switch to user app stacks here.
return mActivityStartController.obtainStarter(intent, “startActivityAsUser”)
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();

}

startActivity方法经过多个方法调用会去执行startActivityAsUser方法,在startActivityAsUser方法最后会返回mActivityStartController的一长串链式调用方法,如果AlertDialog的话,应该不难看出这链式方法肯定都是返回一个类型的对象的,我们只需要看看obtainStarter的返回类型就可以知道这个对象是什么类型了。

frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java

ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}

可以发现这个obtainStarter返回的是ActivityStarter类型的,所以链式方法就是对ActivityStarter对象设置了要启动的活动的相关信息,最后再调用ActivityStarter对象execute方法。所以我们下一步所需要看的就是这个execute方法。

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent);
}
} finally {
onExecutionComplete();
}
}

因为在startActivityAsUser的链式方法中我们调用了setMayWait这个方法,所以这里的mRequest.mayWait为true,故会继续调用startActivityMayWait方法。

ActivityStarter#startActivityMayWait

private 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 globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent) {

//根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,
//则会弹出ResolverActivity让用户选择合适的应用。
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);

}

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup) {

mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask, allowPendingRemoteAnimationRegistryLookup);

return getExternalResult(mLastStartActivityResult);
}

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {

return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity);
}

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {

result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);

postStartActivityProcessing(r, result, mTargetStack);

return result;
}

startActivityMayWait方法经过调用多次的startActivity方法后会调用到startActivityUnchecked这个方法,那这个方法是干啥的呢?这个方法会根据启动标志位和Activity启动模式来决定如何启动一个Activity以及是否要调用deliverNewIntent方法通知Activity有一个Intent试图重新启动它。比如我们在一开始将活动设置了FLAG_ACTIVITY_NEW_TASK后将创建一个任务栈,其它的就自行看代码。

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {

if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//创建新的TaskRecord
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
setTaskToCurrentTopOrCreateNewTask();
}

if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {

} else {
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront(“startActivityUnchecked”);
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}

}

然后无论以何种模式启动最终都会调用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法。

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}

}

于是又调用了ActivityStack的resumeTopActivityUncheckedLocked

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

@GuardedBy(“mService”)
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {

try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
}

}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}

emmmm…,看到这估计都懵逼了,几个类跳来跳去也不知道干了些什么,不慌,让我们坚持看下ActivityStackSupervisor.startSpecificActivityLocked,因为这个方法很重要。这个方法将是普通Activity和根Activity启动流程的分岔路口。

ActivityStackSupervisor#startSpecificActivityLocked

void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//获取即将要启动的Activity的所在的应用程序进程
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
//如果应用进程已经存在
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !“android”.equals(r.info.packageName)) {
// Don’t add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn’t make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "

  • r.intent.getComponent().flattenToShortString(), e);
    }

// If a dead object exception was thrown – fall through to
// restart the application.
}
//应用进程还未创建,则通过AMS调用startProcessLocked向Zygote进程发送请求
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
“activity”, r.intent.getComponent(), false, false, true);
}

阅读上面的代码我们可以知道在方法中首先获取到了即将要启动的Activity所在的应用进程,假如是普通的Activity的启动流程的活,这个进程肯定是存在的,所以将执行realStartActivityLocked的方法。但是我们现在讨论的是根Activity的启动流程,由于应用都还未启动,意味着根Activity所在的应用进程还未创建,而mService其实就是AMS,所以这里将调用AMS的startProcessLocked。于是我们又回到了最初的起点AMS。

ActivityManagerService.java

final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid /, keepIfLarge,
null /
ABI override /, null / entryPoint /, null / entryPointArgs /,
null /
crashHandler */);
}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {

final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);

}

@GuardedBy(“this”)
private final boolean startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr, String abiOverride) {
return startProcessLocked(app, hostingType, hostingNameStr,
false /* disableHiddenApiChecks */, abiOverride);
}

private final boolean startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {

int uid = app.uid; //创建应用进程的用户ID
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
checkTime(startTime, “startProcess: getting gids from package manager”);
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DEBUG_TRIAGED_MISSING, app.userId);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}

/*

  • 对用户组进行创建和赋值
    */
    if (ArrayUtils.isEmpty(permGids)) {
    gids = new int[3];
    } else {
    gids = new int[permGids.length + 3];
    System.arraycopy(permGids, 0, gids, 3, permGids.length);
    }
    gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
    gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
    gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));

// Replace any invalid GIDs
if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
}

//这个参数后文会提到
final String entryPoint = “android.app.ActivityThread”;

return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
}
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {

//重点关注
final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
requiredAbi, instructionSet, invokeWith, app.startTime);


}

private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {

if (hostingType.equals(“webview_service”)) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});

} else {

//通过Process.start方法来为应用创建进程
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkTime(startTime, “startProcess: returned from zygote!”);
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}

是不是又惊呆了,好吧,我也惊呆了!反正就是通过调用多个startProcessLocked方法后最终将调用startProcess方法,不过需要重点看一下上面的第四个startProcessLocked,在该方法中有个entryPoint参数为 “android.app.ActivityThread”,这个参数将在后文讲到创建应用进程后启动ActivityThread会用到。然后在startProcess方法里将调用Process.start来发送应用创建进程的请求。这样AMS就将发送请求的事交给了Process

2.2 Process向Zygote进程发送创建应用进程请求

frameworks/base/core/java/android/os/Process.java

public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith,
/useBlastulaPool=/ true, zygoteArgs);
}

public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean useBlastulaPool,
String[] zygoteArgs) {
try {

//重点关注
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith,
/startChildZygote=/false,
useBlastulaPool, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
“Starting VM process through Zygote failed”);
throw new RuntimeException(
“Starting VM process through Zygote failed”, ex);
}
}

从上面可以发现,Process中的start方法的实现是startViaZygote方法,所以我们重点观察下这个方法。

private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
boolean useBlastulaPool,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList argsForZygote = new ArrayList();

// --runtime-args, --setuid=, --setgid=,
//创建字符串列表argsForZygote,并将启动应用进程的启动参数保存在这个列表中
argsForZygote.add(“–runtime-args”);
argsForZygote.add(“–setuid=” + uid);
argsForZygote.add(“–setgid=” + gid);
argsForZygote.add(“–runtime-flags=” + runtimeFlags);
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add(“–mount-external-default”);
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add(“–mount-external-read”);
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add(“–mount-external-write”);
}
argsForZygote.add(“–target-sdk-version=” + targetSdkVersion);


synchronized(mLock) {

//重点关注
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
useBlastulaPool,
argsForZygote);
}
}

在startViaZygote中会创建字符串列表argsForZygote来保存将要创建的应用进程的启动参数,然后最后会调用zygoteSendArgsAndGetResult方法,而在这个方法中第一个参数会调用openZygoteSocketIfNeeded方法,第三个参数就是启动参数列表。所以我们先看看openZygoteSocketIfNeeded这个方法的实现。

private ZygoteState openZygoteSocketIfNeeded(String abi)
throws ZygoteStartFailedEx {

Preconditions.checkState(Thread.holdsLock(mLock), “ZygoteProcess lock not held”);
//64位进程中的
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {

//调用ZygoteState的connect函数与mZygoteSocketAddress建立连接,
//这里mZygoteSocketAddress的值为“zygote”
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mBlastulaPoolSocketAddress);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx(“Error connecting to primary zygote”, ioe);
}

maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}

if (primaryZygoteState.matches(abi)) {

//Socket进行连接成功并匹配abi后会返回ZygoteState类型对象
return primaryZygoteState;
}

// 32位Zygote进程中
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState =
ZygoteState.connect(mZygoteSecondarySocketAddress,
mBlastulaPoolSecondarySocketAddress);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx(“Error connecting to secondary zygote”, ioe);
}

maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
}

if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}

throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

openZygoteSocketIfNeeded这个方法从方法名就可以推测出这个方法的作用,大概就是与Zygote建立Socket连接。而从代码中也证实了这一点,在代码中会根据Zygote进程的位数来建立相应的Socket连接,然后返回ZygoteState类型的对象。既然与Zygote建立好Socket连接后,接下来当然是发送请求啦!所以让我们来看看zygoteSendArgsAndGetResult这个方法中是如何发送请求的!

//将传入的应用进程的启动参数argsForZygote写入到ZygoteState
@GuardedBy(“mLock”)
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, boolean useBlastulaPool, ArrayList args)
throws ZygoteStartFailedEx {
String msgStr = Integer.toString(args.size()) + “\n”

  • String.join(“\n”, args) + “\n”;

// Should there be a timeout on this?
Process.ProcessStartResult result = new Process.ProcessStartResult();

// TODO (chriswailes): Move branch body into separate function.
if (useBlastulaPool && Zygote.BLASTULA_POOL_ENABLED && isValidBlastulaCommand(args)) {
LocalSocket blastulaSessionSocket = null;

try {
blastulaSessionSocket = zygoteState.getBlastulaSessionSocket();

final BufferedWriter blastulaWriter =
new BufferedWriter(
new OutputStreamWriter(blastulaSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
final DataInputStream blastulaReader =
new DataInputStream(blastulaSessionSocket.getInputStream());

blastulaWriter.write(msgStr);
blastulaWriter.flush();

result.pid = blastulaReader.readInt();
// Blastulas can’t be used to spawn processes that need wrappers.
result.usingWrapper = false;

if (result.pid < 0) {
throw new ZygoteStartFailedEx(“Blastula specialization failed”);
}

return result;
} catch (IOException ex) {
// If there was an IOException using the blastula pool we will log the error and
// attempt to start the process through the Zygote.
Log.e(LOG_TAG, "IO Exception while communicating with blastula pool - "

  • ex.toString());
    } finally {
    try {
    blastulaSessionSocket.close();
    } catch (IOException ex) {
    Log.e(LOG_TAG, "Failed to close blastula session socket: " + ex.getMessage());
    }
    }
    }

try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

zygoteWriter.write(msgStr);
zygoteWriter.flush();

// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "

  • ex.toString());
    throw new ZygoteStartFailedEx(ex);
    }

if (result.pid < 0) {
throw new ZygoteStartFailedEx(“fork() failed”);
}

return result;
}

因为在openZygoteSocketIfNeeded中我们已经与Zygote进程建立了Socket连接,所以在这个方法中将传入的应用进程的启动参数argsForZygote写入到ZygoteState。这样AMS就完成了向Zygote进程发送创建应用进程的请求的任务。

三、Zygote进程接受请求并孵化应用进程

写在最后

在技术领域内,没有任何一门课程可以让你学完后一劳永逸,再好的课程也只能是“师傅领进门,修行靠个人”。“学无止境”这句话,在任何技术领域,都不只是良好的习惯,更是程序员和工程师们不被时代淘汰、获得更好机会和发展的必要前提。

如果你觉得自己学习效率低,缺乏正确的指导,可以一起学习交流!

加入我们吧!群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

result;
}

因为在openZygoteSocketIfNeeded中我们已经与Zygote进程建立了Socket连接,所以在这个方法中将传入的应用进程的启动参数argsForZygote写入到ZygoteState。这样AMS就完成了向Zygote进程发送创建应用进程的请求的任务。

三、Zygote进程接受请求并孵化应用进程

写在最后

在技术领域内,没有任何一门课程可以让你学完后一劳永逸,再好的课程也只能是“师傅领进门,修行靠个人”。“学无止境”这句话,在任何技术领域,都不只是良好的习惯,更是程序员和工程师们不被时代淘汰、获得更好机会和发展的必要前提。

如果你觉得自己学习效率低,缺乏正确的指导,可以一起学习交流!

加入我们吧!群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 27
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值