彻底弄懂Service启动过程

看完 Activity 的启动过程,发现 Service 的启动过程相对来说就比较简单了。

要说起启动过程,就得从 startService 开始:

1.startService

根据源码的跳转,发现跳转到 ContextWrapper 这个类中,代码如下:

@Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
复制代码

其中 mBase 是类型是:Context 类型,如下:

public class ContextWrapper extends Context {
    Context mBase;
    ......
}
复制代码

而我们又知道 Context 是一个抽象类 ,实现者是 ContextImpl ,所以我们应该是查看ContextImpl 这个类中的 startService(service) 方法。

ContextImpl 中的方法定义如下:

@Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
复制代码

startService 中又调用了 startServiceCommon(service,(requirForeground:false),mUser) 这个方法,继续跟进:

2.startServiceCommon

startServiceCommon 方法如下:

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
          //校验要启动的service
            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();
        }
    }
复制代码

这里面有几个需要说明一下:

  • ActivityManager.getService() 点进去查看
/**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
复制代码

首先是返回的类型是 IActivityManager 类型,其中在create 方法中,拿到远程服务的Binder 对象,其中IActivityManager.Stub.asInterface(b) 不知道大家有没有想起AIDL 这就很熟悉了,就是拿到远程服务的代理对象:IActivityManager,通过代理对象调用远程的方法,是应用进程与服务进程通信的媒介,如果没猜错的话就是在ActivityManagerService 中实现了,查看ActivityManagerService 类:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
.....
}
复制代码

果然不出所料,AMS extend IActivityManager.Stub .

  • mMainThread.getApplicationThread() 首先明白 mMainThreadActivityThread 类的实例变量,通过getApplicationThread() 方法拿到一个 ApplicationThread 类的实例:
public ApplicationThread getApplicationThread()
    {
        return mAppThread;
    }
复制代码

ApplicationThread 类定义如下:

private class ApplicationThread extends IApplicationThread.Stub {
.....
}
复制代码

发现 ApplicationThreadActivityThread 的一个内部类.并且实现了 IApplicationThread.Stub ,而我们又把这个类型传入给了AMS,相当于远程服务拿到了一个访问应用进程的代理,类型为:IApplicationThread

总结:到目前为止,客户端拿到了远程服务的代理(IActivityManager), 服务端拿到了客户端的代理(IApplicationThread),它们互相拿到各自进程的代理类,是它们进行进程间通信的基础。

ok ,我们回到最初那个地方:

ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
复制代码

通过前面的分析我们知道:ActivityManager.getService(). 实际就是 AMS 远程代理,最终在AMS 中完成,我们去 AMS 代码中查看下 startService 代码:

3.ActivityManagerService. 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 {
                // 又调用了startServiceLocked 方法
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }
复制代码

startServiceLocked 方法很复杂,大概如下:

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

.....
ServiceRecord r = res.record;//启动service的信息保存在 serviceRecord 中
....
   ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
.....
}
复制代码

内部又调用了:startServiceInnerLocked 方法

4.startServiceInnerLocked

如下:

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
  String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
}
复制代码

又调用: bringUpServiceLocked

5.bringUpServiceLocked

 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
....

realStartServiceLocked(r, app, execInFg);
}
复制代码

而后又调用了 realStartServiceLocked(r, app, execInFg);

6.realStartServiceLocked

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
      ....
          app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
      ....
}

复制代码

其中 app.threadIApplicationThread 类型,就是远程调用客户端进程里的方法,scheduleCreateService ,而我们又知道 ApplicationThread 实现了 IApplicationThread,所以就查看 ApplicationThread 类中的 scheduleCreateService方法,前面我们说过ApplicationThreadActivityThread 的一个内部类,查看:

7.ApplicationThread.scheduleCreateService

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 的消息,HHandle,继续查看: handleMessage 方法

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);
          //创建context
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
          //创建Application
            Application app = packageInfo.makeApplication(false, mInstrumentation);
  //通过attach 方法,将context application ,service 连接起来
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
          //调用service oncreate方法
            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);
            }
        }
    }
复制代码

service.onCreate(); ok ,调用了 onCreate 方法,至此,service的启动过程的就完成了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值