bindService流程三

223 阅读3分钟

这篇文章主要讲的是分真正两种情况启动service,一种是service运行的进程和app进程是同一个进程,还有一种是运行在独立进程中。AMS端的调度流程可以参考之前的文章juejin.cn/post/710046…

ActiveServices#bringUpServiceLocked 这个方法会判断service要运行的进程情况,

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        .......
            // step3.1 查找对应的进程
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            // 进程存在
            if (app != null && app.thread != null) {
                try {
                    // step3.2 启动service
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                }
            }
        // 进程未启动
        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {
            // step3.3 启动进程
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                bringDownServiceLocked(r);
                return msg;
            }
        }

        return null;
    }


这是上一篇分析到的地方,下面继续分析后面的流程。

在app进程中运行service - realStartServiceLocked

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ....
        // 添加到app进程的service集合
        final boolean newService = app.services.add(r);
        ....
        try {
            // step1 调用app进程 创建service
            app.thread.scheduleCreateService(r, r.serviceInfo,
         mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
        }
        // step2 请求bind
        requestServiceBindingsLocked(r, execInFg);
        ....
        // step3 调用onStartCommand
        sendServiceArgsLocked(r, execInFg, true);
        ....
    }

step1调用app进程 创建service

调用到ActivityThread内部ApplicationThread bind对象,

// 参数一 对应的是ServiceRecord,后面再传给ams
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;
           // 只是往主线程插入一个消息,AMS就返回了
            sendMessage(H.CREATE_SERVICE, s);
        }

调用到handler H对象。

private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
            // 创建service对象
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
            ....
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            // 调用生命周期oncreate
            service.onCreate();
            mServices.put(data.token, service);
            // 通知ams service创建好了
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            
    }

service的生命周期oncreate就执行了。

step2 请求bind requestServiceBindingsLocked
    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        // 遍历所有的绑定了 该service的client
        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 ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
               // 调用用户进程scheduleBindService
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } 
        }
        return true;
    }

执行到ActivityThread的applicationthread

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;
            // 只是往主线程插入一个消息,AMS就返回了
            sendMessage(H.BIND_SERVICE, s);
        }
        
        
 private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                try {
                    if (!data.rebind) {
                    // 调用service的生命周期onBind
                        IBinder binder = s.onBind(data.intent);
                        // step3 将binder发布到ams
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        // 生命周期onRebind,跟我们本次讨论的关系不大
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                }
            } 
        }
    }

调用了service的onBind 获取到binder对象,并发布到ams。

step3 将binder发布到ams
public void publishService(IBinder token, Intent intent, IBinder service) {

        synchronized (this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            //ActiveServices#publishServiceLocked,直接强转得到ServiceRecord
            mServices.publishServiceLocked((ServiceRecord) token, intent, service);
        }
    }

ActiveServices#publishServiceLocked

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        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;
                    for (int conni = r.connections.size() - 1; conni >= 0; conni--) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                        for (int i = 0; i < clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                           
                            try {
                                // 调用IServiceConnection的connected
                                c.conn.connected(r.name, service, false);
                            } 
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } 
    }

ams根据token找到对应的ServiceRecord,遍历调用IServiceConnection的connected。IServiceConnection是之前app端实现的ServiceDispatcher,可参考juejin.cn/post/710007…

ServiceDispatcher的定义,内部持有ServiceDispatcher.InnerConnection的binder对象,用于进程间通信,回调的就是 InnerConnection#connected方法

static final class ServiceDispatcher {
        private final ServiceDispatcher.InnerConnection mIServiceConnection;
        private final Handler mActivityThread;

        ServiceDispatcher(ServiceConnection conn,
                Context context, Handler activityThread, int flags) {
            //mIServiceConnection 是InnerConnection类型
            mIServiceConnection = new InnerConnection(this);
            mConnection = conn;
            mContext = context;
            mActivityThread = activityThread;
        }
        // 实现了IServiceConnection.Stub的binder对象,
        private static class InnerConnection extends IServiceConnection.Stub {
            // 持有ServiceDispatcher的弱引用
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }

            public void connected(ComponentName name, IBinder service, boolean dead)
                    throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service, dead);
                }
            }
        }
        
        public void connected(ComponentName name, IBinder service, boolean dead) {
            // mActivityThread是 ActivityThread中的handler H
            if (mActivityThread != null) {
                // 分支step 3.1
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }

connected内部又调用了ServiceDispatcher的connected方法。方法内判断mActivityThread是否为空,从之前的 juejin.cn/post/710007… bindService流程一文章可见,mActivityThread不为空,就等于ActivityThread中的handler H对象。所以进入上面的分支step 3.1 给handler发送了一个runnable -- RunConnection。代码如下:

private final class RunConnection implements Runnable {
            RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
                mName = name;
                mService = service;
                mCommand = command;
                mDead = dead;
            }

            public void run() {
                if (mCommand == 0) {
                    doConnected(mName, mService, mDead);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

            final ComponentName mName;
            final IBinder mService;
            final int mCommand;
            final boolean mDead;
        }

看看构造函数和run方法。入参mCommand = 0,mDead = false 所以执行doConnected方法。


static final class ServiceDispatcher {
private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
            = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
            
public void doConnected(ComponentName name, IBinder service, boolean dead) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
                old = mActiveConnections.get(name);

                if (service != null) {
                    // 创建ConnectionInfo,保存到mActiveConnections
                    info = new ConnectionInfo();
                    info.binder = service;
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
                        mActiveConnections.put(name, info);
                    } 
                }
            }

            // If there is a new viable service, it is now connected.
            if (service != null) {
                // 回调bindservice时提供的ServiceConnected接口
                mConnection.onServiceConnected(name, service);
            } 
        }
}

到这里回调到回调bindservice时提供的ServiceConnected接口的onServiceConnected,这个方法里我们可以获取到service的代理对象。

启动新的进程运行service - mAm.startProcessLocked

我们在下一篇中继续分析启动新进程运行service。

参考资料: www.jianshu.com/p/18e4efa2e… www.jianshu.com/p/f2db0f58d…