Android中间层分析1.【AMS】进程的启动-startservice启动分析

1.启动的入口startservice

无论怎么样,Activity的startservice最终都会到,ActivityManagerService的startService,函数中来。

@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId)
            throws TransactionTooLargeException {

        synchronized (this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

而这个函数并没有做太多事情,就调用了mServices.startServiceLocked,这个mServices变量子在ams里面是专门用来管理service的。

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, String callingPackage, final int userId)
            throws TransactionTooLargeException {
....

        ServiceLookupResult res =
            retrieveServiceLockedWrapper(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);
        if (res == null) {
            return null;
       return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }


这里主要做了两件事情

  • retrieveServiceLockedWrapper : 建立service信息
  • startServiceInnerLocked: 启动这个service

2.service信息的建立过程 — retrieveServiceLocked

private ServiceLookupResult retrieveServiceLockedWrapper(Intent service,
			String resolveType, String callingPackage, int callingPid, int callingUid, int userId,
			boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
		ServiceLookupResult res = retrieveServiceLocked(service, resolveType, callingPackage,
						callingPid, callingUid, userId, createIfNeeded, callingFromFg, isBindExternal);

		String targetPackageName = null;
		if (res != null && res.record != null) {
		    targetPackageName = res.record.packageName;
		}

		return res;
	}

继续调用retrieveServiceLocked

private ServiceLookupResult retrieveServiceLocked(Intent service,
            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
            boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
        ServiceRecord r = null;


        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);

        ServiceMap smap = getServiceMap(userId);
        final ComponentName comp = service.getComponent();
        if (comp != null) {
            r = smap.mServicesByName.get(comp);
        }
       ...
        if (r == null) {
            try {
                ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
                        resolvedType, ActivityManagerService.STOCK_PM_FLAGS
                                | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                        userId);
                ServiceInfo sInfo =
                    rInfo != null ? rInfo.serviceInfo : null;
                if (sInfo == null) {
                    Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
                          ": not found");
                    return null;
                }
                ComponentName name = new ComponentName(
                        sInfo.applicationInfo.packageName, sInfo.name);
...
                r = smap.mServicesByName.get(name);
                if (r == null && createIfNeeded) {
                    Intent.FilterComparison filter
                            = new Intent.FilterComparison(service.cloneFilter());
                    ServiceRestarter res = new ServiceRestarter();
                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
                    BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                    synchronized (stats) {
                        ss = stats.getServiceStatsLocked(
                                sInfo.applicationInfo.uid, sInfo.packageName,
                                sInfo.name);
                    }
                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                    res.setService(r);
                    smap.mServicesByName.put(name, r);
                    smap.mServicesByIntent.put(filter, r);
...
                }
            } catch (RemoteException ex) {
                // pm is in same process, this will never happen.
            }
        }
        if (r != null) {
            if (mAm.checkComponentPermission(r.permission,
                    callingPid, callingUid, r.appInfo.uid, r.exported)
            ....
            }

            if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
                    resolvedType, r.appInfo)) {
                return null;
            }
            return new ServiceLookupResult(r, null);
        }
        return null;
    }
  • 1、通过getServiceMap获取 smap 这个是一个全局的收集Service的地方,
  • 2、comp 如果是第一次启动service是空,如果不是的话就不会
  • 3、这个rServiceRecord,如果是第一次的话也是空
  • 4、如果空怎么办呢?去pms里面找,如果没有找到,rinfo是空的就返回空如果找到,就new一个comp,然后在做一个sInfo复制给r。
  • 5、然后这个r就有了,然后就返回new ServiceLookupResult(r, null);
  • 6、其他就是权限检查
    这样子,我们就建立了一个service的信息。ServiceRecord会放在ServiceMap中。

3.service的启动过程 —startServiceInnerLocked

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);
        }
        return r.name;
    }

将刚才的r,以及其他的信息放给bringUpServiceLocked.

bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
      if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
            if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            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);
                }
...
            }
        } else {
...
            app = r.isolatedProc;
        }
         if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        "service", r.name, false, isolated, false)) == null) {
                    String msg = "Unable to launch app "
                            + r.appInfo.packageName + "/"
                            + r.appInfo.uid + " for service "
                            + r.intent.getIntent() + ": process is bad";
                    Slog.w(TAG, msg);
                    bringDownServiceLocked(r);
                    return msg;
                }
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
  • 一开始判断你这个r是否已经有了app,如果你已经知道了就直接sendServiceArgsLocked 这里第一次是不会的,也就对应我们的service的onCreate只会执行一次,就下面realStartServiceLocked
  • 这里判断是不是isolated 如果不是就直接realStartServiceLocked。如果是就还要绕一大圈。
  • 记住这个mPendingServices
    过程大概是:
    1、startProcessLocked 启动进程,然后会加载一个新的ActivityThread,
    2、然后就会application.attach 就会回到我们AMS的attachApplication
    3、AMS 的 attachApplication 实际上是 attachApplicationLocked
    4、然后又最终我们的ActiveServices 的attachApplicationLocked 如下
    boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
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.versionCode,
                            mAm.mProcessStats);
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                    if (!isServiceNeeded(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.shortName, e);
                throw e;
            }
        }

mPendingServices 是我们刚才记住的。
最终还是会调用realStartServiceLocked

所以在bringUpServiceLocked里面很重要,

  • 1、它判断了你的所要启动的service是否已经有了进程
  • 2、是否你所要启动的service是不是单独的一个孤立进程
  • 3、如果没有进程我还需要给你需要启动的service记录下来,为你启动一个进程,然后等你进程起来以后再给你启动serivice

4.最后回调给应用realStartServiceLocked

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }

        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
//妈的这里壁纸怎么还特殊处理
        if (mAm.mWallpaperClassName != null && r.name.equals(mAm.mWallpaperClassName)) {
            mAm.mWallpaperProcess = app;
        }


        final boolean newService = app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
....

            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 (r.whitelistManager) {
            app.whitelistManager = true;
        }

        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);
...
        sendServiceArgsLocked(r, execInFg, true);

...
    }
  • 1、调用你所需要启动的service的onCreat
  • 2、sendServiceArgsLocked 这个就是发送onStartCommand
    具体怎么调用过去需要看ams和app直接binder的接口流程。
    这样你的service就起来了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沈万三djh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值