美文网首页android之基础学习攻克
bindService用到的各数据结构

bindService用到的各数据结构

作者: weiinter105 | 来源:发表于2018-12-01 00:03 被阅读0次

    bindService中涉及到的几种数据结构

    AMS中相关数据结构

    ServiceRecord

    57final class ServiceRecord extends Binder {
    58    private static final String TAG = TAG_WITH_CLASS_NAME ? "ServiceRecord" : TAG_AM;
    59
    60    // Maximum number of delivery attempts before giving up.
    61    static final int MAX_DELIVERY_COUNT = 3;
    62
    63    // Maximum number of times it can fail during execution before giving up.
    64    static final int MAX_DONE_EXECUTING_COUNT = 6;
    65
    66    final ActivityManagerService ams;
    67    final BatteryStatsImpl.Uid.Pkg.Serv stats;
    68    final ComponentName name; // service component.
    69    final String shortName; // name.flattenToShortString().
    70    final Intent.FilterComparison intent;
    71                            // original intent used to find service.
    72    final ServiceInfo serviceInfo;
    73                            // all information about the service.
    74    final ApplicationInfo appInfo;
    75                            // information about service's app.
    76    final int userId;       // user that this service is running as
    77    final String packageName; // the package implementing intent's component
    78    final String processName; // process where this component wants to run
    79    final String permission;// permission needed to access service
    80    final boolean exported; // from ServiceInfo.exported
    81    final Runnable restarter; // used to schedule retries of starting the service
    82    final long createTime;  // when this service was created
    83    final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
    84            = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
    //Intent及其对应的IntentBindRecord
    85                            // All active bindings to the service.
    86    final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
    87            = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();  
    //IServiceConnection及其对应的ConnectionRecord list
    88                            // IBinder -> ConnectionRecord of all bound clients
    89
    90    ProcessRecord app;      // where this service is running or null.
    91    ProcessRecord isolatedProc; // keep track of isolated process, if requested
    92    ServiceState tracker; // tracking service execution, may be null
    93    ServiceState restartTracker; // tracking service restart
    94    boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
    95    boolean delayed;        // are we waiting to start this service in the background?
    96    boolean fgRequired;     // is the service required to go foreground after starting?
    97    boolean fgWaiting;      // is a timeout for going foreground already scheduled?
    98    boolean isForeground;   // is service currently in foreground mode?
    99    int foregroundId;       // Notification ID of last foreground req.
    100    Notification foregroundNoti; // Notification record of foreground state.
    101    long lastActivity;      // last time there was some activity on the service.
    102    long startingBgTimeout;  // time at which we scheduled this for a delayed start.
    103    boolean startRequested; // someone explicitly called start?
    104    boolean delayedStop;    // service has been stopped but is in a delayed start?
    105    boolean stopIfKilled;   // last onStart() said to stop if service killed?
    106    boolean callStart;      // last onStart() has asked to alway be called on restart.
    107    int executeNesting;     // number of outstanding operations keeping foreground.
    108    boolean executeFg;      // should we be executing in the foreground?
    109    long executingStart;    // start time of last execute request.
    110    boolean createdFromFg;  // was this service last created due to a foreground process call?
    111    int crashCount;         // number of times proc has crashed with service running
    112    int totalRestartCount;  // number of times we have had to restart.
    113    int restartCount;       // number of restarts performed in a row.
    114    long restartDelay;      // delay until next restart attempt.
    115    long restartTime;       // time of last restart.
    116    long nextRestartTime;   // time when restartDelay will expire.
    117    boolean destroying;     // set when we have started destroying the service
    118    long destroyTime;       // time at which destory was initiated.
    119
    120    String stringName;      // caching of toString
    121
    122    private int lastStartId;    // identifier of most recent start request.
    123
    124    static class StartItem {
    125        final ServiceRecord sr;
    126        final boolean taskRemoved;
    127        final int id;
    128        final int callingId;
    129        final Intent intent;
    130        final ActivityManagerService.NeededUriGrants neededGrants;
    131        long deliveredTime;
    132        int deliveryCount;
    133        int doneExecutingCount;
    134        UriPermissionOwner uriPermissions;
    135
    136        String stringName;      // caching of toString
    

    IntentBindRecord

    一个Service可能与多种Intent关联,从Intent的角度保存的数据结构

    27/**
    28 * A particular Intent that has been bound to a Service.
    29 */
    30final class IntentBindRecord {
    31    /** The running service. */
    32    final ServiceRecord service;
    33    /** The intent that is bound.*/
    34    final Intent.FilterComparison intent; //
    35    /** All apps that have bound to this Intent. */
    36    final ArrayMap<ProcessRecord, AppBindRecord> apps
    37            = new ArrayMap<ProcessRecord, AppBindRecord>(); 
    //保存所有使用了该种Intent的客户端
    38    /** Binder published from service. */
    39    IBinder binder; 
    //保存的服务端Service实例对应的binder对象
    40    /** Set when we have initiated a request for this binder. */
    //需要结合代码看
    41    boolean requested;
    42    /** Set when we have received the requested binder. */
    43    boolean received;
    44    /** Set when we still need to tell the service all clients are unbound. */
    45    boolean hasBound; 
    46    /** Set when the service's onUnbind() has asked to be told about new clients. */
    47    boolean doRebind;
    48
    49    String stringName;      // caching of toString
    

    AppBindRecord

    其实代表了相应ServiceRecord的一个客户端在AMS中的表达方式

    23/**
    24 * An association between a service and one of its client applications.
    25 */
    26final class AppBindRecord {
    27    final ServiceRecord service;    // The running service. 
    //绑定的ServiceRecord
    28    final IntentBindRecord intent;  // The intent we are bound to. 
    //用于绑定的Intent  (IntentBindRecord)
    29    final ProcessRecord client;     // Who has started/bound the service.
     //客户端进程信息
    30
    31    final ArraySet<ConnectionRecord> connections = new ArraySet<>(); 
    //客户端所持有的ConnectionRecord
    32                                    // All ConnectionRecord for this client.
    

    ConnectionRecord

    代表一个最小的binding元素

    25/**
    26 * Description of a single binding to a service.
    27 */
    28final class ConnectionRecord {
    29    final AppBindRecord binding;    // The application/service binding.  
    //依附的客户端的相关信息
    30    final ActivityRecord activity;  // If non-null, the owning activity. 
    //从客户端的Activity bindService
    31    final IServiceConnection conn;  // The client connection. 
    //客户端ServiceConnection对应的binder对象
    32    final int flags;                // Binding options.
    33    final int clientLabel;          // String resource labeling this client.
    34    final PendingIntent clientIntent; // How to launch the client.
    35    String stringName;              // Caching of toString.
    36    boolean serviceDead;            // Well is it?
    

    总结

    相当于客户端进程,Intent,ServiceConnection是bindService的三要素,这三者确定要绑定的ServiceRecord
    1.三个要素都限定死了,那么就是ConnectionRecord
    2.限定死了客户端进程和Intent,放松ServiceRecord就是AppBindRecord (ArraySet<ConnectionRecord> connections)
    3.只限定Intent,那么可以有多个客户端使用Intent来bindService( final ArrayMap<ProcessRecord, AppBindRecord> apps = new ArrayMap<ProcessRecord, AppBindRecord>(); //保存所有使用了该种Intent的客户端)

    客户端数据结构

    ServiceDispatcher

    124    private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
    125        = new ArrayMap<>();
    
    1489    static final class ServiceDispatcher {
    1490        private final ServiceDispatcher.InnerConnection mIServiceConnection; 
    //持有一个与ServiceConnection对象相关的binder对象传递给AMS,这样AMS就可以通过这个对象来操作客户端,这个对象是个内部类,其持有外部对象的弱引用,这样就可以调用到ServiceDispatcher中的方法,比较巧妙
    1491        private final ServiceConnection mConnection;
    1492        private final Context mContext;
    1493        private final Handler mActivityThread;
    1494        private final ServiceConnectionLeaked mLocation;
    1495        private final int mFlags;
    1496
    1497        private RuntimeException mUnbindLocation;
    1498
    1499        private boolean mForgotten;
    1500
    1501        private static class ConnectionInfo {
    1502            IBinder binder;
    1503            IBinder.DeathRecipient deathMonitor;
    1504        }
    1505
    1506        private static class InnerConnection extends IServiceConnection.Stub {
    1507            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; 
                   //WeakReference的使用场景
                  //静态内部类持有外部对象(用WeakReference引用) 
    

    完整逻辑:

    1489    static final class ServiceDispatcher {
    1490        private final ServiceDispatcher.InnerConnection mIServiceConnection;
    1491        private final ServiceConnection mConnection;
    1492        private final Context mContext;
    1493        private final Handler mActivityThread;
    1494        private final ServiceConnectionLeaked mLocation;
    1495        private final int mFlags;
    1496
    1497        private RuntimeException mUnbindLocation;
    1498
    1499        private boolean mForgotten;
    1500
    1501        private static class ConnectionInfo {
    1502            IBinder binder;
    1503            IBinder.DeathRecipient deathMonitor;
    1504        }
    1505
    1506        private static class InnerConnection extends IServiceConnection.Stub {
    1507            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; //WeakReference的使用场景
                          //静态内部类持有外部对象(用WeakReference引用) 
    1508
    1509            InnerConnection(LoadedApk.ServiceDispatcher sd) {
    1510                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
    1511            }
    1512
    1513            public void connected(ComponentName name, IBinder service, boolean dead)
    1514                    throws RemoteException {
    1515                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
    1516                if (sd != null) { //判断其是否已经被回收
    1517                    sd.connected(name, service, dead);
    1518                }
    1519            }
    1520        }
    1521
    1522        private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
    1523            = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
    1524
    1525        ServiceDispatcher(ServiceConnection conn,
    1526                Context context, Handler activityThread, int flags) {
    1527            mIServiceConnection = new InnerConnection(this); 
    1528            mConnection = conn;
    1529            mContext = context;
    1530            mActivityThread = activityThread;
    1531            mLocation = new ServiceConnectionLeaked(null);
    1532            mLocation.fillInStackTrace();
    1533            mFlags = flags;
    1534        } 
    1535
    1536        void validate(Context context, Handler activityThread) {
    1537            if (mContext != context) {
    1538                throw new RuntimeException(
    1539                    "ServiceConnection " + mConnection +
    1540                    " registered with differing Context (was " +
    1541                    mContext + " now " + context + ")");
    1542            }
    1543            if (mActivityThread != activityThread) {
    1544                throw new RuntimeException(
    1545                    "ServiceConnection " + mConnection +
    1546                    " registered with differing handler (was " +
    1547                    mActivityThread + " now " + activityThread + ")");
    1548            }
    1549        }
    1550
    1551        void doForget() {
    1552            synchronized(this) {
    1553                for (int i=0; i<mActiveConnections.size(); i++) {
    1554                    ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
    1555                    ci.binder.unlinkToDeath(ci.deathMonitor, 0);
    1556                }
    1557                mActiveConnections.clear();
    1558                mForgotten = true;
    1559            }
    1560        }
    1561
    1562        ServiceConnectionLeaked getLocation() {
    1563            return mLocation;
    1564        }
    1565
    1566        ServiceConnection getServiceConnection() {
    1567            return mConnection;
    1568        }
    1569
    1570        IServiceConnection getIServiceConnection() {
    1571            return mIServiceConnection;
    1572        }
    1573
    1574        int getFlags() {
    1575            return mFlags;
    1576        }
    1577
    1578        void setUnbindLocation(RuntimeException ex) {
    1579            mUnbindLocation = ex;
    1580        }
    1581
    1582        RuntimeException getUnbindLocation() {
    1583            return mUnbindLocation;
    1584        }
    1585
    1586        public void connected(ComponentName name, IBinder service, boolean dead) {
    1587            if (mActivityThread != null) {
    1588                mActivityThread.post(new RunConnection(name, service, 0, dead));
    1589            } else {
    1590                doConnected(name, service, dead);
    1591            }
    1592        }
    1593
    1594        public void death(ComponentName name, IBinder service) {
    1595            if (mActivityThread != null) {
    1596                mActivityThread.post(new RunConnection(name, service, 1, false));
    1597            } else {
    1598                doDeath(name, service);
    1599            }
    1600        }
    1601
    1602        public void doConnected(ComponentName name, IBinder service, boolean dead) {
    1603            ServiceDispatcher.ConnectionInfo old;
    1604            ServiceDispatcher.ConnectionInfo info;
    1605
    1606            synchronized (this) {
    1607                if (mForgotten) {
    1608                    // We unbound before receiving the connection; ignore
    1609                    // any connection received.
    1610                    return;
    1611                }
    1612                old = mActiveConnections.get(name);
    1613                if (old != null && old.binder == service) {
    1614                    // Huh, already have this one.  Oh well!
    1615                    return;
    1616                }
    1617
    1618                if (service != null) {
    1619                    // A new service is being connected... set it all up.
    1620                    info = new ConnectionInfo();
    1621                    info.binder = service;
    1622                    info.deathMonitor = new DeathMonitor(name, service);
    1623                    try {
    1624                        service.linkToDeath(info.deathMonitor, 0);
    1625                        mActiveConnections.put(name, info);
    1626                    } catch (RemoteException e) {
    1627                        // This service was dead before we got it...  just
    1628                        // don't do anything with it.
    1629                        mActiveConnections.remove(name);
    1630                        return;
    1631                    }
    1632
    1633                } else {
    1634                    // The named service is being disconnected... clean up.
    1635                    mActiveConnections.remove(name);
    1636                }
    1637
    1638                if (old != null) {
    1639                    old.binder.unlinkToDeath(old.deathMonitor, 0);
    1640                }
    1641            }
    1642
    1643            // If there was an old service, it is now disconnected.
    1644            if (old != null) {
    1645                mConnection.onServiceDisconnected(name);
    1646            }
    1647            if (dead) {
    1648                mConnection.onBindingDied(name);
    1649            }
    1650            // If there is a new service, it is now connected.
    1651            if (service != null) {
    1652                mConnection.onServiceConnected(name, service);
    1653            }
    1654        }
    1655
    1656        public void doDeath(ComponentName name, IBinder service) {
    1657            synchronized (this) {
    1658                ConnectionInfo old = mActiveConnections.get(name);
    1659                if (old == null || old.binder != service) {
    1660                    // Death for someone different than who we last
    1661                    // reported...  just ignore it.
    1662                    return;
    1663                }
    1664                mActiveConnections.remove(name);
    1665                old.binder.unlinkToDeath(old.deathMonitor, 0);
    1666            }
    1667
    1668            mConnection.onServiceDisconnected(name);
    1669        }
    1670
    1671        private final class RunConnection implements Runnable {
    1672            RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
    1673                mName = name;
    1674                mService = service;
    1675                mCommand = command;
    1676                mDead = dead;
    1677            }
    1678
    1679            public void run() {
    1680                if (mCommand == 0) {
    1681                    doConnected(mName, mService, mDead);
    1682                } else if (mCommand == 1) {
    1683                    doDeath(mName, mService);
    1684                }
    1685            }
    1686
    1687            final ComponentName mName;
    1688            final IBinder mService;
    1689            final int mCommand;
    1690            final boolean mDead;
    1691        }
    1692
    1693        private final class DeathMonitor implements IBinder.DeathRecipient
    1694        {
    1695            DeathMonitor(ComponentName name, IBinder service) {
    1696                mName = name;
    1697                mService = service;
    1698            }
    1699
    1700            public void binderDied() {
    1701                death(mName, mService);
    1702            }
    1703
    1704            final ComponentName mName;
    1705            final IBinder mService;
    1706        }
    1707    }
    1708}
    

    服务端数据结构

    就是一个Service实例,没什么特别值得说的

    总结结构图

    bindService数据结构.png

    可见,IntentBindRecord.binder中保存的Service实例的binder对象,ConnectionRecord.conn保存客户端ServiceConnection对应的binder对象

    相关文章

      网友评论

        本文标题:bindService用到的各数据结构

        本文链接:https://www.haomeiwen.com/subject/juzkcqtx.html