0
点赞
收藏
分享

微信扫一扫

Android 10 Service 工作过程

深夜瞎琢磨 2021-09-29 阅读 62
Android

本次源码分析是熟悉Service启动过程,让我们对Service的工作原理有进一步的了解。Service分为启动过程和绑定过程,启动状态执行后台计算,绑定状态是其他组件与Service交互。这两种状态可以同时存在。

startService 过程

现在我们开始分析startService启动过程,下图是启动过程的时序图,如图:



当我们调用startService方法时候,紧接着都会调用startServiceCommon,我们来看看这个方法做了哪些事情。

 private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        ...
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
         ...
    }

上述代码看出,直接调用了AMS的startService,在此方法中引入了mServices这个引用实则是ActiveServices类,它是辅助AMS进行Service管理,主要包括启动、绑定和停止等。接着开始调用ActiveServices的startServiceLocked方法。

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
                                      String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ...
        synchronized (this) {
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        }
        ...
    }

进入startServiceLocked后我们发现,解析了service且把Service信息封装到了ServiceRecord中,然后在调用startServiceInnerLocked方法。

 ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            final int userId, boolean allowBackgroundActivityStarts)
            throws TransactionTooLargeException {
        ...
        //1
        ServiceLookupResult res =
            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
        
        ServiceRecord r = res.record;
        ...
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

在上述代码标记1)解析参数service里面的数据,获取到对应的Service信息并且封装到ServiceRecord,每个Service都有一个ServiceRecord对象,都像Activity都有一个ActivityRecord。ServiceRecord继承Binder可以进程之间通讯。在调用startServiceInnerLocked后接着有调用了bringUpServiceLocked方法。

   private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                                        boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //1
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        //2
        final String procName = r.processName;
        HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
        ProcessRecord app;

        if (!isolated) {
            //3
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            //4
            if (app != null && app.thread != null) {
                app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                realStartServiceLocked(r, app, execInFg);
                return null;
            }
        }
        //5
        if (app == null && !permissionsReviewRequired) {
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, false, isolated, false)) == null) {
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
        return null;
    }

在上述代码标记
1)多次调用startService会多次调用onStartCommand 后面不在执行。
2)描述service需要在那个进程运行,AndroidManifest.xml设置的android:process属性来开启进程。
3)查询service对应的ProcessRecord类型的app。
4)发现有对应的进程都开始执行创建Service。
5)当没有发现有service运行的进程,都需要重新创建进程。
我们分析的是Service创建流程,接下来都应该执行方法realStartServiceLocked。

 private final void realStartServiceLocked(ServiceRecord r,
                                              ProcessRecord app, boolean execInFg) throws RemoteException {
        //1
        r.setProcess(app);
        boolean created = false;
        //2
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                app.getReportedProcState());
        created = true;
        //3
       sendServiceArgsLocked(r, execInFg, true);
     }

1)ServiceRecord绑定进程。
2)这里开始执行创建Service过程。
3)执行onStartCommand过程,接下来会分析。
我们现在分析创建Service过程,从代码可以看出,我们马上都要跨进程到ApplicationThread调用scheduleCreateService这个方法。此方法里面通过H继承Handler发送了CREATE_SERVICE消息到ActivityThread执行创建Service。

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

最后代码执行到了ActivityThread的handleCreateService方法里面。

 private void handleCreateService(CreateServiceData data) {
        //创建对象
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            ClassLoader cl = packageInfo.getClassLoader();
            //创建service对象
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        } catch (Exception e) {}
        try {
            //创建上下文
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            //关联service对象
            context.setOuterContext(service);
            //获取Application对象
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //关联上下文和Application对象
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            //data.token都是ServiceRecord,它是binder对象,token与service建立映射关系存储在mServices的map中
            mServices.put(data.token, service);
        } catch (Exception e) {}
    }

通过上述代码,我们可以看出创建了Service对象,创建上下文,然后service调用attach关联Application和上下文,最后调用创建onCreate。mServices是一个ArrayMap,用来存储service对象,ServiceRecord为key值。
接下来我们分析上面提到的sendServiceArgsLocked方法,调用了scheduleServiceArgs方法。

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
                                             boolean oomAdjusted) throws TransactionTooLargeException {
        r.app.thread.scheduleServiceArgs(r, slice);
    }

我们在ApplicationThread找了scheduleServiceArgs方法,里面通过H发送SERVICE_ARGS消息到ActivityThread,调用了handleServiceArgs方法。

 private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                if (!data.taskRemoved) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }
            } catch (Exception e) {
            }
        }
    }

获取ServiceRecord对应的Service,并且调用了onStartCommand方法。
到此我们把Service的启动流程都分析完了

bindService 过程

我们分析bindService过程。我们先来看一张序列图,如图所示:



当我们在调用bindService后,接着调用了bindServiceCommon方法,

  private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                                      String instanceName, Handler handler, Executor executor, UserHandle user) {
        IServiceConnection sd;
        if (mPackageInfo != null) {
            // 1 
            if (executor != null) {
                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
            } else {
                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
            }
        }
        try {
            //此token都是AMS创建ActivityRecord创建
            IBinder token = getActivityToken();
            if (token == null && (flags & BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            service.prepareToLeaveProcess(this);
            int res = ActivityManager.getService().bindIsolatedService(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

  private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
            Context context, Handler handler, Executor executor, int flags) {
        synchronized (mServices) {
            ServiceDispatcher sd = null;
            //根据启动者的context获取arrayMap
            ArrayMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                sd = map.get(c);
            }
            if (sd == null) {
                //创建ServiceDispatcher对象,此类是ServiceConnection和InnerConnection桥梁,
                if (executor != null) {
                    sd = new ServiceDispatcher(c, context, executor, flags);
                } else {
                    sd = new ServiceDispatcher(c, context, handler, flags);
                }
                if (map == null) {
                    map = new ArrayMap<>();
                    mServices.put(context, map);
                }
                //ServiceConnection与ServiceDispatcher建立映射关系
                map.put(c, sd);
            } else {
                sd.validate(context, handler, executor);
            }
            return sd.getIServiceConnection();
        }
    }

在标记1)处创建IServiceConnection对象,调用getServiceDispatcherCommon方法作用是将ServiceConnection对象封装成IServiceConnection类型的sd引用,IServiceConnection类实现了Binder机制,这样的封装都是为了支持跨进程。当我们Service绑定成功后会回调ServiceConnection这个类的方法,此类无法跨进程使用,所以必须封装成支持跨进程的IServiceConnection。我们继续调用AMS的bindIsolatedService方法,然后调用了mServices(提到过的ActiveServices)的bindServiceLocked方法。

 int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String instanceName, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        //创建ServiceRecord对象,这个类继承Binder
        ServiceLookupResult res =
            retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
                    callerFg, isBindExternal, allowInstant);
        ServiceRecord s = res.record;
        try {
            //1
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            //2
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent,
                    callerApp.uid, callerApp.processName, callingPackage);
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                //3
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }
            if (s.app != null && b.intent.received) {
                try {
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {
                }
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    //4
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                //5
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return 1;
    }

1)应用进程通过Intent来绑定Service,AppBindRecord是Service和应用程序进程桥梁。
2)ConnectionRecord 用于描述应用进程和Service建立一次通信。
3)这都是我们创建Service的过程,创建流程已经写过。
4)首先设置onUnbind返回值true,当我们startService--bindService--unBindService--bindService都会调用onRebind。
5)我们第一次调用bindService都走的是第五步。
我们接着看requestServiceBindingLocked方法,又走到ApplicationThread的scheduleBindService方法。

 private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.getReportedProcState());
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
             
            } catch (RemoteException e) {
            }
        }
        return true;
    }

通过H发送BIND_SERVICE到主线程管理类ActivityThread,然后执行handleBindService这个方法。

private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                     //1
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                       ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                       //2
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
            }
        }
    }

1)在bindServiceLocked方法提到的走的第5步,调用绑定onBind方法,并且再次调用AMS的publishService方法中去。
2)在bindServiceLocked方法提到的走的第4步,解绑后的重新绑定调用onRebind方法。
接下来我们再去看看publishService方法,调用了ActiveServices的publishServiceLocked方法。

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        try {
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                    for (int conni = connections.size() - 1; conni >= 0; conni--) {
                        ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
                                continue;
                            }
                            try {
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

走到这里都明白了,这里是准备bind回调,connected方法跨进程调用了这个类IServiceConnection的connected,然后调用了ServiceDispatcher的connected方法

    //ServiceDispatcher.java
    public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityExecutor != null) {
                mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
            } else if (mActivityThread != null) {
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }
     private final class RunConnection implements Runnable {
            public void run() {
                if (mCommand == 0) {
                    doConnected(mName, mService, mDead);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }
        }
     public void doConnected(ComponentName name, IBinder service, boolean dead) {
            if (service != null) {
                mConnection.onServiceConnected(name, service);
            } else {
                mConnection.onNullBinding(name);
            }
        }

上述代码看出最终调用了ServiceConnection的onServiceConnected方法。
上面都是所有分析bindService的过程。

举报

相关推荐

0 条评论