Service

Posted ayanwan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Service相关的知识,希望对你有一定的参考价值。

相关源码目录

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
/frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java
/frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
/frameworks/base/core/java/android/app/IActivityManager.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java (内含ActivityManagerProxy类)
/frameworks/base/core/java/android/app/ActivityManager.java

/frameworks/base/core/java/android/app/IApplicationThread.java
/frameworks/base/core/java/android/app/ApplicationThreadNative.java (内含ApplicationThreadProxy类)
/frameworks/base/core/java/android/app/ActivityThread.java (内含ApplicationThread类)

/frameworks/base/core/java/android/app/ContextImpl.java


先看Service与AMS的UML图:


(1)ActivityManagerService是Android的Java framework的服务框架最重要的服务之一。对于Andorid的Activity、Service、Broadcast、ContentProvider四剑客的管理,包含其生命周期都是通过ActivityManagerService来完成的。

(2)ActivityThread,App的真正入口,其中有一个main()用于开启消息循环线程,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作;
(3)ApplicationThread。简单的说就是应用进程需要调用ActivityManagerService提供的功能,而ActivityManagerService也需要主动调用应用进程以控制应用进程并完成指定操作。这样ActivityManagerService也需要应用进程的一个Binder代理对象,而这个代理对象就是ApplicationThreadProxy对象。

(4)ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。


我们在来看一下Service的生命周期图。 


1、startService分析

启动服务的流程图:


图中涉及的首字母缩写:

AMP:ActivityManagerProxy

AMN:ActivityManagerNative

AMS:ActivityManagerService

AT:ApplicationThread

ATP:ApplicationThreadProxy

ATN:ApplicationThreadNative


startService与startActivity流程及其相似,这里就不重复了。


2、bindService分析

启动服务的流程图:


        上图仅仅是一个简化的流程图,因为图中没有出现zygote,ActvityThread#main等关键流程,就是生命周期中onCreate()的回掉过程。这一部分与startService是一致的。下面先分析这一部分内容。

2.1  onCreate()会调过程

2.1.1  ActiveServices#bringUpServiceLocked

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

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

        if (!isolated) 
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) 
                try 
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                 catch (RemoteException e) 
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            
         else 
            // If this service runs in an isolated process, then each time
            // we call startProcessLocked() we will get a new isolated
            // process, starting another process if we are currently waiting
            // for a previous process to come up.  To deal with this, we store
            // in the service any current isolated process it is running in or
            // waiting to have come up.
            app = r.isolatedProc;
        

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        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_STARTS) Slog.v(TAG, "Applying delayed stop (in bring up): " + r);
                stopServiceLocked(r);
            
        

        return null;
    

2.1.2  ActivityManagerService#startProcessLocked
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) 
            ...

            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);//关键
            checkTime(startTime, "startProcess: returned from zygote!");

           ....
    
Process.start的第一个参数entryPoint = "android.app.ActivityThread";这就是启动ActivityThread.main的过程。

2.1.3  Process#start

public static final ProcessStartResult start(…… ) 
       return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, targetSdkVersion, zygoteArgs);



//Starts a new process via the zygote mechanism.
private static ProcessStartResult startViaZygote(…… )

       synchronized(Process.class) 
              ArrayList<String> argsForZygote = new ArrayList<String>();
              //参数设置
              // --runtime-init, --setuid=, --setgid=,……
        //--runtime-init这里决定上面所提到创建新的进程的启动方式
              argsForZygote.add("--runtime-init");         
              argsForZygote.add("--setuid=" + uid);
              argsForZygote.add("--setgid=" + gid);
              //……

              argsForZygote.add(processClass);
              for (String arg : extraArgs) 
                  argsForZygote.add(arg);
                 
              return zygoteSendArgsAndGetResult(argsForZygote);
       


//Sends an argument list to the zygote process, which starts a new child
//and returns the child's pid
private static ProcessStartResult zygoteSendArgsAndGetResult
    (ArrayList<String> args)

       //open socket to Zygote process if not already open
       openZygoteSocketIfNeeded();

       //write Argument
       sZygoteWriter.write(Integer.toString(args.size()));
       sZygoteWriter.newLine();
       sZygoteWriter.flush();
       ……

       通过上面这一段代码,向Zygote发送创建进程的请求,设置相关的参数。其中有argsForZygote.add("--runtime-init"); 决定新创建进程的启动方式为RuntimeInit.zygoteInit方式启动:找到目标类main函数执行。

       接下去的流程就是AMP进行attach操作, 再调到AS.realStartServiceLocked,进而完成Service.onCreate()回调。

2.1.4 ActiveServices#realStartServiceLocked

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException 
    ...
    r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    final boolean newService = app.services.add(r);

    //发送delay消息
    bumpServiceExecutingLocked(r, execInFg, "create");
    boolean created = false;
    try 
        ...
        mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        //服务进入 onCreate() 
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
     catch (DeadObjectException e) 
        mAm.appDiedLocked(app); //应用死亡处理
        throw e;
     finally 
        if (!created) 
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            if (newService) 
                app.services.remove(r);
                r.app = null;
            
            //尝试重新启动服务
            if (!inDestroying) 
                scheduleServiceRestartLocked(r, false);
            
        
    
    
    requestServiceBindingsLocked(r, execInFg);  //关键,进行onBind的回调
    updateServiceClientActivitiesLocked(app, null, true);

    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) 
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                null, null));
    

    sendServiceArgsLocked(r, execInFg, true);
    if (r.delayed) 
        getServiceMap(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    
    ...

app.thread.scheduleCreateService就是ApplicationThreadProxy.scheduleCreateService,进而进入ApplicationThread服务的对应方法中,

2.1.5  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);
通过handler机制, 将H.CREATE_SERVICE消息发送给远程服务进程的主线程的handler来处理。
private void handleCreateService(CreateServiceData data) 
    //当应用处于后台即将进行GC,而此时被调回到活动状态,则跳过本次gc。
    unscheduleGcIdler();
    LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);

    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    //通过反射创建目标服务对象
    Service service = (Service) cl.loadClass(data.info.name).newInstance();
    ...

    try 
        //创建ContextImpl对象
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
        //创建Application对象
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManagerNative.getDefault());
        //调用服务onCreate()方法
        service.onCreate();
        mServices.put(data.token, service);
        //调用服务创建完成
        ActivityManagerNative.getDefault().serviceDoneExecuting(
                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
     catch (Exception e) 
        ...
    


2.2 onBind() 回调

        还记得2.1.4中的 requestServiceBindingsLocked(r, execInFg)方法么,该方法进行了onBind的回调。

2.2.1 ActiveServices#requestServiceBindingsLocked

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
        throws TransactionTooLargeException 
    for (int i=r.bindings.size()-1; i>=0; i--) 
        IntentBindRecord ibr = r.bindings.valueAt(i);
        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) 
            break;
        
    

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException 
    if (r.app == null || r.app.thread == null) 
        return false;
    
    
    if ((!i.requested || rebind) && i.apps.size() > 0) 
        try 
            //发送bind开始的消息
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //服务进入 onBind() 
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState);
            if (!rebind) 
                i.requested = true;
            
            i.hasBound = true;
            i.doRebind = false;
         catch (TransactionTooLargeException e) 
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            throw e;
         catch (RemoteException e) 
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            return false;
        
    
    return true;
2.2.2  ATP#scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,
        int processState) throws RemoteException 
    Parcel data = Parcel.obtain();
    data.writeInterfaceToken(IApplicationThread.descriptor);
    data.writeStrongBinder(token);
    intent.writeToParcel(data, 0);
    data.writeInt(rebind ? 1 : 0);
    data.writeInt(processState);
 
    mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
            IBinder.FLAG_ONEWAY);
    data.recycle();
ATN#onTransact
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException 
    switch (code) 
    case SCHEDULE_BIND_SERVICE_TRANSACTION: 
        data.enforceInterface(IApplicationThread.descriptor);
        IBinder token = data.readStrongBinder();
        Intent intent = Intent.CREATOR.createFromParcel(data);
        boolean rebind = data.readInt() != 0;
        int processState = data.readInt();
        //【见流程13】
        scheduleBindService(token, intent, rebind, processState);
        return true;
    
    ...
AT#scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) 
    updateProcessState(processState, false);
    BindServiceData s = new BindServiceData();
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;
    
    sendMessage(H.BIND_SERVICE, s);
        最终,通过handler机制, 将H.BIND_SERVICE消息发送给远程服务进程的主线程的handler来处理
2.2.3  AT#handleBindService
private void handleBindService(BindServiceData data) 
    Service s = mServices.get(data.token);
    if (s != null) 
        try 
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            
            if (!data.rebind) 
                // 执行Service.onBind()回调方法
                IBinder binder = s.onBind(data.intent);
                //将onBind返回值传递回去
                ActivityManagerNative.getDefault().publishService(
                        data.token, data.intent, binder);
             else 
                s.onRebind(data.intent);
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            
            ensureJitEnabled();
         catch (Exception e) 
            ...
        
    

2.3 bindService的调用关系如下:(省略了onCreate回调的流程)

CW.bindService
    CI.bindService
        CI.bindServiceCommon
            AMP.bindService
                AMS.bindService
                    AS.bindServiceLocked
                        AS.retrieveServiceLocked
                        SR.retrieveAppBindingLocked
                        AS.bringUpServiceLocked
                            AS.realStartServiceLocked
                                ATP.scheduleCreateService
                                    AT.scheduleCreateService
                                        AT.handleCreateService
                                            Service.onCreate()
                                            AMP.serviceDoneExecuting
                                                AMS.serviceDoneExecuting
                                requestServiceBindingsLocked
                                    requestServiceBindingLocked
                                         ATP.scheduleBindService
                                             AT.scheduleBindService
                                                AT.handleBindService
                                                    Service.onBind()
                                                    AMP.publishService
                                                        AMS.publishService
                                                            AS.publishServiceLocked
                                                                IServiceConnection.Stub.Proxy.connected
                                                                    InnerConnection.connected
                                                                        ServiceDispatcher.connected
                                                                            RunConnection.run
                                                                                ServiceDispatcher.doConnected
                                                                                    ServiceConnection.onServiceConnected
                                                    AMP.serviceDoneExecuting
                                                        AMS.serviceDoneExecuting



如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!


以上是关于Service的主要内容,如果未能解决你的问题,请参考以下文章

前端三剑客HTML+CSS+JavaScript

01-09 Linux三剑客-awk

文本处理三剑客之sed

华为云-三剑客之PaaS云服务

Web Service 部分内容简述

读取微软三剑客的内容创建信息