浅析startService在一个新进程中启动的流程

我们一般在写代码的时候,都会通过startService来启动一个服务,但是服务到底是怎样启动的以及startService到底做了哪些工作呢?现在就来把整个过程进行整理。
我们知道Service的启动是调用了Context对象里面的startService方法,但是Context只是一个抽象类,真正的操作都是在它的实现类ContextImpl中,所以我们直接看ContextImpl里面的startService方法。

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }

我们对其进行跟踪,接着调用了startServiceCommon(service, mUser);

 private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess();
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), 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());
                }
            }
            return cn;
        } catch (RemoteException e) {
            return null;
        }
    }

这里我们要打断一下,先看看ActivityManagerNative.getDefault()干了些什么,所以我们要进入ActivityManagerNative类里面,差个究竟。

    static public IActivityManager getDefault() {
        return gDefault.get();
    }
继续看源码,
  private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

如果看过前面浅析PackageManager的工作流程,应该对ServiceManager.getService(“activity”)这一句代码并不陌生,因为我们的PackageManager也是使用的服务,在那篇文章中,我们获取这个服务是通过ServiceManager.getService(“package”),这样充分的说明了一点:ServiceManager就是一个服务管理者,系统的service需要通过add_service把自己的信息注册到ServiceManager中,这样在需要的时候就会获取到服务。
所以我们可以看到通过ServiceManager.getService(“activity”)可以得到远程服务的Binder对象,下面接着调用了asInterface(b),这句代码大家应该并不陌生,因为我们在编写绑定远程服务的时候就会使用,我直接贴一段小程序,激发一下大家的回忆:

public class MainActivity extends Activity {

    private IManager manager;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("MyService", "onServiceConnected");
            //得到本地代理对象
            manager = IManager.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void bindService(View view) {
        Log.i("MyService", "bindService");
        Intent intent = new Intent("com.newintenttest.startservice.MyService");
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    public void unbindService(View view) {
        unbindService(connection);
    }

    public void caculate(View view){
        if (manager == null) {
            Toast.makeText(this, "请绑定服务", Toast.LENGTH_SHORT).show();
        } else {
            int result = 0;
            try {
                result = manager.add(4, 5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Toast.makeText(this, result + "",Toast.LENGTH_SHORT).show();
        }
    }
}

这段程序来自浅析绑定远程服务bindService基本原理与AIDL分析
我们在调用了bindService(intent, connection, Context.BIND_AUTO_CREATE)后,会回调onServiceConnected方法,这个方法里面有一个IBinder类型的参数,就相当于上面的ServiceManager.getService(“activity”),都是得到远程服务的Binder对象,在上面的代码中接着调用了IManager.Stub.asInterface(service),得到本地代理对象,同理,回过头看看asInterface(b),这里肯定也是得到本地的代理对象,然后就是通过本地代理对象进行操作。
那么我们接着看看ActivityManagerNative的asInterface的操作,就可以看到这个代理对象了。

   static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

我们写代码的时候,这些代码使用AIDL来自动生成的,其实也可以不自动生成,看看浅析绑定远程服务bindService基本原理与AIDL分析就知道了。
好了,这里其实得到的就是ActivityManagerProxy对象。我们回到上面,也就是说ActivityManagerNative.getDefault()返回了一个ActivityManagerProxy对象,接着看看这一整句代码ActivityManagerNative.getDefault().startService,调用了ActivityManagerNative里面的startService。我们进入到ActivityManagerNative类,看看里面的源码。ActivityManagerNative也在ActivityManagerNative.java文件中。

public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeInt(userId);
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        ComponentName res = ComponentName.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return res;
    }

这里调用了mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0),其中mRemote就是ServiceManager.getService(“activity”)返回的Binder对象。

说到这里,如果还是不明白,强烈建议看看浅析绑定远程服务bindService基本原理与AIDL分析这篇文章,看了这篇文章之后,对于这整个过程就可以有一个宏观的理解。

接着会调用ActivityManagerNative里面的onTransact方法。

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
     switch (code) {
      case START_SERVICE_TRANSACTION: {
          data.enforceInterface(IActivityManager.descriptor);
          IBinder b = data.readStrongBinder();
          IApplicationThread app = ApplicationThreadNative.asInterface(b);
          Intent service = Intent.CREATOR.createFromParcel(data);
          String resolvedType = data.readString();
          int userId = data.readInt();
          ComponentName cn = startService(app, service, resolvedType, userId);
          reply.writeNoException();
          ComponentName.writeToParcel(cn, reply);
          return true;
        }
}

从里面可以看到会调用startService(app, service, resolvedType, userId);我们发现在ActivityManagerNative里面没有startService方法,不要急,这个方法肯定存在,我们来看看ActivityManagerNative的子类ActivityManagerService类。

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) {
        enforceNotIsolatedCaller("startService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (DEBUG_SERVICE)
            Slog.v(TAG, "startService: " + service + " type=" + resolvedType);
        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, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

在这个里面调用了mServices.startServiceLocked方法,mServices是什么,在ActivityManagerService的构造函数中,我们可以看到下面一句。

private ActivityManagerService() {

        mServices = new ActiveServices(this);
}

下面我们就要进入ActiveServices类,看看源码:

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

     ServiceLookupResult res =
         retrieveServiceLocked(service, resolvedType,
                 callingPid, callingUid, userId, true, callerFg);
     ........

     return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }

函数首先通过retrieveServiceLocked来解析service这个Intent,就是解析前面我们在AndroidManifest.xml定义的Service标签的intent-filter相关内容,然后将解析结果放在res.record中,后面调用了startServiceInnerLocked方法

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
            ServiceRecord r, boolean callerFg, boolean addToStarting) {
       ProcessStats.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);
        if (error != null) {
            return new ComponentName("!!", error);
        }

        if (r.startRequested && addToStarting) {
            boolean first = smap.mStartingBackground.size() == 0;
            smap.mStartingBackground.add(r);
            r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
            if (DEBUG_DELAYED_SERVICE) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.v(TAG, "Starting background (first=" + first + "): " + r, here);
            } else if (DEBUG_DELAYED_STATS) {
                Slog.v(TAG, "Starting background (first=" + first + "): " + r);
            }
            if (first) {
                smap.rescheduleDelayedStarts();
            }
        } else if (callerFg) {
            smap.ensureNotStartingBackground(r);
        }

        return r.name;
    }

这里调用了bringUpServiceLocked进一步处理。

    private final String bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean execInFg, boolean whileRestarting) {
        ......

        final String procName = r.processName;
        ProcessRecord app;
        ......

        if (app == null) {
            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 (isolated) {
                r.isolatedProc = app;
            }
        }

        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Applying delayed stop (in bring up): " + r);
                stopServiceLocked(r);
            }
        }

        return null;
    }

这里的procName便是我们前面在AndroidManifest.xml文件定义service标签时指定的android:process属性值了,
接着调用startProcessLocked函数来创建一个新的进程,以便加载自定义的Service类。最后将这个ServiceRecord保存在成员变量mPendingServices列表中。
那么mAm.startProcessLocked里面的mAm是什么?
看看ActiveServices的构造函数就知道了。

 public ActiveServices(ActivityManagerService service) {
        mAm = service;
    }

就是调用了ActivityManagerService里面的startProcessLocked方法

private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
      ......

      // Start the process.  It will either succeed and return a result containing
      // the PID of the new process, or else throw a RuntimeException.
      Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
              app.processName, uid, uid, gids, debugFlags, mountExternal,
              app.info.targetSdkVersion, app.info.seinfo, null);

     ......

      synchronized (mPidsSelfLocked) {
          this.mPidsSelfLocked.put(startResult.pid, app);
          Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
          msg.obj = app;
          mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                  ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
            }
    }

这里调用Process.start函数创建了一个新的进程,指定新的进程执行android.app.ActivityThread类。最后将表示这个新进程的ProcessRecord保存在mPidSelfLocked列表中.

在新进程中指定了执行ActivityThread类,下面就直接进入ActivityThread的main函数里面。

public static void main(String[] args) {
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        Security.addProvider(new AndroidKeyStoreProvider());

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        AsyncTask.init();

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
}

在上面创建了一个ActivityThread对象,然后执行了它的attach方法。

    private void attach(boolean system) {

            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        } 
    }

上面又执行了ActivityManagerNative.getDefault()方法,对于这个现在应该不陌生了吧,返回的就是一个ActivityManagerProxy本地代理对象.接着执行mgr.attachApplication(mAppThread)就是执行了ActivityManagerProxy里面的attachApplication方法。
其中mAppThread就是ApplicationThread对象。因为在ActivityThread里面创建了这个对象。
另外ApplicationThread继承自ApplicationThreadNative,ApplicationThreadNative继承自Binder。

final ApplicationThread mAppThread = new ApplicationThread();

接着进入ActivityManagerProxy类查看源码:

public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app.asBinder());
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

调用了ActivityManagerNative里面的onTransant方法。

  public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
         case ATTACH_APPLICATION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IApplicationThread app = ApplicationThreadNative.asInterface(
                    data.readStrongBinder());
            if (app != null) {
                attachApplication(app);
            }
            reply.writeNoException();
            return true;
        }
}

它里面执行了attachApplication方法。同样,这个方法在ActivityManagerNative的子类ActivityManagerService里面。

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

接着跟踪attachApplicationLocked方法

     private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ......
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName);
            } catch (Exception e) {
                badApp = true;
            }
        }
        ......
        return true;
    }

它执行了mServices.attachApplicationLocked函数,mServices就是ActiveServices对象。

       boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
        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, mAm.mProcessStats);
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.w(TAG, "Exception in new application when starting service "
                        + sr.shortName, 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 = null;
            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方法,

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.thread是IApplicatonThread类型,最终将执行ApplicationThreadProxy里的scheduleCreateService方法。

public final void scheduleCreateService(IBinder token, ServiceInfo info,
            CompatibilityInfo compatInfo, int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        info.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        data.writeInt(processState);
        mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

这个现在应该很熟悉了,接着执行ApplicationThreadNative里面的onTransact方法

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {

        case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
            CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
            int processState = data.readInt();
            scheduleCreateService(token, info, compatInfo, processState);
            return true;
        }
    }

接着就执行scheduleCreateService方法。因为ApplicationThreadNative里面没有实现scheduleCreateService这个方法,所以会执行它的子类ApplicationThread里的scheduleCreateService方法。ApplicationThread这个类在ActivityThread.java文件中。

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);
 }

接着会执行sendMessage方法。

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

从定义final H mH = new H()可以看到mH是一个H对象,而H是一个继承自Handler的类。

 private class H extends Handler {
 public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
            case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
                    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 = new ContextImpl();
        context.init(packageInfo, null, this);

        Application app = packageInfo.makeApplication(false, mInstrumentation);
        context.setOuterContext(service);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManagerNative.getDefault());
        //执行了onCreate方法,也就是说我们的onCreate方法是在这里调用的
        service.onCreate();
        mServices.put(data.token, service);
        try {
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, 0, 0, 0);
        } catch (RemoteException e) {
            // nothing to do.
        }
    } 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()就创建了一个服务,data.info.name就是自定义的服务.接着就执行了service.onCreate()方法,对于这个方法应该很熟悉了,原来我们的onCreate方法是在这个地方调用的。

参考文章:
Android系统在新进程中启动自定义服务过程(startService)的原理分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值