2019-04-26 bindService 源码分析

2019-04-26  本文已影响0人  猫KK

上一篇分析了 startService 的流程,这一篇来分析 bindService 的流程,先上一个时序图:


bindService-时序图.png

接下来看代码

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

很熟悉,有进到 mBase 中,也就是 ContextImpl 中

    
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
    }

    
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;
        //.....

            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);

            //......
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            
    }

调用自身的方法,最后到达 ActivityManagerService 中的 bindService 方法中,值得注意的是 IServiceConnection 对象实例是ServiceDispatcher.InnerConnection,继续到AMS中

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        
    }

走到 ActiveServices 中的 bindServiceLocked 方法

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {

            //..... 

            //判断 flags 是否为 BIND_AUTO_CREATE 
            //如果 flags 为 BIND_AUTO_CREATE 则会调用 bringUpServiceLocked
            //也就是启动 Service 并调用onCreate 方法
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }

            //判断是否已经接受到received
            //这个状态会在 bindService 成功后置为true
            //当前刚进来,所以为false
            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }

                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                //所以走这个方法
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }
        return 1;
    }

上面,值得注意的就是:当bindService是设置flags为BIND_AUTO_CREATE时,会自己创建Service 并调用onCreate方法,假如没有设置这个flags,Service是不能启动的。接下来继续看

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        //.....
       
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
               
        return true;
    }

又回到 ApplicationThread 中的 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;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }

很熟悉,又是 sendMessage,直接看

    case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

又到 ActivityThread 中的 handleBindService 方法中

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
                     //记得前面的 rebind 参数为false
                    if (!data.rebind) {
                        //调用Service的 onBind 方法
                        IBinder binder = s.onBind(data.intent);
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
    }

这里,调用了 Service的 onBind 方法,之后又通过AMS调用 publishService 方法

    public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

有去到 ActiveServices 中

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
                
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    //设置前面说的 received 值
                    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++) {
                                //c.conn为 IServiceConnection 
                                //还记得前面说的 IServiceConnection 的实例为 ServiceDispatcher.InnerConnection
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                                Slog.w(TAG, "Failure sending service " + r.name +
                                      " to connection " + c.conn.asBinder() +
                                      " (in " + c.binding.client.processName + ")", e);
                            }
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

最后调用 ServiceDispatcher.InnerConnection 的 connected 方法

    public void connected(ComponentName name, IBinder service, boolean dead)
                    throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service, dead);
                }
            }

又走到 LoadedApk.ServiceDispatcher 的 connected 方法中

    public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityThread != null) {
                //走这里
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }

熟悉Hander的机制就知道会走到 RunConnection 的run方法中

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

又到 doConnected 方法中

    public void doConnected(ComponentName name, IBinder service, boolean dead) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            //.....
            if (service != null) {
                //到这里
                mConnection.onServiceConnected(name, service);
            } else {
                // The binding machinery worked, but the remote returned null from onBind().
                mConnection.onNullBinding(name);
            }
        }

最后走到 mConnection 的 onServiceConnected 方法中,就是在bindService时候传过来的 ServiceConnection

到这里 bindService 流程就走完了,需要注意的是,这只是流程,没有多少细节

上一篇 下一篇

猜你喜欢

热点阅读