前面最先分析得Activity和Provider,其中Activity是在ActivityThread中直接啟動的,呼叫了handleLaunchActivity;而Provider如果是跨程式,則呼叫了AMS獲取IContentProvider會阻塞在“等待Provider安裝完成”,ActivityThread在安裝完成後通知AMS已經安裝Provider成功,AMS阻塞被喚醒返回給呼叫者。
這裡感覺一下,startService應該跟Activity類似,而bindeService跟Provider類似。前者在ActivityThread中作出相應即可,而後者則需要在AMS中等待onBinder的安裝(bindService是非同步的,而Provider呼叫時同步的)。
1684 @Override
1685 public ComponentName startService(Intent service) {
1686 warnIfCallingFromSystemProcess();
1687 return startServiceCommon(service, mUser);
1688 }
1701 private ComponentName startServiceCommon(Intent service, UserHandle user) {
1702 try {
1703 validateServiceIntent(service);
1704 service.prepareToLeaveProcess();
1705 ComponentName cn = ActivityManagerNative.getDefault().startService(
1706 mMainThread.getApplicationThread(), service,
1707 service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
1719 return cn;
1720 } catch (RemoteException e) {
1721 return null;
1722 }
1723 }複製程式碼
穿越進入ActivityManagerService中,第一個引數ApplicationThread,第二個引數是Intent,第三個引數是型別,第四個引數是userid。
14680 @Override
14681 public ComponentName startService(IApplicationThread caller, Intent service,
14682 String resolvedType, int userId) {
14691 synchronized(this) {
14692 final int callingPid = Binder.getCallingPid();
14693 final int callingUid = Binder.getCallingUid();
14694 final long origId = Binder.clearCallingIdentity();
14695 ComponentName res = mServices.startServiceLocked(caller, service,
14696 resolvedType, callingPid, callingUid, userId);
14698 return res;
14699 }
14700 }複製程式碼
282 ComponentName startServiceLocked(IApplicationThread caller,
283 Intent service, String resolvedType,
284 int callingPid, int callingUid, int userId) {
287
288 final boolean callerFg;
289 if (caller != null) {
290 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
291 if (callerApp == null) {
296 }
298 } else {
299 callerFg = true;
300 }
301
303 ServiceLookupResult res =
304 retrieveServiceLocked(service, resolvedType,
305 callingPid, callingUid, userId, true, callerFg);
314 ServiceRecord r = res.record;
332 final ServiceMap smap = getServiceMap(r.userId);
333 boolean addToStarting = false;
334 if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {
335 ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
383 }
394 return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
395 }複製程式碼
Service的處理邏輯單獨放到了ActiveService中,如果ServiceRecord沒有則會在retrieveServiceLocked中新建一個smap中,new ServiceLoopupResult(serviceRecord)返回。
397 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
398 ServiceRecord r, boolean callerFg, boolean addToStarting) {
399 ProcessStats.ServiceState stracker = r.getTracker();
407 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);
429
430 return r.name;
431 }複製程式碼
1305 private final String bringUpServiceLocked(ServiceRecord r,
1306 int intentFlags, boolean execInFg, boolean whileRestarting) {
1310 if (r.app != null && r.app.thread != null) {
1311 sendServiceArgsLocked(r, execInFg, false);
1312 return null;
1313 }
1358 final String procName = r.processName;
1359 ProcessRecord app;
1360
1361 if (!isolated) {
1362 app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
1365 if (app != null && app.thread != null) {
1366 try {
1367 app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
1368 realStartServiceLocked(r, app, execInFg);
1369 return null;
1370 } catch (RemoteException e) {
1372 }
1376 }
1377 }
1389 if (app == null) {
1390 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
1391 "service", r.name, false, isolated, false)) == null) {
1397 bringDownServiceLocked(r);
1398 return msg;
1399 }
1403 }
14041405 if (!mPendingServices.contains(r)) {
1406 mPendingServices.add(r);
1407 }
1418 return null;
1419 }
複製程式碼
三步走
第一步:如果服務,對ServiceRecord中掛起的任務處理一次。第一次建立ServiceRecord這裡不會執行的。騷年們要注意呀,這裡的判斷是ServiceRecord.app && ServiceRecord.app.thread
1507 private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
1508 boolean oomAdjusted) {
1509 final int N = r.pendingStarts.size();
1510 if (N == 0) {
1511 return;
1512 }
1513
1514 while (r.pendingStarts.size() > 0) {
1515 try {
1516 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
1519 if (si.intent == null && N > 1) {
1524 continue;
1525 }
1545 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
1546 } catch (RemoteException e) {
1550 break;
1551 } catch (Exception e) {
1553 break;
1554 }
1555 }
1556 }複製程式碼
呼叫IApplicationThread.handleServiceArgs,進入到ActivityThread中
第二步:如果是程式內,且程式已經啟動了,呼叫ActivityThread中的handleCreateService,後面再分析吧
1430 private final void realStartServiceLocked(ServiceRecord r,
1431 ProcessRecord app, boolean execInFg) throws RemoteException {
1440
1446 boolean created = false;
1447 try {
1448 String nameTerm;
1449 int lastPeriod = r.shortName.lastIndexOf('.');
1460 app.thread.scheduleCreateService(r, r.serviceInfo,
1461 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
1462 app.repProcState);
1463 r.postNotification();
1464 created = true;
1465 } catch (DeadObjectException e) {
1467 mAm.appDiedLocked(app);
1468 } finally {
1469 if (!created) {
1470 app.services.remove(r);
1471 r.app = null;
1472 scheduleServiceRestartLocked(r, false);
1473 return;
1474 }
1475 }1477 requestServiceBindingsLocked(r, execInFg);
1478
1489 sendServiceArgsLocked(r, execInFg, true);
1505 }複製程式碼
第三步:程式(程式內和程式外放到一起了)還沒有啟動,那麼呼叫startProcessLocked
-> ActivityThread.main -> ActivityThread.attach -> AMS.attachApplication -> IApplicationThread.scheduleBindAppliction + ActivityStackSupervisor.attachProceessLocked + ActiveServices.attachProcessLocked + mBroadcastQueues.sendPendingBraodcasts
http://androidxref.com/5.0.0_r2/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java#attachApplicationLocked1917 boolean attachApplicationLocked(ProcessRecord proc, String processName)
1918 throws RemoteException {
1919 boolean didSomething = false;
1921 if (mPendingServices.size() > 0) {
1922 ServiceRecord sr = null;
1923 try {
1924 for (int i=0; i<mPendingServices.size(); i++) {
1925 sr = mPendingServices.get(i);
1930
1931 mPendingServices.remove(i);
1932 i--;
1933 proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
1934 mAm.mProcessStats);
1935 realStartServiceLocked(sr, proc, sr.createdFromFg);
1936 didSomething = true;
1937 }
1938 } catch (RemoteException e) {
1941 throw e;
1942 }
1943 }
1960 return didSomething;
1961 }複製程式碼
取出mPendingServices中的服務,啟動併傳送訊息。
1430 private final void realStartServiceLocked(ServiceRecord r,
1431 ProcessRecord app, boolean execInFg) throws RemoteException {
1440
1446 boolean created = false;
1447 try {
1448 String nameTerm;
1449 int lastPeriod = r.shortName.lastIndexOf('.');
1460 app.thread.scheduleCreateService(r, r.serviceInfo,
1461 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
1462 app.repProcState);
1463 r.postNotification();
1464 created = true;
1465 } catch (DeadObjectException e) {
1467 mAm.appDiedLocked(app);
1468 } finally {
1469 if (!created) {
1470 app.services.remove(r);
1471 r.app = null;
1472 scheduleServiceRestartLocked(r, false);
1473 return;
1474 }
1475 }
1477 requestServiceBindingsLocked(r, execInFg);
1489 sendServiceArgsLocked(r, execInFg, true);
1505 }複製程式碼
總結一下三部曲:
如果服務啟動了,直接傳送訊息,並執行bind流程。如果服務沒有啟動,那麼:
如果程式啟動了,則啟動服務一下併傳送訊息;如果程式沒有啟動,那麼先把服務加入到mPendingServices中,再啟動程式,等程式啟動後執行ActiveServices.attachApplicationLocked解決呼叫mPendingServices。
------------------------------------------------------------------------------------------------
看看ActivityThread中的handleCreateService
2703 private void handleCreateService(CreateServiceData data) {
2706 unscheduleGcIdler();
2707
2708 LoadedApk packageInfo = getPackageInfoNoCheck(
2709 data.info.applicationInfo, data.compatInfo);
2710 Service service = null;
2711 try {
2712 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2713 service = (Service) cl.loadClass(data.info.name).newInstance();
2714 } catch (Exception e) {
2715 if (!mInstrumentation.onException(service, e)) {
2719 }
2720 }
2721
2722 try {
2725 ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
2726 context.setOuterContext(service);
2727
2728 Application app = packageInfo.makeApplication(false, mInstrumentation);
2729 service.attach(context, this, data.info.name, data.token, app,
2730 ActivityManagerNative.getDefault());
2731 service.onCreate();
2732 mServices.put(data.token, service);
2733 try {
2734 ActivityManagerNative.getDefault().serviceDoneExecuting(
2735 data.token, 0, 0, 0);
2736 } catch (RemoteException e) {
2738 }
2739 } catch (Exception e) {
2745 }
2746 }複製程式碼
首先反射構造Service例項,執行了onCreate函式,並儲存到mServices中。
再看看給Service傳送訊息handleServiceArgs
2854 private void handleServiceArgs(ServiceArgsData data) {
2855 Service s = mServices.get(data.token);
2856 if (s != null) {
2857 try {
2862 int res;
2863 if (!data.taskRemoved) {
2864 res = s.onStartCommand(data.args, data.flags, data.startId);
2865 } else {
2866 s.onTaskRemoved(data.args);
2867 res = Service.START_TASK_REMOVED_COMPLETE;
2868 }
2870 QueuedWork.waitToFinish();
2879 } catch (Exception e) {
2885 }
2886 }
2887 }複製程式碼
因為建立的時候儲存到mService中,取出來然後執行onStartCommand操作。其中mService的key是ServiceRecord的代理。可以看看類資訊
應該是根據component儲存到了AMS.ActivieServices.smap中吧
------------------------------------------------------------------------------------------------
總結:AMS為每一個Service建立了一個ServiceRecord,儲存在smap中。首先需要建立Service,建立的時機是在mPendingServices或者直接建立,最終都呼叫scheduleCreateService。當建立完成後會傳送待處理的訊息,待處理的訊息放在了ServiceRecord.mPendingStars中,最終呼叫了scheduleServiceArgs。因此,startService的整個模型跟Activity差不多,AMS建立元件快取並轉發訊息給元件。