Android8.0.0-r4 ——Service的绑定过程


可以通过调用Context的startService来启动Service,也可以通过Context的bindService来绑定Service

下面是Service的绑定过程

1.ContextWrapper.bindService

代码路径:/frameworks/base/core/java/android/content/ContextWrapper.java

 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/content/ContextWrapper.java)

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

用bindService方法来绑定Service,它的实现在ContextWrapper中


2.ContextImpl.bindService

代码路径:/frameworks/base/core/java/android/app/ContextImpl.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/ContextImpl.java)
1537    @Override
1538    public boolean bindService(Intent service, ServiceConnection conn,
1539            int flags) {
1540        warnIfCallingFromSystemProcess();
1541        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
1542                Process.myUserHandle());
1543    }

在bindService方法中,又return了bindServiceCommon方法

3.ContextImpl.bindServiceCommon

代码路径:/frameworks/base/core/java/android/app/ContextImpl.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/ContextImpl.java)

1581    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
1582            handler, UserHandle user) {
1583        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
1584        IServiceConnection sd;
1585        if (conn == null) {
1586            throw new IllegalArgumentException("connection is null");
1587        }
1588        if (mPackageInfo != null) {
1589            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
1590        } else {
1591            throw new RuntimeException("Not supported in system context");
1592        }
1593        validateServiceIntent(service);
1594        try {
1595            IBinder token = getActivityToken();
1596            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
1597                    && mPackageInfo.getApplicationInfo().targetSdkVersion
1598                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1599                flags |= BIND_WAIVE_PRIORITY;
1600            }
1601            service.prepareToLeaveProcess(this);
1602            int res = ActivityManager.getService().bindService(
1603                mMainThread.getApplicationThread(), getActivityToken(), service,
1604                service.resolveTypeIfNeeded(getContentResolver()),
1605                sd, flags, getOpPackageName(), user.getIdentifier());
1606            if (res < 0) {
1607                throw new SecurityException(
1608                        "Not allowed to bind to service " + service);
1609            }
1610            return res != 0;
1611        } catch (RemoteException e) {
1612            throw e.rethrowFromSystemServer();
1613        }
1614    }

在bindServiceCommon方法中会在1602行调用ActivityManageService(AMS)的代理对象的bindService方法,最终会调用AMS的bindService方法

这里与Android 7.0代码的逻辑有些不同,Android 7.0是通过ActivityManagerNative的getDefault来获取AMS的代理对象,现在这个逻辑封装到了ActivityManager中而不是ActivityManagerNative中


4.ActivityManagerService.bindService

代码路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java)

18275    public int bindService(IApplicationThread caller, IBinder token, Intent service,
18276            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
18277            int userId) throws TransactionTooLargeException {
18278        enforceNotIsolatedCaller("bindService");
18279
18280        // Refuse possible leaked file descriptors
18281        if (service != null && service.hasFileDescriptors() == true) {
18282            throw new IllegalArgumentException("File descriptors passed in Intent");
18283        }
18284
18285        if (callingPackage == null) {
18286            throw new IllegalArgumentException("callingPackage cannot be null");
18287        }
18288
18289        synchronized(this) {
18290            return mServices.bindServiceLocked(caller, token, service,
18291                    resolvedType, connection, flags, callingPackage, userId);
18292        }
18293    }

在18290行bindService方法最后会调用ActiveServices类型的对象mServices的bindServiceLocked方法


5.ActiveServices.bindService

代码路径:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java)

1228    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
1229            String resolvedType, final IServiceConnection connection, int flags,
1230            String callingPackage, final int userId) throws TransactionTooLargeException {
         .........................................
1435
1436            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
1437                s.lastActivity = SystemClock.uptimeMillis();
1438                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
1439                        permissionsReviewRequired) != null) {
1440                    return 0;
1441                }
1442            }
1443
             ...........................................
1461
1462            if (s.app != null && b.intent.received) {
1463                // Service is already running, so we can immediately
1464                // publish the connection.
1465                try {
1466                    c.conn.connected(s.name, b.intent.binder, false);
1467                } catch (Exception e) {
1468                    Slog.w(TAG, "Failure sending service " + s.shortName
1469                            + " to connection " + c.conn.asBinder()
1470                            + " (in " + c.binding.client.processName + ")", e);
1471                }
1472
1473                // If this is the first app connected back to this binding,
1474                // and the service had previously asked to be told when
1475                // rebound, then do so.
1476                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
1477                    requestServiceBindingLocked(s, b.intent, callerFg, true);
1478                }
1479            } else if (!b.intent.requested) {
1480                requestServiceBindingLocked(s, b.intent, callerFg, false);
1481            }
1482
1483            getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
1484
1485        } finally {
1486            Binder.restoreCallingIdentity(origId);
1487        }
1488
1489        return 1;
1490    }
在1438行会bringUpServiceLocked方法,在bringUpServiceLocked方法中又会调用realStartServiceLocked方法,最终由ActivityThread来调用Service的onCreate方法启动Service

在1462行s.app != null 表示Service已经运行,其中s是ServiceRecord类型对象,app是ProcessRecord类型对象。b.intent.received表示当前应用程序进程的Client端已经接收到绑定Service时返回的Binder,这样应用程序进程的Client端就可以通过Binder来获取要绑定的Service的访问接口。

在1466行调用c.conn的connected方法,其中c.conn指的是IServiceConnection,它的具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类,InnerConnection的connected方法内部会调用H的post方法向主线程发送消息,从而解决当前应用程序进程和Service跨进程通信的问题。 

在1476行如果当前应用程序进程的Client端第一次与Service进行绑定的,并且Service已经调用过onUnBind方法,则需要调用 requestServiceBindingLocked。 

在1479行如果应用程序进程的Client端没有发送过绑定Service的请求,则会调用注释7的代码,注释7和注释5的代码区别就是最后一个参数rebind为false,表示不是重新绑定。 


6.ActiveServices.requestServiceBindingLocked

代码路径:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java)

1840    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
1841            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
1842        if (r.app == null || r.app.thread == null) {
1843            // If service is not currently running, can't yet bind.
1844            return false;
1845        }
1846        if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
1847                + " rebind=" + rebind);
1848        if ((!i.requested || rebind) && i.apps.size() > 0) {
1849            try {
1850                bumpServiceExecutingLocked(r, execInFg, "bind");
1851                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
1852                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
1853                        r.app.repProcState);
1854                if (!rebind) {
1855                    i.requested = true;
1856                }
1857                i.hasBound = true;
1858                i.doRebind = false;
1859            } catch (TransactionTooLargeException e) {
1860                // Keep the executeNesting count accurate.
1861                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
1862                final boolean inDestroying = mDestroyingServices.contains(r);
1863                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
1864                throw e;
1865            } catch (RemoteException e) {
1866                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
1867                // Keep the executeNesting count accurate.
1868                final boolean inDestroying = mDestroyingServices.contains(r);
1869                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
1870                return false;
1871            }
1872        }
1873        return true;
1874    }

在1848行i.requested表示是否发送过绑定Service的请求,从前面的代码得知是没有发送过,因此,!i.requested为true。从前面的代码得知rebind值为false,那么(!i.requested || rebind)的值为true。

如果IntentBindRecord中的应用程序进程记录大于0,则会调用1852行的代码,r.app.thread的类型为IApplicationThread


7.ActivityThread.scheduleBindService

代码路径:/frameworks/base/core/java/android/app/ActivityThread.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/ActivityThread.java)

852        public final void scheduleBindService(IBinder token, Intent intent,
853                boolean rebind, int processState) {
854            updateProcessState(processState, false);
855            BindServiceData s = new BindServiceData();
856            s.token = token;
857            s.intent = intent;
858            s.rebind = rebind;
859
860            if (DEBUG_SERVICE)
861                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
862                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
863            sendMessage(H.BIND_SERVICE, s);
864        }

首先将Service的信息封装成BindServiceData对象,需要注意的BindServiceData的成员变量rebind的值为false。接着将BindServiceData传入到sendMessage方法中。sendMessage向H发送消息。

8.ActivityThread.handleMessage

代码路径:/frameworks/base/core/java/android/app/ActivityThread.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/ActivityThread.java)

1584        public void handleMessage(Message msg) {
1585            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
1586            switch (msg.what) {
     ..............................................
1686                case BIND_SERVICE:
1687                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
1688                    handleBindService((BindServiceData)msg.obj);
1689                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1690                    break;
1691                case UNBIND_SERVICE:
1692                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
1693                    handleUnbindService((BindServiceData)msg.obj);
1694                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1695                    break;
      .............................................
1859            }
1860            Object obj = msg.obj;
1861            if (obj instanceof SomeArgs) {
1862                ((SomeArgs) obj).recycle();
1863            }
1864            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
1865        }

在1686行H在接收到BIND_SERVICE类型消息时,会在handleMessage方法中会调用handleBindService方法


9.ActivityThread.handleBindService

代码路径:/frameworks/base/core/java/android/app/ActivityThread.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/ActivityThread.java)

3421    private void handleBindService(BindServiceData data) {
3422        Service s = mServices.get(data.token);
3423        if (DEBUG_SERVICE)
3424            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
3425        if (s != null) {
3426            try {
3427                data.intent.setExtrasClassLoader(s.getClassLoader());
3428                data.intent.prepareToEnterProcess();
3429                try {
3430                    if (!data.rebind) {
3431                        IBinder binder = s.onBind(data.intent);
3432                        ActivityManager.getService().publishService(
3433                                data.token, data.intent, binder);
3434                    } else {
3435                        s.onRebind(data.intent);
3436                        ActivityManager.getService().serviceDoneExecuting(
3437                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3438                    }
3439                    ensureJitEnabled();
3440                } catch (RemoteException ex) {
3441                    throw ex.rethrowFromSystemServer();
3442                }
3443            } catch (Exception e) {
3444                if (!mInstrumentation.onException(s, e)) {
3445                    throw new RuntimeException(
3446                            "Unable to bind to service " + s
3447                            + " with " + data.intent + ": " + e.toString(), e);
3448                }
3449            }
3450        }
3451    }

在3422行获取要绑定的Service 。

在3430行的BindServiceData的成员变量rebind的值为false,

这样会调用在3431行的代码来调用Service的onBind方法,这样Service处于绑定状态了。

如果rebind的值为true就会调用3435行的Service的onRebind方法.

在3432行,实际上是调用AMS的publishService方法。 

9.ActivityThread.publishService

代码路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java)

18301    public void publishService(IBinder token, Intent intent, IBinder service) {
18302        // Refuse possible leaked file descriptors
18303        if (intent != null && intent.hasFileDescriptors() == true) {
18304            throw new IllegalArgumentException("File descriptors passed in Intent");
18305        }
18306
18307        synchronized(this) {
18308            if (!(token instanceof ServiceRecord)) {
18309                throw new IllegalArgumentException("Invalid service token");
18310            }
18311            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
18312        }
18313    }

publishService方法中,调用了ActiveServices类型的mServices对象的publishServiceLocked方法

10.ActiveServices.publishServiceLocked

代码路径:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java)

1492    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
1493        final long origId = Binder.clearCallingIdentity();
1494        try {
1495            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
1496                    + " " + intent + ": " + service);
1497            if (r != null) {
1498                Intent.FilterComparison filter
1499                        = new Intent.FilterComparison(intent);
1500                IntentBindRecord b = r.bindings.get(filter);
1501                if (b != null && !b.received) {
1502                    b.binder = service;
1503                    b.requested = true;
1504                    b.received = true;
1505                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
1506                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
1507                        for (int i=0; i<clist.size(); i++) {
1508                            ConnectionRecord c = clist.get(i);
1509                            if (!filter.equals(c.binding.intent.intent)) {
1510                                if (DEBUG_SERVICE) Slog.v(
1511                                        TAG_SERVICE, "Not publishing to: " + c);
1512                                if (DEBUG_SERVICE) Slog.v(
1513                                        TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
1514                                if (DEBUG_SERVICE) Slog.v(
1515                                        TAG_SERVICE, "Published intent: " + intent);
1516                                continue;
1517                            }
1518                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
1519                            try {
1520                                c.conn.connected(r.name, service, false);
1521                            } catch (Exception e) {
1522                                Slog.w(TAG, "Failure sending service " + r.name +
1523                                      " to connection " + c.conn.asBinder() +
1524                                      " (in " + c.binding.client.processName + ")", e);
1525                            }
1526                        }
1527                    }
1528                }
1529
1530                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
1531            }
1532        } finally {
1533            Binder.restoreCallingIdentity(origId);
1534        }
1535    }
 

在1520行c.conn指的是IServiceConnection,它的具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类。

11.LoadedApk.ServiceDispatcher.connected

代码路径:/frameworks/base/core/java/android/app/LoadedApk.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/LoadedApk.java)

471    static final class ServiceDispatcher {
..........................................................
1487
1488        private static class InnerConnection extends IServiceConnection.Stub {
1489            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1490
1491            InnerConnection(LoadedApk.ServiceDispatcher sd) {
1492                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1493            }
1494
1495            public void connected(ComponentName name, IBinder service, boolean dead)
1496                    throws RemoteException {
1497                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1498                if (sd != null) {
1499                    sd.connected(name, service, dead);
1500                }
1501            }
1502        }
..........................................................
1689    }
 
1499行调用了ServiceDispatcher 类型的sd对象的connected方法 

12.LoadedApk.connected

代码路径:/frameworks/base/core/java/android/app/LoadedApk.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/LoadedApk.java)

1568        public void connected(ComponentName name, IBinder service, boolean dead) {
1569            if (mActivityThread != null) {
1570                mActivityThread.post(new RunConnection(name, service, 0, dead));
1571            } else {
1572                doConnected(name, service, dead);
1573            }
1574        }

在1570行调用Handler类型的对象mActivityThread的post方法,mActivityThread实际上指向的是H。因此,通过调用H的post方法将RunConnection对象的内容运行在主线程中。


13.LoadedApk.RunConnection.run

代码路径:/frameworks/base/core/java/android/app/LoadedApk.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/LoadedApk.java)

1653        private final class RunConnection implements Runnable {
1654            RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
1655                mName = name;
1656                mService = service;
1657                mCommand = command;
1658                mDead = dead;
1659            }
1660
1661            public void run() {
1662                if (mCommand == 0) {
1663                    doConnected(mName, mService, mDead);
1664                } else if (mCommand == 1) {
1665                    doDeath(mName, mService);
1666                }
1667            }
1668
1669            final ComponentName mName;
1670            final IBinder mService;
1671            final int mCommand;
1672            final boolean mDead;
1673        }
 

 1661行RunConnection的run方法中调用了doConnected方法

14.LoadedApk.doConnected

代码路径:/frameworks/base/core/java/android/app/LoadedApk.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/LoadedApk.java)

1584        public void doConnected(ComponentName name, IBinder service, boolean dead) {
1585            ServiceDispatcher.ConnectionInfo old;
1586            ServiceDispatcher.ConnectionInfo info;
1587
1588            synchronized (this) {
1589                if (mForgotten) {
1590                    // We unbound before receiving the connection; ignore
1591                    // any connection received.
1592                    return;
1593                }
1594                old = mActiveConnections.get(name);
1595                if (old != null && old.binder == service) {
1596                    // Huh, already have this one.  Oh well!
1597                    return;
1598                }
1599
1600                if (service != null) {
1601                    // A new service is being connected... set it all up.
1602                    info = new ConnectionInfo();
1603                    info.binder = service;
1604                    info.deathMonitor = new DeathMonitor(name, service);
1605                    try {
1606                        service.linkToDeath(info.deathMonitor, 0);
1607                        mActiveConnections.put(name, info);
1608                    } catch (RemoteException e) {
1609                        // This service was dead before we got it...  just
1610                        // don't do anything with it.
1611                        mActiveConnections.remove(name);
1612                        return;
1613                    }
1614
1615                } else {
1616                    // The named service is being disconnected... clean up.
1617                    mActiveConnections.remove(name);
1618                }
1619
1620                if (old != null) {
1621                    old.binder.unlinkToDeath(old.deathMonitor, 0);
1622                }
1623            }
1624
1625            // If there was an old service, it is now disconnected.
1626            if (old != null) {
1627                mConnection.onServiceDisconnected(name);
1628            }
1629            if (dead) {
1630                mConnection.onBindingDied(name);
1631            }
1632            // If there is a new service, it is now connected.
1633            if (service != null) {
1634                mConnection.onServiceConnected(name, service);
1635            }
1636        }
1634行调用了ServiceConnection类型的对象mConnection的onServiceConnected方法,这样在客户端中实现了ServiceConnection接口的类的onServiceConnected方法就会被执行


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FusionCompute CNA-8.0.0-arm是华为公司推出的一款基于ARM架构的新一代云计算虚拟化平台,该平台具有稳定性高、性能强、适用范围广等优点,在云计算领域具有广泛的应用价值。该平台提供了高效的虚拟化能力,能够为企业客户提供更加安全和可靠的虚拟化解决方案。 作为一种云计算服务提供平台,FusionCompute CNA-8.0.0-arm具有一些独特的特点。首先,该平台采用最新的ARM架构,可以支持更加广泛的应用场景,具有很强的通用性和可扩展性。其次,该平台提供了高度智能化的管理功能,可以自动化分配计算资源,优化资源的运用效率,并且具有严格的安全保障机制,可以有效保护客户的数据安全。 同时,FusionCompute CNA-8.0.0-arm采用了独特的分布式架构,可以快速响应客户的需求,为客户提供更加优质的服务。其虚拟化能力卓越,可以满足客户在不同行业的需求,例如金融、交通、医疗、教育等领域的应用需求,并可提供高效的云计算解决方案。 总之,FusionCompute CNA-8.0.0-arm是一款非常优秀的云计算虚拟化平台,是企业客户在建立云计算服务时的绝佳选择。该平台采用最新的ARM架构,具有通用性和可扩展性,且具有优异的性能表现,可以满足各种不同行业的需求。同时,该平台具有智能化的管理功能和严格的安全保障机制,可以为企业客户提供更加安全可靠、高效的云计算服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值