Android中的Service是如何启动的(android service用法)
lipiwang 2024-11-15 22:03 33 浏览 0 评论
1:前言
Service是Android中的四大组件之一,日常开发中我们经常会使用startService之类的方法来启动Service,那这个方法调用的底层原理是什么呢?Android系统是如何启动起来Service的呢?本文我们从源码出发,介绍一下Android中的Service是如何启动Service的,本文的结构如下:
2:源码分析
2.1:ContextImpl.startService&startForegroundService:应用层调用的入口
我们调用startService/startForegroundService之后,会调用到android.app.ContextImpl#startService/startForegroundService:
class ContextImpl extends Context {
@Override
public ComponentName startService(Intent service) {
return startServiceCommon(service, false, mUser);
}
@Override
public ComponentName startForegroundService(Intent service) {
return startServiceCommon(service, true, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
...
}
}
可以看到,startService和startForegroundService最终调用的都是startServiceCommon这个方法,唯一不同的是第二个参数requireForeground的值不一样,用来标识当前Service是否是前台Serivice,我们来看startServiceCommon的具体实现:
class ContextImpl extends Context {
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(), getAttributionTag(), 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();
}
}
}
可以看到,核心是调用到了ActivityManager.getService().startService()方法进行Service的启动,即AMS中,我们来看一下AMS中是如何启动Service的.
2.2:ActivityManagerService.startService:执行前置判断,满足启动service的条件的话触发真正startService的逻辑
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
final ActiveServices mServices;
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId)
throws TransactionTooLargeException {
...
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, callingFeatureId, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
}
可以看到,最终调用到了ActiveServices.startServiceLocked()中:
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
@Nullable String callingFeatureId, final int userId)
throws TransactionTooLargeException {
return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
callingPackage, callingFeatureId, userId, false);
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
@Nullable String callingFeatureId, final int userId,
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
/**
*对当前Service的启动进行判断,看下Service启动的限制(比如权限、前后台等是否满足)
**/
...
//启动Service
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
if (!r.mAllowWhileInUsePermissionInFgs) {
r.mAllowWhileInUsePermissionInFgs =
shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid,
callingUid, service, r, allowBackgroundActivityStarts);
}
return cmp;
}
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;
}
}
核心是调用到了ActiveServices.bringUpServiceLocked.
2.3:ActiveServices.bringUpServiceLocked:根据进程&线程是否存在执行不同操作
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//如果进程和线程已经不为空,说明该Service已经create了,直接调用sendServiceArgsLocked
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
...
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
//如果进程已经在了,调用realStartServiceLocked进行start service
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
}
// 如果进程还没启动,调用mAm.startProcessLocked启动进程
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
//埋下异常
bringDownServiceLocked(r);
...
}
}
//将当前ServiceRecord加到mPendingServices里,
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
...
}
}
在《Android的进程》一文中我们介绍过,最终进程起来之后会执行ActivityManagerService.attachApplication-->ActivityManagerService.attachApplicationLocked:
public class ActivityManagerService extends IActivityManager.Stub{
public ActivityTaskManagerInternal mAtmInternal;
final ActiveServices mServices;
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
boolean badApp = false;
boolean didSomething = false;
// 先尝试启动Activity
if (normalMode) {
try {
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
//Activity启动没问题,尝试启动Service
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
}
}
可以看到,先启动了Activity,如果Activity的启动过程中没有出错,就启动Service即调用ActiveServices.attachApplicationLocked.
2.4:ActiveServices.attachApplicationLocked:进程启动完成,继续启动service
public final class ActiveServices {
boolean attachApplicationLocked(ProcessRecord proc, String processName){
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);
i--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
mAm.mProcessStats);
//核心操作是调用realStartServiceLocked
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
if (!isServiceNeededLocked(sr, false, false)) {
// We were waiting for this service to start, but it is actually no
// longer needed. This could happen because bringDownServiceIfNeeded
// won't bring down a service that is pending... so now the pending
// is done, so let's drop it.
bringDownServiceLocked(sr);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortInstanceName, e);
throw e;
}
}
// Also, if there are any services that are waiting to restart and
// would run in this process, now is a good time to start them. It would
// be weird to bring up the process but arbitrarily not let the services
// run at this point just because their restart time hasn't come up.
if (mRestartingServices.size() > 0) {
ServiceRecord sr;
for (int i=0; i<mRestartingServices.size(); i++) {
sr = mRestartingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mAm.mHandler.removeCallbacks(sr.restarter);
mAm.mHandler.post(sr.restarter);
}
}
return didSomething;
}
}
可以看到最终调用到了realStartServiceLocked.
2.5:ActiveServices.realStartServiceLocked:先埋炸弹,然后触发service启动
public final class ActiveServices {
/**
* Note the name of this method should not be confused with the started services concept.
* The "start" here means bring up the instance in the client, and this method is called
* from bindService() as well.
*/
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.setProcess(app);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
//调用ProcessRecord.startService,实质是将此处的ServiceRecord add到ProcessRecord.mServices中
final boolean newService = app.startService(r);
//埋下ANR炸弹
bumpServiceExecutingLocked(r, execInFg, "create");
//调整进程的优先级
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
boolean created = false;
...
//最终触发service.onCreate
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
...
//bind service
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
if (newService && created) {
app.addBoundClientUidsOfNewService(r);
}
// 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));
}
//拉起timeout,最终调用Service.onStartCommand
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);
}
}
}
2.6:ActiveServices.bumpServiceExecutingLocked:埋下ANR炸弹(SERVICE_TIMEOUT_MSG)
public final class ActiveServices {
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
// How long the startForegroundService() grace period is to get around to
// calling startForeground() before we ANR + stop it.
static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
long now = SystemClock.uptimeMillis();
if (r.executeNesting == 0) {
r.executeFg = fg;
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
}
if (r.app != null) {
r.app.executingServices.add(r);
r.app.execServicesFg |= fg;
if (timeoutNeeded && r.app.executingServices.size() == 1) {
//启动延迟炸弹(触发ANR)
scheduleServiceTimeoutLocked(r.app);
}
}
} else if (r.app != null && fg && !r.app.execServicesFg) {
r.app.execServicesFg = true;
if (timeoutNeeded) {
scheduleServiceTimeoutLocked(r.app);
}
}
r.executeFg |= fg;
r.executeNesting++;
r.executingStart = now;
}
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
//前台Service延迟SERVICE_TIMEOUT(20s),后台Service延迟SERVICE_BACKGROUND_TIMEOUT(200s)
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}
}
2.7:ActivityThread.scheduleCreateService:触发Service.onCreate
可以看到这里主要是发送了一个CREATE_SERVICE的Message消息:
//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler
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);
}
public void handleMessage(Message msg) {
...
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
...
}
public static final int SERVICE_DONE_EXECUTING_ANON = 0;
@UnsupportedAppUsage
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
Application app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//实例化Service的对象
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// Service resources must be initialized with the same loaders as the application
// context.
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
context.setOuterContext(service);
//调用Service.attach
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用Service.onCreate
service.onCreate();
mServices.put(data.token, service);
//通知ActivityManagerService,Service启动完成,拆除预埋的炸弹,调整进程优先级
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (Exception e) {
}
}
}
//frameworks/base/core/java/android/app/AppComponentFactory.java
class AppComponentFactory{
public @NonNull Service instantiateService(@NonNull ClassLoader cl,
@NonNull String className, @Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Service) cl.loadClass(className).newInstance();
}
}
2.8:ActivityManagerService.serviceDoneExecuting:拆除预埋的炸弹
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
final ActiveServices mServices;
public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
throw new IllegalArgumentException("Invalid service token");
}
mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
}
}
}
最终调用到了ActiveServices.serviceDoneExecutingLocked:
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
if (r != null) {
...
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
}
}
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
boolean finishing) {
//拆除预埋的SERVICE_TIMEOUT_MSG炸弹
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
//调整进程优先级
mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
}
}
2.9:ActiveServices.sendServiceArgsLocked:启动延迟任务,埋下ANR和崩溃炸弹、触发onstartCommand
public final class ActiveServices {
final ActivityManagerService mAm;
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
ArrayList<ServiceStartArgs> args = new ArrayList<>();
while (r.pendingStarts.size() > 0) {
ServiceRecord.StartItem si = r.pendingStarts.remove(0);
//核心操作,埋下ANR炸弹,上面介绍过了
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
//更新进程优先级
mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
}
if (r.fgRequired && !r.fgWaiting) {
if (!r.isForeground) {
//对于前台Service,启动延迟任务,检测Service调用了startForeground,否则会崩溃
scheduleServiceForegroundTransitionTimeoutLocked(r);
} else {
r.fgRequired = false;
}
}
int flags = 0;
if (si.deliveryCount > 1) {
flags |= Service.START_FLAG_RETRY;
}
if (si.doneExecutingCount > 0) {
flags |= Service.START_FLAG_REDELIVERY;
}
args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
}
ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
slice.setInlineCountLimit(4);
Exception caughtException = null;
try {
//调用ActivityThread.scheduleServiceArgs,最终执行Service.onstartCommand
r.app.thread.scheduleServiceArgs(r, slice);
}
}
// How long the startForegroundService() grace period is to get around to
// calling startForeground() before we ANR + stop it.
static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
if (r.app.executingServices.size() == 0 || r.app.thread == null) {
return;
}
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
msg.obj = r;
r.fgWaiting = true;
//延迟10s发送,埋下崩溃炸弹
mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT);
}
}
2.10:ActivityThread.scheduleServiceArgs:触发onStartcommand
//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = ssa.taskRemoved;
s.startId = ssa.startId;
s.flags = ssa.flags;
s.args = ssa.args;
sendMessage(H.SERVICE_ARGS, s);
}
}
public void handleMessage(Message msg) {
...
case SERVICE_ARGS:
handleServiceArgs((ServiceArgsData)msg.obj);
break;
...
}
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
...
//调用onStartcommand
res = s.onStartCommand(data.args, data.flags, data.startId);
//拆除预埋的炸弹
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
...
}
}
核心是发送了一个SERVICE_ARGS的message。
2.11:ActivityManagerService.handleMessage:处理不同的message(炸弹)
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
final MainHandler mHandler;
final ActiveServices mServices;
final class MainHandler extends Handler {
public MainHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SERVICE_TIMEOUT_MSG: {
//抛出anr
mServices.serviceTimeout((ProcessRecord)msg.obj);
}
break;
case SERVICE_FOREGROUND_TIMEOUT_MSG: {
//抛出anr
mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
}
break;
case SERVICE_FOREGROUND_CRASH_MSG: {
//引发crash,报错Context.startForegroundService() did not then call Service.startForeground() xxx
mServices.serviceForegroundCrash(
(ProcessRecord) msg.obj, msg.getData().getCharSequence(SERVICE_RECORD_KEY));
}
break;
}
}
}
}
2.12:Service.startFroeground:前台Service必须调用,展示通知,解除崩溃炸弹
对于前台Service,必须在Service启动之后手动调用Service.startFroeground,否则会触发上文中的崩溃炸弹:
//frameworks/base/core/java/android/app/Service.java
public abstract class Service extends ContextWrapper {
public final void startForeground(int id, Notification notification) {
try {
mActivityManager.setServiceForeground(
new ComponentName(this, mClassName), mToken, id,
notification, 0, FOREGROUND_SERVICE_TYPE_MANIFEST);
} catch (RemoteException ex) {
}
}
}
最终调用到了AMS.setServiceForeground:
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
final ActiveServices mServices;
@Override
public void setServiceForeground(ComponentName className, IBinder token,
int id, Notification notification, int flags, int foregroundServiceType) {
synchronized(this) {
mServices.setServiceForegroundLocked(className, token, id, notification, flags,
foregroundServiceType);
}
}
}
核心是调用ActiveServices.setServiceForegroundLocked.
2.13:ActiveServices.setServiceForegroundLocked:发送通知,取消崩溃
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
public void setServiceForegroundLocked(ComponentName className, IBinder token,
int id, Notification notification, int flags, int foregroundServiceType) {
final int userId = UserHandle.getCallingUserId();
final long origId = Binder.clearCallingIdentity();
try {
ServiceRecord r = findServiceLocked(className, token, userId);
if (r != null) {
setServiceForegroundInnerLocked(r, id, notification, flags, foregroundServiceType);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
/**
* @param id Notification ID. Zero === exit foreground state for the given service.
*/
private void setServiceForegroundInnerLocked(final ServiceRecord r, int id,
Notification notification, int flags, int foregroundServiceType) {
//id不可为0
if (id != 0) {
//notification不可为空
if (notification == null) {
throw new IllegalArgumentException("null notification");
}
...
if (r.fgRequired) {
if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "Service called startForeground() as required: " + r);
}
r.fgRequired = false;
r.fgWaiting = false;
alreadyStartedOp = stopProcStatsOp = true;
//移除SERVICE_FOREGROUND_TIMEOUT_MSG消息,取消崩溃
mAm.mHandler.removeMessages(
ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
}
}
}
}
3:整个Service启动过程中涉及到的跨进程调用
3.1:ContextImpl -→ AMS:调用方进程→system_server进程
- 被调用方法:AMS中的startService()
ActivityManager.getService().startService()
3.2:ActivityThread -→ AMS:service所在进程→system_server进程
- 被调用方法:AMS中的attachApplication()
ActivityManager.getService().attachApplication()
- 拆除炸弹
ActivityManager.getService().serviceDoneExecuting()
3.3: AMS -→ ActivityThread:system_server进程→service所在进程
- 被调用方法:ApplicationThread中的scheduleCreateService()
app.thread.scheduleCreateService()
- 被调用方法:ApplicationThread中的scheduleServiceArgs()
app.threadscheduleServiceArgs()
4:总结
基于上述源码的分析,我们可以将Service的整体启动流程总结为下图:
以上就是Android中Service启动的大致原理,如果觉得有收获,欢迎关注点赞~
5:参考
相关推荐
- lushdns – 如何使用 Windows ipconfig /flushdns 命令刷新 DNS
-
您可能已经注意到,第一次访问网站后,下次访问时该网站的加载速度会更快。这是因为您的操作系统或浏览器(如果是GoogleChrome)会缓存您访问的任何网站的IP地址和DNS(域名系统)信息。...
- Windows10电脑无法直接连接已保存无线网络逐步排查和解决方案
-
可能原因分析IP地址冲突:系统未能正确获取或释放IP地址,导致与路由器通信失败。DNS缓存/网络配置错误:旧的缓存或错误配置阻碍新连接。无线网卡驱动问题:驱动不兼容或存在故障。电源管理干扰:系统为省电...
- 删除电脑dns缓存(如何删除dns缓存)
-
用Windows+R快捷键打开「运行」,输入cmd,然后按Ctrl+Shift+Enter以管理员权限启动「命令提示符」。输入:ipconfig/flushdns回车...
- 电脑插网线无法上网的系统化解决方案
-
当电脑插上网线却无法访问网络时,可从物理连接、网络配置、驱动程序、系统设置等多维度排查问题。以下按优先级排序的解决方案,助你高效定位并解决故障。一、基础排查(解决80%常见问题)检查物理连接首先确...
- 《银与绯》国服海外畅玩解决方案(银绯什么意思)
-
对于海外玩家想要体验《银与绯》国服,使用SixFast游戏加速器是最佳选择。以下是详细操作指南:一、SixFast完整配置流程1.获取SixFast客户端-官网下载:访问sixfast.com选择对...
- steam打不开/商店打不开的最新解决方法来了
-
steam打不开/商店打不开的最新解决方法来了Steam平台采用了统一的账户系统,玩家只需注册一个账户,就可以在平台上购买、下载和玩游戏。遇到Steam平台或商店打不开的烦恼?别担心,这里有几个简单实...
- 电脑恢复DNS最简单方法(如何恢复dns默认设置)
-
当电脑遇到DNS(域名系统)问题时,通常表现为无法访问某些网站或整个网络浏览变得缓慢而不稳定。DNS负责将人类可读的域名(如www.example.com)转换为机器可读的IP地址(如192.0.2....
- WiFi越用越慢?几个简单操作让网络满血复活
-
关注硬件·聪明消费|欢迎关注钛师父动图:耳机震膜工作原理WiFi用了一段时间后便慢了?这恐怕不是幻觉,也不是运营商的猫腻,显然没有人会像苹果一样刻意降低你的网速逼你换套餐甚至换运营商。大多时候这样...
- Win11快速开启DNS加密功能(国内可用)
-
今天我花了三个小时仔细研究了Windows的DNS加密(DoH)相关的内容,最终成功开启了国内可用的DNS加密功能,如果你还不知道什么是DoH并对原理感兴趣,可以参考这篇文章:https://zhua...
- 如何在 Windows 11 或 10 中使用 CMD 清除缓存
-
当你使用操作系统的时间变长,随着时间推移,缓存文件的积累可能会导致Windows11或10系统变慢,还会占用宝贵的存储空间,尤其是当您使用M.2固态硬盘的时候。因此,定期清除缓存文件或许...
- 绝地求生PUBG商店买不了东西Steam界面一直刷新加载的解决办法
-
在绝地求生(PUBG)的最新更新中,游戏引入了一系列新功能和优化,包括地图改进、武器平衡调整以及新的皮肤和物品。然而,随之而来的是一些玩家在尝试从游戏内商店购买这些新鲜内容时遇到了绝地求生PUBG商店...
- Win11正式版网络错误访问提示0x800704cf的问题
-
有深度技术的用户在win11正式版系统电脑中出现网络错误提示0x800704cf错误代码,那么如何解决这个问题?接下来,深度官网小编为大家带来详细的解决方案,大家可以一起来看看。当Win11正式版...
- 网站维护进不去怎么办(网站在维护期间进不去)
-
当遇到网站无法访问并显示维护提示时,可能是临时维护,也可能存在其他故障。以下提供系统的排查步骤与解决方法,助你快速定位问题并解决。一、判断网站是否处于真实维护状态1.官方渠道信息核查公告查询:访问网...
- 网络适配器在设备管理器中消失的恢复方案
-
网络适配器(网卡)在设备管理器中突然消失,会导致设备无法正常联网,这通常由驱动异常、系统冲突或硬件故障引起。为帮助你高效解决问题,以下提供按操作复杂度由易到难排序的逐步恢复方案,请依次尝试。一、基础排...
- 【电脑蓝屏】常见的电脑问题解决方法
-
一、系统问题1.电脑开机慢/卡顿解决方法:关闭开机启动项:Ctrl+Shift+Esc→启动→禁用不必要的程序。清理磁盘:Win+S→搜索“磁盘清理”→勾选临时文件、...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)