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

来源:互联网 发布:董宇阳,知乎 编辑:程序博客网 时间:2024/04/30 21:31

我们一般在写代码的时候,都会通过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方法。

@Overridepublic 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)的原理分析

0 0