Android启动Service流程

其实启动Service和我们上一篇启动App的流程差不多,通过学习老罗的Android系统在新进程中启动自定义服务过程(startService)的原理分析,补充了一些不太清楚的知识点。这里做一下笔记。
老罗的例子,Service是设置了一个android:process属性,表明要在新建的进程运行Service。例子xml代码:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    package="shy.luo.ashmem"  
    android:sharedUserId="android.uid.system"  
    android:versionCode="1"  
    android:versionName="1.0">  
        <application android:icon="@drawable/icon" android:label="@string/app_name">  
            ......  
            <service   
                android:enabled="true"   
                android:name=".Server"  
                android:process=".Server" ><!-- 设置了process属性 -->  
                    <intent-filter>  
                        <action android:name="shy.luo.ashmem.server"/>  
                        <category android:name="android.intent.category.DEFAULT"/>  
                    </intent-filter>  
            </service>  
        </application>  
</manifest>   

在这篇博文中,讲述了ActivityManagerService是在一个ServerThread类(有种熟悉的感觉,ActivityThread,不过没有联系的,哈哈)中启动的,代码如下:

class ServerThread extends Thread {   
    ......  
    @Override  
    public void run() {  
        ......  
        // Critical services...  
        try {  
            ......  
            context = ActivityManagerService.main(factoryTest);  
            ......  
            ActivityManagerService.setSystemProcess();  
            ......  
        } catch (RuntimeException e) {  
            Slog.e("System", "Failure starting core service", e);  
        }  
        ......  
    }  
    ......
}  

调用了ActivityManagerService的main和setSystemProcess方法,我们接着看代码:

public final class ActivityManagerService extends ActivityManagerNative  
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
    ......  
    static ActivityManagerService mSelf;  
    ......  
    public static void setSystemProcess() {  
        try {  
            ActivityManagerService m = mSelf;  
            ServiceManager.addService("activity", m);  
            ......  
        } catch (PackageManager.NameNotFoundException e) {  
            ......  
        }  
    }  
    ......  
    public static final Context main(int factoryTest) {  
        ......  
        ActivityManagerService m = thr.mService;  
        mSelf = m;  
        ......  
    }  
}  

在setSystemProcess方法里,调用了ServiceManager的addService方法,这样ActivityManagerService作为Service注册到ServiceManager中,Client就可以在ServiceManager中获取到ActivityManagerService的代理对象,并与之通信。这样ActivityManagerService就算是“启动”起来了。
当我们通过startService启动Service时,和启动App一样,其实是调用ActivityManagerService代理对象ActivityManagerProxy 的startService方法:

class ActivityManagerProxy implements IActivityManager {  
    ......  
    public ComponentName startService(IApplicationThread caller, Intent service,  
        String resolvedType) 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);  
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);  
        reply.readException();  
        ComponentName res = ComponentName.readFromParcel(reply);  
        data.recycle();  
        reply.recycle();  
        return res;  
    }  
    ......  
}  

参数service是一个Intent实例,它里面指定了要启动的服务的名称,也就是例子定义的服务名称“shy.luo.ashmem.server”了。

参数caller是一个IApplicationThread实例,它是一个在主进程创建的一个Binder对象。在Android应用程序中,每一个进程都用一个ActivityThread实例来表示,而在ActivityThread类中,有一个成员变量mAppThread,它是一个ApplicationThread实例,实现了IApplicationThread接口,它的作用是用来辅助ActivityThread类来执行一些操作(其实mAppThread是ActivityManagerService持有与App进程通信的Binder代理对象,ActivityManagerService利用调用IApplicationThread代理对象,实现通知ActivityThread执行对应的方法),这个我们在后面会看到它是如何用来启动服务的。

参数resolvedType是一个字符串,它表示service这个Intent的MIME类型,它是在解析Intent时用到的。在这个例子中,我们没有指定这个Intent 的MIME类型,因此,这个参数为null。

ActivityManagerProxy类的startService函数把这三个参数写入到data本地变量去,接着通过mRemote.transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒正在等待Client请求的ActivityManagerService进程,最后进入到ActivityManagerService的startService函数中。

接下来就是ActivityManagerService会做一系列检查,然后通过socket方式通知Zygote孵化新的进程,指定新的进程加载ActivityThread类,并执行main方法。代码过程请参考我上一篇博文Android应用App启动流程。这里我们还是着重看一下Service在新的进程启动过程。

先看看ActivityThread的main方法:

public final class ActivityThread {   
    ......  
    public static final void main(String[] args) {  
        ......  
        Looper.prepareMainLooper();  
        ......  
        ActivityThread thread = new ActivityThread();  
        thread.attach(false);  
        ......  
        Looper.loop();  
        ......  
        thread.detach();  
        ......  
    }  
}  

因为这段代码可以带我们了解App的启动和初始化过程,所以很重要。在这里初始化Looper,创建Looper和MessageQueue,然后调用attach方法,把自己的ApplicationThread代理对象通过IPC传给ActivityManagerService,调用Looper.loop方法,让Looper不断的从MessageQueue取出消息,实现消息机制。我们来看看attach方法(上一个博文没有写清楚attach方法,因为不清楚):

public final class ActivityThread {  
    ......  
    private final void attach(boolean system) {  
        ......  
        if (!system) {  
            ......  
            IActivityManager mgr = ActivityManagerNative.getDefault();  
            try {  
                mgr.attachApplication(mAppThread);  
            } catch (RemoteException ex) {  
            }  
        } else {  
            ......  
        }  
        ......  
    }  
    ......  
}  

主要是调用ActivityManagerService的代理对象ActivityManagerProxy的attachApplication的方法:

class ActivityManagerProxy implements IActivityManager {  
    ......  
    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();  
    }  
    ......  
}  

这下应该清楚知道ActivityThread怎么把ApplicationThread的代理对象传给ActivityManagerService了吧。我们顺便往下看,ActivityManagerService调用attachApplication的方法:

public final class ActivityManagerService extends ActivityManagerNative  
                            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
    ......      
    public final void attachApplication(IApplicationThread thread) {  
        synchronized (this) {  
            int callingPid = Binder.getCallingPid();  
            final long origId = Binder.clearCallingIdentity();  
            attachApplicationLocked(thread, callingPid);  
            Binder.restoreCallingIdentity(origId);  
        }  
    }  
    ......  
}  

attachApplicationLocked方法代码:

public final class ActivityManagerService extends ActivityManagerNative  
                        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {    
    ......  
    private final boolean attachApplicationLocked(IApplicationThread thread,  
            int pid) {  
        // Find the application record that is being attached...  either via  
        // the pid if we are running in multiple processes, or just pull the  
        // next app record if we are emulating process with anonymous threads.  
        ProcessRecord app;  
        if (pid != MY_PID && pid >= 0) {  
            synchronized (mPidsSelfLocked) {  
                app = mPidsSelfLocked.get(pid);  
            }  
        } else if (mStartingProcesses.size() > 0) {  
            app = mStartingProcesses.remove(0);  
            app.setPid(pid);  
        } else {  
            app = null;  
        }  
        ......  

        String processName = app.processName;  
        ......  
        app.thread = thread;  
        ......  
        boolean badApp = false;  
        ......  
        // Find any services that should be running in this process...  
        if (!badApp && mPendingServices.size() > 0) {  
            ServiceRecord sr = null;  
            try {  
                for (int i=0; i<mPendingServices.size(); i++) {  
                    sr = mPendingServices.get(i);  
                    if (app.info.uid != sr.appInfo.uid  
                        || !processName.equals(sr.processName)) {  
                            continue;  
                    }  
                    mPendingServices.remove(i);  
                    i--;  
                    realStartServiceLocked(sr, app);  
                    didSomething = true;  
                }  
            } catch (Exception e) {  
                ......  
            }  
        }  
        ......  
        return true;  
    }  
    ......  
}  

最终调用realStartServiceLocked方法:

class ActivityManagerProxy implements IActivityManager {  
    ......  
    private final void realStartServiceLocked(ServiceRecord r,  
            ProcessRecord app) throws RemoteException {  
        ......  
        r.app = app;  
        ......  
        try {  
            ......  
            app.thread.scheduleCreateService(r, r.serviceInfo);  
            ......  
        } finally {  
            ......  
        }  
        ......  
    }  
    ......  
}  

这里的app.thread是一个ApplicationThread的代理对象,通过调用这个代理对象scheduleCreateService方法,通知ActivityThread启动Service,回到App进程。

class ApplicationThreadProxy implements IApplicationThread {  
    ......  
    public final void scheduleCreateService(IBinder token, ServiceInfo info)  
                throws RemoteException {  
        Parcel data = Parcel.obtain();  
        data.writeInterfaceToken(IApplicationThread.descriptor);  
        data.writeStrongBinder(token);  
        info.writeToParcel(data, 0);  
        mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,  
            IBinder.FLAG_ONEWAY);  
        data.recycle();  
    }  
    ......  
}  
public final class ActivityThread {  
    ......  
    private final class ApplicationThread extends ApplicationThreadNative {  
        ......  
        public final void scheduleCreateService(IBinder token,  
        ServiceInfo info) {  
            CreateServiceData s = new CreateServiceData();  
            s.token = token;  
            s.info = info;  
            queueOrSendMessage(H.CREATE_SERVICE, s);  
        }  
        ......  
    }  
    ......  
}  

又见到熟悉的身形了,ApplicationThread作为ActivityThread内部类,直接代用queueOrSendMessage方法,分发消息到ActivityThread的MessageQueue,通知ActivityThread执行对应方法。所以整个Handler的消息机制,在Android中起了大多的作用。整个App运行,都是通过这个消息机制得以和谐运行,表示不禁感叹。上次都没看怎么ApplicationThread怎么分发消息,代码如下:

public final class ActivityThread {  
    ......  
    private final void queueOrSendMessage(int what, Object obj) {  
        queueOrSendMessage(what, obj, 0, 0);  
    }  
    private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {  
        synchronized (this) {  
            ......  
            Message msg = Message.obtain();  
            msg.what = what;  
            msg.obj = obj;  
            msg.arg1 = arg1;  
            msg.arg2 = arg2;  
            mH.sendMessage(msg);  
        }  
    }  
    ......  
}  

很普通代码,通过Handler分发消息。看一下ActivityThread的Handler怎么处理启动Service的代码:

public final class ActivityThread {   
    ......  
    private final class H extends Handler {  
        ......  
        public void handleMessage(Message msg) {  
            ......  
            switch (msg.what) {  
                ......  
                case CREATE_SERVICE:  
                    handleCreateService((CreateServiceData)msg.obj);  
                    break;  
                ......  
            }  
            ......  
        }  
        ......  
    }  
    ......  
}  

调用了handleCreateService方法:

public final class ActivityThread {  
    ......  
    private final 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);  
        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());  
            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.onCreate()方法。至此,启动Service代码分析完毕。跟着老罗的代码解析,的确学习了不少。

参考资料

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值