基于8.0源码解析:startService 启动过程
2018-01-24 16:01
525 查看
基于8.0源码解析:startService 启动过程
调用startService 后会到ContextWrapper中:@Override public ComponentName startService(Intent service) { return mBase.startService(service); }
这个mBase就是Context,然后到ContextImpl中看一眼:
@Override 1459 public ComponentName startService(Intent service) { 1460 warnIfCallingFromSystemProcess(); 1461 return startServiceCommon(service, false, mUser); 1462 } 1463
又调用了startServiceCommon
private ComponentName startServiceCommon(Intent service, boolean requireForeground, 1487 UserHandle user) { 1488 try { 1489 validateServiceIntent(service); 1490 service.prepareToLeaveProcess(this); 1491 ComponentName cn = ActivityManager.getService().startService( 1492 mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( 1493 getContentResolver()), requireForeground, 1494 getOpPackageName(), user.getIdentifier()); 1495 if (cn != null) { 1496 if (cn.getPackageName().equals("!")) { 1497 throw new SecurityException( 1498 "Not allowed to start service " + service 1499 + " without permission " + cn.getClassName()); 1500 } else if (cn.getPackageName().equals("!!")) { 1501 throw new SecurityException( 1502 "Unable to start service " + service 1503 + ": " + cn.getClassName()); 1504 } else if (cn.getPackageName().equals("?")) { 1505 throw new IllegalStateException( 1506 "Not allowed to start service " + service + ": " + cn.getClassName()); 1507 } 1508 } 1509 return cn; 1510 } catch (RemoteException e) { 1511 throw e.rethrowFromSystemServer(); 1512 } 1513 } 1514
看到其中有这么一句:
ComponentName cn = ActivityManager.getService().startService( 1492 mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( 1493 getContentResolver()), requireForeground, 1494 getOpPackageName(), user.getIdentifier());
了解Binder机制的就会知道这会调用到ActivityManagerService中,
@Override 18125 public ComponentName startService(IApplicationThread caller, Intent service, 18126 String resolvedType, boolean requireForeground, String callingPackage, int userId) 18127 throws TransactionTooLargeException { 18128 enforceNotIsolatedCaller("startService"); 18129 // Refuse possible leaked file descriptors 18130 if (service != null && service.hasFileDescriptors() == true) { 18131 throw new IllegalArgumentException("File descriptors passed in Intent"); 18132 } 18133 18134 if (callingPackage == null) { 18135 throw new IllegalArgumentException("callingPackage cannot be null"); 18136 } 18137 18138 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, 18139 "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground); 18140 synchronized(this) { 18141 final int callingPid = Binder.getCallingPid(); 18142 final int callingUid = Binder.getCallingUid(); 18143 final long origId = Binder.clearCallingIdentity(); 18144 ComponentName res; 18145 try { 18146 res = mServices.startServiceLocked(caller, service, 18147 resolvedType, callingPid, callingUid, 18148 requireForeground, callingPackage, userId); 18149 } finally { 18150 Binder.restoreCallingIdentity(origId); 18151 } 18152 return res; 18153 } 18154 }
mServices.startServiceLocked
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, 328 int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) 329 throws TransactionTooLargeException { 330 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service 331 + " type=" + resolvedType + " args=" + service.getExtras()); 332 333 final boolean callerFg; 334 if (caller != null) { 335 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); 336 if (callerApp == null) { 337 throw new SecurityException( 338 "Unable to find app for caller " + caller 339 + " (pid=" + callingPid 340 + ") when starting service " + service); 341 } 342 callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; 343 } else { 344 callerFg = true; 345 } 346 347 ServiceLookupResult res = 348 retrieveServiceLocked(service, resolvedType, callingPackage, 349 callingPid, callingUid, userId, true, callerFg, false); 350 if (res == null) { 351 return null; 352 } 353 if (res.record == null) { 354 return new ComponentName("!", res.permission != null 355 ? res.permission : "private to package"); 356 } 357 358 ServiceRecord r = res.record; 359 360 if (!mAm.mUserController.exists(r.userId)) { 361 Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId); 362 return null; 363 } 364 365 // If this isn't a direct-to-foreground start, check our ability to kick off an 366 // arbitrary service 367 if (!r.startRequested && !fgRequired) { 368 // Before going further -- if this app is not allowed to start services in the 369 // background, then at this point we aren't going to let it period. 370 final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName, 371 r.appInfo.targetSdkVersion, callingPid, false, false); 372 if (allowed != ActivityManager.APP_START_MODE_NORMAL) { 373 Slog.w(TAG, "Background start not allowed: service " 374 + service + " to " + r.name.flattenToShortString() 375 + " from pid=" + callingPid + " uid=" + callingUid 376 + " pkg=" + callingPackage); 377 if (allowed == ActivityManager.APP_START_MODE_DELAYED) { 378 // In this case we are silently disabling the app, to disrupt as 379 // little as possible existing apps. 380 return null; 381 } 382 // This app knows it is in the new model where this operation is not 383 // allowed, so tell it what has happened. 384 UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid); 385 return new ComponentName("?", "app is in background uid " + uidRec); 386 } 387 } 388 389 NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked( 390 callingUid, r.packageName, service, service.getFlags(), null, r.userId); 391 392 // If permissions need a review before any of the app components can run, 393 // we do not start the service and launch a review activity if the calling app 394 // is in the foreground passing it a pending intent to start the service when 395 // review is completed. 396 if (mAm.mPermissionReviewRequired) { 397 if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, 398 callingUid, service, callerFg, userId)) { 399 return null; 400 } 401 } 402 403 if (unscheduleServiceRestartLocked(r, callingUid, false)) { 404 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); 405 } 406 r.lastActivity = SystemClock.uptimeMillis(); 407 r.startRequested = true; 408 r.delayedStop = false; 409 r.fgRequired = fgRequired; 410 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), 411 service, neededGrants, callingUid)); 412 413 final ServiceMap smap = getServiceMapLocked(r.userId); 414 boolean addToStarting = false; 415 if (!callerFg && !fgRequired && r.app == null 416 && mAm.mUserController.hasStartedUserState(r.userId)) { 417 ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); 418 if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { 419 // If this is not coming from a foreground caller, then we may want 420 // to delay the start if there are already other background services 421 // that are starting. This is to avoid process start spam when lots 422 // of applications are all handling things like connectivity broadcasts. 423 // We only do this for cached processes, because otherwise an application 424 // can have assumptions about calling startService() for a service to run 425 // in its own process, and for that process to not be killed before the 426 // service is started. This is especially the case for receivers, which 427 // may start a service in onReceive() to do some additional work and have 428 // initialized some global state as part of that. 429 if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of " 430 + r + " in " + proc); 431 if (r.delayed) { 432 // This service is already scheduled for a delayed start; just leave 433 // it still waiting. 434 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r); 435 return r.name; 436 } 437 if (smap.mStartingBackground.size() >= mMaxStartingBackground) { 438 // Something else is starting, delay! 439 Slog.i(TAG_SERVICE, "Delaying start of: " + r); 440 smap.mDelayedStartList.add(r); 441 r.delayed = true; 442 return r.name; 443 } 444 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r); 445 addToStarting = true; 446 } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { 447 // We slightly loosen when we will enqueue this new service as a background 448 // starting service we are waiting for, to also include processes that are 449 // currently running other services or receivers. 450 addToStarting = true; 451 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, 452 "Not delaying, but counting as bg: " + r); 453 } else if (DEBUG_DELAYED_STARTS) { 454 StringBuilder sb = new StringBuilder(128); 455 sb.append("Not potential delay (state=").append(proc.curProcState) 456 .append(' ').append(proc.adjType); 457 String reason = proc.makeAdjReason(); 458 if (reason != null) { 459 sb.append(' '); 460 sb.append(reason); 461 } 462 sb.append("): "); 463 sb.append(r.toString()); 464 Slog.v(TAG_SERVICE, sb.toString()); 465 } 466 } else if (DEBUG_DELAYED_STARTS) { 467 if (callerFg || fgRequired) { 468 Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid=" 469 + callingUid + " pid=" + callingPid + " fgRequired=" + fgRequired + "): " + r); 470 } else if (r.app != null) { 471 Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r); 472 } else { 473 Slog.v(TAG_SERVICE, 474 "Not potential delay (user " + r.userId + " not started): " + r); 475 } 476 } 477 478 ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); 479 return cmp; 480 }
最后调用了ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, 527 boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { 528 ServiceState stracker = r.getTracker(); 529 if (stracker != null) { 530 stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); 531 } 532 r.callStart = false; 533 synchronized (r.stats.getBatteryStats()) { 534 r.stats.startRunningLocked(); 535 } 536 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); 537 if (error != null) { 538 return new ComponentName("!!", error); 539 } 540 541 if (r.startRequested && addToStarting) { 542 boolean first = smap.mStartingBackground.size() == 0; 543 smap.mStartingBackground.add(r); 544 r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT; 545 if (DEBUG_DELAYED_SERVICE) { 546 RuntimeException here = new RuntimeException("here"); 547 here.fillInStackTrace(); 548 Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here); 549 } else if (DEBUG_DELAYED_STARTS) { 550 Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r); 551 } 552 if (first) { 553 smap.rescheduleDelayedStartsLocked(); 554 } 555 } else if (callerFg || r.fgRequired) { 556 smap.ensureNotStartingBackgroundLocked(r); 557 } 558 559 return r.name; 560 }
这个方法中又调用到了 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
然后掉用到:
sendServiceArgsLocked(r, execInFg, false);
进而调用到:
realStartServiceLocked(r, app, execInFg);
private final void realStartServiceLocked(ServiceRecord r, 2190 ProcessRecord app, boolean execInFg) throws RemoteException { 2191 if (app.thread == null) { 2192 throw new RemoteException(); 2193 } 2194 if (DEBUG_MU) 2195 Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid 2196 + ", ProcessRecord.uid = " + app.uid); 2197 r.app = app; 2198 r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); 2199 2200 final boolean newService = app.services.add(r); 2201 bumpServiceExecutingLocked(r, execInFg, "create"); 2202 mAm.updateLruProcessLocked(app, false, null); 2203 updateServiceForegroundLocked(r.app, /* oomAdj= */ false); 2204 mAm.updateOomAdjLocked(); 2205 2206 boolean created = false; 2207 try { 2208 if (LOG_SERVICE_START_STOP) { 2209 String nameTerm; 2210 int lastPeriod = r.shortName.lastIndexOf('.'); 2211 nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName; 2212 EventLogTags.writeAmCreateService( 2213 r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid); 2214 } 2215 synchronized (r.stats.getBatteryStats()) { 2216 r.stats.startLaunchedLocked(); 2217 } 2218 mAm.notifyPackageUse(r.serviceInfo.packageName, 2219 PackageManager.NOTIFY_PACKAGE_USE_SERVICE); 2220 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); 2221 app.thread.scheduleCreateService(r, r.serviceInfo, 2222 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), 2223 app.repProcState); 2224 r.postNotification(); 2225 created = true; 2226 } catch (DeadObjectException e) { 2227 Slog.w(TAG, "Application dead when creating service " + r); 2228 mAm.appDiedLocked(app); 2229 throw e; 2230 } finally { 2231 if (!created) { 2232 // Keep the executeNesting count accurate. 2233 final boolean inDestroying = mDestroyingServices.contains(r); 2234 serviceDoneExecutingLocked(r, inDestroying, inDestroying); 2235 2236 // Cleanup. 2237 if (newService) { 2238 app.services.remove(r); 2239 r.app = null; 2240 } 2241 2242 // Retry. 2243 if (!inDestroying) { 2244 scheduleServiceRestartLocked(r, false); 2245 } 2246 } 2247 } 2248 2249 if (r.whitelistManager) { 2250 app.whitelistManager = true; 2251 } 2252 2253 requestServiceBindingsLocked(r, execInFg); 2254 2255 updateServiceClientActivitiesLocked(app, null, true); 2256 2257 // If the service is in the started state, and there are no 2258 // pending arguments, then fake up one so its onStartCommand() will 2259 // be called. 2260 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { 2261 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), 2262 null, null, 0)); 2263 } 2264 2265 sendServiceArgsLocked(r, execInFg, true); 2266 2267 if (r.delayed) { 2268 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r); 2269 getServiceMapLocked(r.userId).mDelayedStartList.remove(r); 2270 r.delayed = false; 2271 } 2272 2273 if (r.delayedStop) { 2274 // Oh and hey we've already been asked to stop! 2275 r.delayedStop = false; 2276 if (r.startRequested) { 2277 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, 2278 "Applying delayed stop (from start): " + r); 2279 stopServiceLocked(r); 2280 } 2281 } 2282 }
app.thread.scheduleCreateService,这个thread就是IApplicationThread,就是ActivityThread对象,于是我们回到ActivityThread中:
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); }
我们去到H中找到对应的handleMessage处理CREATE_SERVICE的方法:
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;
然后handleCreateService:
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, ActivityManagerNative.getDefault()); service.onCreate(); mServices.put(data.token, service); try { ActivityManagerNative.getDefault().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); } } }
这个方法中service = (Service) cl.loadClass(data.info.name).newInstance();
用反射的方式创建了service对象;
然后ContextImpl context = ContextImpl.createAppContext(this, packageInfo);又创建了context对象;
然后用service.attach将context对象进行参数设置;
然后就调用了service.onCreate();
这就是Service的启动过程。
在刚刚realStartServiceLocked方法中:调用了 app.thread.scheduleCreateService方法后又调用了:
sendServiceArgsLocked(r, execInFg, true);
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, 2285 boolean oomAdjusted) throws TransactionTooLargeException { 2286 final int N = r.pendingStarts.size(); 2287 if (N == 0) { 2288 return; 2289 } 2290 2291 ArrayList<ServiceStartArgs> args = new ArrayList<>(); 2292 2293 while (r.pendingStarts.size() > 0) { 2294 ServiceRecord.StartItem si = r.pendingStarts.remove(0); 2295 if (DEBUG_SERVICE) { 2296 Slog.v(TAG_SERVICE, "Sending arguments to: " 2297 + r + " " + r.intent + " args=" + si.intent); 2298 } 2299 if (si.intent == null && N > 1) { 2300 // If somehow we got a dummy null intent in the middle, 2301 // then skip it. DO NOT skip a null intent when it is 2302 // the only one in the list -- this is to support the 2303 // onStartCommand(null) case. 2304 continue; 2305 } 2306 si.deliveredTime = SystemClock.uptimeMillis(); 2307 r.deliveredStarts.add(si); 2308 si.deliveryCount++; 2309 if (si.neededGrants != null) { 2310 mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants, 2311 si.getUriPermissionsLocked()); 2312 } 2313 mAm.grantEphemeralAccessLocked(r.userId, si.intent, 2314 r.appInfo.uid, UserHandle.getAppId(si.callingId)); 2315 bumpServiceExecutingLocked(r, execInFg, "start"); 2316 if (!oomAdjusted) { 2317 oomAdjusted = true; 2318 mAm.updateOomAdjLocked(r.app, true); 2319 } 2320 if (r.fgRequired && !r.fgWaiting) { 2321 if (!r.isForeground) { 2322 if (DEBUG_BACKGROUND_CHECK) { 2323 Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r); 2324 } 2325 scheduleServiceForegroundTransitionTimeoutLocked(r); 2326 } else { 2327 if (DEBUG_BACKGROUND_CHECK) { 2328 Slog.i(TAG, "Service already foreground; no new timeout: " + r); 2329 } 2330 r.fgRequired = false; 2331 } 2332 } 2333 int flags = 0; 2334 if (si.deliveryCount > 1) { 2335 flags |= Service.START_FLAG_RETRY; 2336 } 2337 if (si.doneExecutingCount > 0) { 2338 flags |= Service.START_FLAG_REDELIVERY; 2339 } 2340 args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent)); 2341 } 2342 2343 ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args); 2344 slice.setInlineCountLimit(4); 2345 Exception caughtException = null; 2346 try { 2347 r.app.thread.scheduleServiceArgs(r, slice); 2348 } catch (TransactionTooLargeException e) { 2349 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size() 2350 + " args, first: " + args.get(0).args); 2351 Slog.w(TAG, "Failed delivering service starts", e); 2352 caughtException = e; 2353 } catch (RemoteException e) { 2354 // Remote process gone... we'll let the normal cleanup take care of this. 2355 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r); 2356 Slog.w(TAG, "Failed delivering service starts", e); 2357 caughtException = e; 2358 } catch (Exception e) { 2359 Slog.w(TAG, "Unexpected exception", e); 2360 caughtException = e; 2361 } 2362 2363 if (caughtException != null) { 2364 // Keep nesting count correct 2365 final boolean inDestroying = mDestroyingServices.contains(r); 2366 for (int i = 0; i < args.size(); i++) { 2367 serviceDoneExecutingLocked(r, inDestroying, inDestroying); 2368 } 2369 if (caughtException instanceof TransactionTooLargeException) { 2370 throw (TransactionTooLargeException)caughtException; 2371 } 2372 } 2373 }
看到有这么一句r.app.thread.scheduleServiceArgs(r, slice);
于是回到ActivityThread中:
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, int flags ,Intent args) { ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = taskRemoved; s.startId = startId; s.flags = flags; s.args = args; sendMessage(H.SERVICE_ARGS, s); }
还是去H中找对应的处理case:
case SERVICE_ARGS: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj))); handleServiceArgs((ServiceArgsData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
接着去看handleServiceArgs:
private void handleServiceArgs(ServiceArgsData data) { Service s = mServices.get(data.token); if (s != null) { try { if (data.args != null) { data.args.setExtrasClassLoader(s.getClassLoader()); data.args.prepareToEnterProcess(); } int res; if (!data.taskRemoved) { res = s.onStartCommand(data.args, data.flags, data.startId); } else { s.onTaskRemoved(data.args); res = Service.START_TASK_REMOVED_COMPLETE; } QueuedWork.waitToFinish(); try { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } ensureJitEnabled(); } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }
s.onStartCommand中s就是上面创建的service对象。那么onStartCommand方法就是在这里调用的。至此service启动过程完毕。下面画图看下这个流程:
相关文章推荐
- 基于8.0源码解析:bindService 启动过程
- Android 8.0系统源码分析--startService启动过程源码分析
- Android源码解析之新进程中启动自定义服务过程(startService)的原理分析
- Activity的启动过程之startActivity源码解析
- Android源码解析四大组件系列(一)---Service的启动过程分析
- Android笔记-service启动过程分析:bindService源码分析、startService和bindService区别
- Android源码解析之应用程序内部启动Activity过程(startActivity)的源代码分析
- Android笔记-service启动过程分析:startService源码分析
- RocketMQ4.1.0源码解析--Consumer的启动过程
- Android应用程序的启动过程源码解析—点击图标启动过程
- Android系统在新进程中启动自定义服务过程(startService)的原理分析
- Android 插件化开发——应用的启动过程源码解析(简单清晰)
- Android系统在新进程中启动自定义服务过程(startService)的原理分析
- Android系统源码阅读(4):Service在新进程中启动过程
- 8.0源码解析:Activity启动流程
- android 4.04的应用程序启动过程及与Zygote的交互(基于静态源码分析)
- docker 源码分析 六(基于1.8.2版本),Docker run启动过程
- Spring源码解析-Web容器启动过程
- docker 源码分析 一(基于1.8.2版本),docker daemon启动过程;