概括
Service是Android的四大组件之一,它是一个没有前台展示页面但可以一直在后台运行的组件.因为Service跟Activity一样都是运行UI线程的既使Service没有前台页面也尽量不要在Service中执行耗时操作,除非在Service中声明子线程.
这篇文章从Service的启动入手进行源码分析讲解此为上篇,下篇将讲述Service的Binder过程.
启动Service
1.对于Service的解析我们需要从 startService(Intent service) 开始
public class ContextWrapper extends Context {
Context mBase;
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
}
2.此处可以看到直接调入到ContextWrapper类中startActivity方法函数中(注意: 我们知道四大组件中由于Activity需要界面绘制所以他继承的是一个带主题的ContextWapper即ContextThemeWapper;而Service是没有页面绘制的所以它继承的是ContextWrapper,此处的调用直接调入到了Service的父类中)
public abstract class Context {
@Nullable
public abstract ComponentName startService(Intent service);
}
3.在ContextWrapper中并没有功能的实现,而直接进入到ContextWrapper的父类Context的startService(Intent service)函数方法中,但是Context是个抽象类没有对其进行实现;这该如何是好!
还记得我们在分析Activity启动过程那篇文章中提到的(Activity初始化中的相关操作都是交由ContextImpl去实现的),即ContextImpl是Context的实现类ContextImpl下继续分析startService(Intent service)方法函数
class ContextImpl extends Context {
@Override
public ComponentName startService(Intent service) {
//若系统进程直接调用,会输出警告级Log日志
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
//检查Service Intent,若无指定Service Intent发送的包名 21API之前会给出警告"此隐式意图不安全" ,21API之后会抛出异常"必须明确意图"
validateServiceIntent(service);
//准备让Intent离开程序进程
service.prepareToLeaveProcess(this);
//通过AMS,startService并返回一个ComponetName类型的值
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
} else if (cn.getPackageName().equals("?")) {
throw new IllegalStateException(
"Not allowed to start service " + service + ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
4.既然我们获取了AMS,并且调用了AMS中的satrtService函数方法,那么我们就去看看它里面的实现:
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
//不允许隔离线程的调用
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
synchronized(this) {
//获取当前进程ID
final int callingPid = Binder.getCallingPid();
//获取分配给进程的Linux UID
final int callingUid = Binder.getCallingUid();
//重置当前线程的IPC标识
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
//AMS向下继续调用,并将上面获取到的ID和标识传入进去
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
5. AMS在startSevice方法中并没有实现功能,而是获取了一些参数,继续向下调用
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
...
//对服务进行检索
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
//判断服务检索检索记录是否为Null
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
}
ServiceRecord r = res.record;
final ServiceMap smap = getServiceMapLocked(r.userId);
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
6. 上面这段段代码好大一坨,然而无关键的实现还得继续前行 startServiceInnerLocked(smap, service, r, callerFg, addToStarting)
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
return r.name
}
7.继续调用进入bringUpServiceLocked方法函数
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
//发现一个方法函数,这个名在起的好真切啊"真实开启服务锁",但愿是最后了吧!
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
}
}
8.看看 realStartServiceLocked方法函数它的实现吧!
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
boolean created = false;
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//终于找到正主了,正式进入ApplicationThread中创建Service <1>创建启动
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
//Servie绑定过程
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
...
sendServiceArgsLocked(r, execInFg, true); // 调取Service的onStrart方法
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (from start): " + r);
stopServiceLocked(r); //
}
}
}
9. 通过调用 app.thread.scheduleCreateService方法函数 源码来到了ActivityThread内部类ApplicationThread的scheduleCreateService方法函数的位置
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
10.这里发了一个Handler消息,会交由H类的handleMessage做处理
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
11.最终交由 handleCreateService函数实现对Service的启动
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
//获取包信息
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
//通过类加载器,实例化Service
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
//创建一个对应Service的ContextImpl的对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
//设置外部上下文环境
context.setOuterContext(service);
//创建一个application
Application app = packageInfo.makeApplication(false, mInstrumentation);
//初始化Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用Service的onCreate生命周期
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
网友评论