首先,Sevice的工作过程分两种:Service启动过程
和Service绑定过程
下面是用法:
1.用stratService()启动一个Service
Intent intentService = new Intent(this, MyService.class);
startService(intentService);
2.用bindService()绑定一个Service
Intent intentService = new Intent(this,MyService.calss);
bindService(intentServcie,mSeviceConnection,BIND_AUTOCREATE);
这里有3个参数:第一个是Intent类型,第二个是ServiceConnection类型,第三个是int类型的一个flag。
然后,我们开始分析一下Sevice的两种工作状态的具体过程。
一、Service启动过程
Service的启动过程是从ContextWrapper的startService开始,如下所示:
public ComponentName startService(Intent intent){
return mBase.startService(service);
}
mBase的类型是ContextImpl
ContextImpl是一个很重要的数据结构,它是Context的具体实现,而Context是abstract类型。ContextImpl上下文API的通用实现,它提供了基础用于活动和其他应用程序组件的上下文对象。它在Activity启动过程中,通过Activity的attach方法来和Activity建立关联,并在attach方法中完成Window的创建并建立自己和Window的关联,这样当Window接受到外部输入事件后就可以将事件传递给Activity。
它是在activity启动的时候,有一个performLaunchActivity方法,在这个方法中被创建出来的。
从ContentWrapper的实现可以看出,其大部分的操作是通过mBase来实现的,在设计模式中是一种典型的桥接模式,下面继续看ContextImpl的startService方法:
//这个是上面方法接着调用的方法startServiceConmmon()
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
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();
}
}
在ContextImple中,startService方法会调用startServiceCommon方法。StartServiceCommon方法中有一句ComponentName cn = ActivityManager.getService().startService(...);
书上原是由AMS对象调用,但是由于AMN要弃用了所以这里不一样了。
———-AMS(ActivityManagerService)和AMN(ActivtyManagerNative)———–
AMN:我在《Android艺术开发探索》书上看时觉得AMN还很重要就看了一下,但这本书的版本是2015年的,现在AMN准备弃用了,可以在as上用这个搜索框搜索ServiceManagerNative,然后如下所示:
AMS:具体看图吧:
继续上面ActivityManager.getService()是获取一个单例AMS对象。原书上是由AMN.getDefault()方法获取的,现在也改了。
AMS对象调用startService()方法,用来启动服务,是一个远程的调用过程。实现如下:
@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) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
service这个对象来完成Service后续的启动过程。
mService对象的类型是ActiveServices,ActiveServices是一个辅助AMS进行Servcie管理的类,包括Service的启动、绑定、停止等。
其中,mServcie调startServiceLocked方法(好长),这个方法尾部会调用startServiceInnnerLocked方法,startServcieInnerLocked的实现如下:
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
if (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStartsLocked();
}
} else if (callerFg || r.fgRequired) {
smap.ensureNotStartingBackgroundLocked(r);
}
return r.name;
}
在上述代码中,ServiceRecord描述的是一个Servcie记录,ServiceRecord一直贯穿整个Service的启动过程。startServiceInnerLocked方法并没有完成具体的启动工作,而是把后续的工作交给了bringUpServiceLocked方法来处理,在bringUpServiceLocked方法中又调用了realStartServiceLocked方法。从名字上来看,这个方法应该是一个真正启动Service的方法。它的实现如下:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
if (DEBUG_MU)
Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ ", ProcessRecord.uid = " + app.uid);
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
mAm.updateOomAdjLocked();
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);
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;
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null, 0));
}
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
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);
}
}
}
//app.thread这里我的AS看不到代码
在上述代码中,首先它通过app.thread的scheduleCreateService方法来创建Service对象
并调用其onCreate
,接着再通过sendServiceArgsLocked方法来调用Service的其他方法,如:onStartCommond,这两个过程均属于进程间通信。而app.thread的对象是iAppliacationThread类型,它实际上是一个Binder,因此只需要看ApplicationThread对Service启动过程的处理,通过ApplicationThread类中的scheduleCreateService方法发送一个msg,看代码如下:
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);
}
这里发送了CREATE_SERVICE消息,H(它在ActivityThread.java中)会接收并通过ActivityThread的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;
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);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
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);
}
}
}
这个方法中:
1.通过类加载器加载创建Service的实例。
2.创建Application对象并调用其onCreate,并且Application的创建过程只有一次。
3.创建conTextImpl对象并通过Service的attach方法建立二者之间的关系,这个过程和Activity实际上是类似的,毕竟Service和Activity都是一个Contex。
4.最后Service调用onCreate方法并将Service对象存储到ActivityThread中的一个列表(Map)中。如下;
final ArrayMap<IBinder,Service> mService =
new ArrayMap<IBinder, Service>()
由于Service的onCreate方法已经被执行了,所以Servcie已经启动了。除此之外,ActivityThread中还会通过hanleServiceArgs方法调用Servcie的onStartCommand方法。(onCreate方法的执行和onStartCommand方法的调用前面已经提到了)