ContentProvider引用计数

Posted by Gityuan on May 3, 2016

基于Android 6.0源码剖析,本文涉及的相关源码:

一.概述

上一篇文章理解ContentProvider原理介绍了provider的整个原理, 本文以查询操作为例,说一说provider引用计数的问题.

1.1 query操作

public final  Cursor query(final  Uri uri,  String[] projection,
             String selection,  String[] selectionArgs,
             String sortOrder,  CancellationSignal cancellationSignal) {
    //增加引用[见小节二]
    IContentProvider unstableProvider = acquireUnstableProvider(uri);
    IContentProvider stableProvider = null;
    Cursor qCursor = null;
    try {
        ...
        try {
            qCursor = unstableProvider.query(mPackageName, uri, projection,
                    selection, selectionArgs, sortOrder, remoteCancellationSignal);
        } catch (DeadObjectException e) {
            //减少引用[见小节三]
            unstableProviderDied(unstableProvider);

            //增加引用[见小节二]
            stableProvider = acquireProvider(uri);
            qCursor = stableProvider.query(mPackageName, uri, projection,
                    selection, selectionArgs, sortOrder, remoteCancellationSignal);
        }
        ...
        return wrapper;
    } catch (RemoteException e) {
        return null;
    } finally {
        ...
        if (unstableProvider != null) {
            releaseUnstableProvider(unstableProvider);//减少引用[见小节三]
        }
        if (stableProvider != null) {
            releaseProvider(stableProvider);//减少引用[见小节三]
        }
    }
}
  • provider引用计数的增加时机: acquireUnstableProvider()或者acquireProvider()
  • provider引用计数的减少时机: releaseUnstableProvider()或者releaseProvider()或unstableProviderDied()

1.2 相关对象

public final class ContentProviderConnection extends Binder {
    public final ContentProviderRecord provider;
    public final ProcessRecord client;
    public final long createTime; //创建时间
    public int stableCount; //stable引用次数
    public int unstableCount; //unstable引用次数
    public boolean waiting; //该连接的client正在等待provider发布
    public boolean dead; //该连接的provider已处于死亡状态
    //用于调试
    public int numStableIncs; //stable计数总的增加次数
    public int numUnstableIncs; //unstable计数总的增加次数
}

private static final class ProviderRefCount {
    public final IActivityManager.ContentProviderHolder holder;
    public final ProviderClientRecord client;
    public int stableCount;
    public int unstableCount;
    public boolean removePending;
}

以上两个对象记录provider引用相关的对象:

  • ContentProviderConnection: 连接contentprovider与client之间的连接对象
  • ProviderRefCount: ActivityThread的内部类,该引用保存到Client端.

二. 增加引用计数

acquireUnstableProvider过程具体过程见文章,理解ContentProvider原理, 对于acquireProvider的调用栈跟acquireUnstableProvider过程非常相近,都会调用到AT.acquireProvider(),主要差别在于stable值. 这里仅仅列举其调用栈如下:

CASE 1: acquireUnstableProvider

CR.acquireUnstableProvider
    ACR.acquireUnstableProvider
        AT.acquireProvider   // stable = false
            AT.acquireExistingProvider //增加计数[见小节2.1]
            AMP.getContentProvider
                AMS.getContentProvider
                    AMS.getContentProviderImpl //增加计数[见小节2.2]
            AT.installProvider

CASE 2: acquireProvider

CR.acquireProvider
    ACR.acquireProvider  
        AT.acquireProvider   // stable = true
            AT.acquireExistingProvider
            AMP.getContentProvider
                AMS.getContentProvider
                    AMS.getContentProviderImpl
            AT.installProvider

整个过程中有两个地方会增加引用计数: [小节2.2] acquireExistingProvider和 [小节2.3] getContentProviderImpl

2.1 AT.acquireExistingProvider

public final IContentProvider acquireExistingProvider(
        Context c, String auth, int userId, boolean stable) {
    synchronized (mProviderMap) {
        final ProviderKey key = new ProviderKey(auth, userId);
        //从AT.mProviderMap查询是否存在相对应的provider
        final ProviderClientRecord pr = mProviderMap.get(key);
        if (pr == null) {
            return null;
        }

        IContentProvider provider = pr.mProvider;
        IBinder jBinder = provider.asBinder();
        if (!jBinder.isBinderAlive()) {
            handleUnstableProviderDiedLocked(jBinder, true);
            return null;
        }

        ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
        if (prc != null) {
            //增加引用计数[见小节2.1.1]
            incProviderRefLocked(prc, stable);
        }
        return provider;
    }
}
  • acquireUnstableProvider的调用, 则stable=false.
  • acquireProvider的调用, 则stable=true.

2.1.1 AT.incProviderRefLocked

private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
    if (stable) {
        prc.stableCount += 1; //stable引用计数+1
        if (prc.stableCount == 1) {
            int unstableDelta;
            if (prc.removePending) {
                unstableDelta = -1;
                prc.removePending = false;
                mH.removeMessages(H.REMOVE_PROVIDER, prc); //移除消息
            } else {
                unstableDelta = 0;
            }
            // [见小节2.1.2]
            ActivityManagerNative.getDefault().refContentProvider(
                    prc.holder.connection, 1, unstableDelta);

        }
    } else {
        prc.unstableCount += 1; //unstable引用计数+1
        if (prc.unstableCount == 1) {
            if (prc.removePending) {
                prc.removePending = false;
                mH.removeMessages(H.REMOVE_PROVIDER, prc);
            } else {
                // [见小节2.1.2]
                ActivityManagerNative.getDefault().refContentProvider(
                        prc.holder.connection, 0, 1);
            }
        }
    }
}

该方法先增加ProviderRefCount对象的引用,再通过Binder调用AMS.refContentProvider来增加ContentProviderConnection的引用.

  • 对于stable provider, 当stableCount=1的情况
    • 当removePending = false时, 则refContentProvider传递的后两个参数(1, -1)
    • 当removePending = true 时, 则refContentProvider传递的后两个参数(1, 0)
  • 对于unstable provider,当unstableCount=1的情况
    • 当removePending=false时, 则refContentProvider传递的后两个参数(0,1)

2.1.2 AMP.refContentProvider

public boolean refContentProvider(IBinder connection, int stable, int unstable)
        throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(connection);
    data.writeInt(stable);
    data.writeInt(unstable);
    //[见小节2.1.3]
    mRemote.transact(REF_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
    reply.readException();
    boolean res = reply.readInt() != 0;
    data.recycle();
    reply.recycle();
    return res;
}

2.1.3 AMN.onTransact

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
        case REF_CONTENT_PROVIDER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            int stable = data.readInt();
            int unstable = data.readInt();
            //[见小节2.1.4]
            boolean res = refContentProvider(b, stable, unstable);
            reply.writeNoException();
            reply.writeInt(res ? 1 : 0);
            return true;
        }
        ...
    }
}

2.1.4 AMS.refContentProvider

public boolean refContentProvider(IBinder connection, int stable, int unstable) {
    ContentProviderConnection conn;
    conn = (ContentProviderConnection)connection;
    ...
    synchronized (this) {
        if (stable > 0) {
            conn.numStableIncs += stable;
        }

        //修改stableCount
        stable = conn.stableCount + stable;

        if (stable < 0) {
            throw new IllegalStateException("stableCount < 0: " + stable);
        }

        if (unstable > 0) {
            conn.numUnstableIncs += unstable;
        }

        //修改unstableCount
        unstable = conn.unstableCount + unstable;

        if (unstable < 0) {
            throw new IllegalStateException("unstableCount < 0: " + unstable);
        }
        if ((stable+unstable) <= 0) {
            throw new IllegalStateException("ref counts can't go to zero here: stable="
                    + stable + " unstable=" + unstable);
        }
        conn.stableCount = stable;
        conn.unstableCount = unstable;
        return !conn.dead;
    }
}

该方法是修改conn的stable和unstable引用次数,并返回connection是否存活. 存活则返回1,死亡则返回0. 修改后的stable和unstable值必须大于或等于0,且至少有一项大于0才能正常返回.以下任一情况会抛出异常IllegalStateException:

  • stable < 0
  • unstable < 0
  • (stable+unstable) <= 0

2.2 AMS.getContentProviderImpl

private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId) {
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;

    synchronized(this) {
        ProcessRecord r = getRecordForAppLocked(caller);
        //从AMS中查询相应的ContentProviderRecord
        cpr = mProviderMap.getProviderByName(name, userId);
        ...
        boolean providerRunning = cpr != null;

        if (providerRunning) {
            ...
            // 目标provider已存在的情况 [见小节2.2.1]
            conn = incProviderCountLocked(r, cpr, token, stable);
            ...
        }

        if (!providerRunning) {
            ...
            // 目标provider不存在的情况 [见小节2.2.1]
            conn = incProviderCountLocked(r, cpr, token, stable);
            ...
        }
    }
    ...
    return cpr != null ? cpr.newHolder(conn) : null;
}

2.2.1 AMS.incProviderCountLocked

ContentProviderConnection incProviderCountLocked(ProcessRecord r,
        final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
    if (r != null) {
        for (int i=0; i<r.conProviders.size(); i++) {
            ContentProviderConnection conn = r.conProviders.get(i);
            //从当前进程所使用的provider中查询与目标provider一致的信息
            if (conn.provider == cpr) {
                if (stable) {
                    conn.stableCount++;  //stable计数加1
                    conn.numStableIncs++;
                } else {
                    conn.unstableCount++;  //unstable计数加1
                    conn.numUnstableIncs++;
                }
                return conn;
            }
        }

        //当查询不到时,则新建provider连接对象
        ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
        if (stable) {
            conn.stableCount = 1;  //stable计数置为1
            conn.numStableIncs = 1;
        } else {
            conn.unstableCount = 1; //unstable计数置为1
            conn.numUnstableIncs = 1;
        }
        cpr.connections.add(conn);
        r.conProviders.add(conn);
        startAssociationLocked(r.uid, r.processName, cpr.uid, cpr.name, cpr.info.processName);
        return conn;
    }
    cpr.addExternalProcessHandleLocked(externalProcessToken);
    return null;
}

2.3 小节

增加引用计数的过程:removePending是指当前正在处于移除引用计数的过程,当removePending=true代表正处于移除最后引用的情况.而此时有需要增加引用计数,所以会抵消一次unstableCount加1的操作.

ContentProviderConnection引用计数情况:

方法 stableCount unstableCount 条件
acquireProvider +1 0 removePending=false
acquireProvider +1 -1 removePending=true
acquireUnstableProvider 0 +1 removePending=false
acquireUnstableProvider 0 0 removePending=true

增加引用计数的具体方法:

  • AT.incProviderRefLocked ==> AMS.refContentProvider
  • AMS.incProviderCountLocked

三. 减小引用计数

releaseProvider跟releaseUnstableProvider过程很相似, 都会调用到AT.releaseProvider(), 其主要区别在于参数stable. 另外还有方法unstableProviderDied()也是用于减小引用计数.

CASE 1: releaseUnstableProvider

ApplicationContentResolver.releaseUnstableProvider
    AT.releaseProvider   // stable = false [见小节3.1]
        AMP.refContentProvider
            AMS.refContentProvider
        AT.completeRemoveProvider //减小计数[见小节3.2]
            AMP.removeContentProvider
                AMS.removeContentProvider
                    AMS.decProviderCountLocked

CASE 2: releaseProvider

ApplicationContentResolver.releaseProvider
    AT.releaseProvider   // stable = true [见小节3.1]
        AMP.refContentProvider
            AMS.refContentProvider
        AT.completeRemoveProvider //减小计数[见小节3.2]
            AMP.removeContentProvider
                AMS.removeContentProvider
                    AMS.decProviderCountLocked

3.1 AT.releaseProvider

public final boolean releaseProvider(IContentProvider provider, boolean stable) {
    if (provider == null) {
        return false; //provider为空则直接返回
    }

    IBinder jBinder = provider.asBinder();
    synchronized (mProviderMap) {
        ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
        if (prc == null) {
            return false;  //provider引用对象为空则直接返回
        }

        boolean lastRef = false;
        if (stable) {
            if (prc.stableCount == 0) {
                return false; //引用次数为0则直接返回
            }

            prc.stableCount -= 1; //stable引用计数减1
            if (prc.stableCount == 0) {
                lastRef = prc.unstableCount == 0;
                //[见小节3.1.1]
                ActivityManagerNative.getDefault().refContentProvider(
                        prc.holder.connection, -1, lastRef ? 1 : 0);
            }
        } else {
            if (prc.unstableCount == 0) {
                return false;
            }
            prc.unstableCount -= 1; //unstable引用计数减1
            if (prc.unstableCount == 0) {
                lastRef = prc.stableCount == 0;
                if (!lastRef) {
                    //[见小节3.1.1]
                    ActivityManagerNative.getDefault().refContentProvider(
                        prc.holder.connection, 0, -1);

            }
        }

        //当执行完该方法,引用技术变成0时,则发送REMOVE_PROVIDER消息[见小节3.2]
        if (lastRef) {
            if (!prc.removePending) {
                prc.removePending = true;
                Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
                mH.sendMessage(msg);
            }
        }
        return true;
    }
}

该方法先减小ProviderRefCount对象的引用,再通过Binder调用AMS.refContentProvider来减小ContentProviderConnection的引用.

  • 对于stable provider,当stableCount=0的情况下
    • 当unstableCount != 0时, 则refContentProvider传递的后两个参数(-1, 0)
    • 当unstableCount = 0时, 则refContentProvider传递的后两个参数(-1, 1)
  • 对于unstable provider,当unstableCount=0的情况下:
    • 当stableCount != 0 时, 则refContentProvider传递的后两个参数(0,-1)

当最后引用计数时,则发送REMOVE_PROVIDER消息, 主线程收到消息调用AT.completeRemoveProvider.

3.1.1 AMS.refContentProvider

public boolean refContentProvider(IBinder connection, int stable, int unstable) {
    ContentProviderConnection conn;
    conn = (ContentProviderConnection)connection;
    ...
    synchronized (this) {
        if (stable > 0) {
            conn.numStableIncs += stable;
        }

        //修改stableCount
        stable = conn.stableCount + stable;

        if (stable < 0) {
            throw new IllegalStateException("stableCount < 0: " + stable);
        }

        if (unstable > 0) {
            conn.numUnstableIncs += unstable;
        }

        //修改unstableCount
        unstable = conn.unstableCount + unstable;

        if (unstable < 0) {
            throw new IllegalStateException("unstableCount < 0: " + unstable);
        }
        if ((stable+unstable) <= 0) {
            throw new IllegalStateException("ref counts can't go to zero here: stable="
                    + stable + " unstable=" + unstable);
        }
        conn.stableCount = stable;
        conn.unstableCount = unstable;
        return !conn.dead;
    }
}

3.2 AT.completeRemoveProvider

final void completeRemoveProvider(ProviderRefCount prc) {
    synchronized (mProviderMap) {
        if (!prc.removePending) {
            return;
        }

        prc.removePending = false;

        final IBinder jBinder = prc.holder.provider.asBinder();
        ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
        if (existingPrc == prc) {
            mProviderRefCountMap.remove(jBinder);
        }

        for (int i=mProviderMap.size()-1; i>=0; i--) {
            ProviderClientRecord pr = mProviderMap.valueAt(i);
            IBinder myBinder = pr.mProvider.asBinder();
            if (myBinder == jBinder) {
                mProviderMap.removeAt(i);
            }
        }
    }
    // [见小节3.2.1]
    ActivityManagerNative.getDefault().removeContentProvider(
            prc.holder.connection, false);

}

3.2.1 AMP.removeContentProvider

public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(connection);
    data.writeInt(stable ? 1 : 0);
    //[见小节3.2.2]
    mRemote.transact(REMOVE_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
    reply.readException();
    data.recycle();
    reply.recycle();
}

3.2.2 AMN.onTransact

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
        case REMOVE_CONTENT_PROVIDER_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            boolean stable = data.readInt() != 0;
            //[见小节3.2.3]
            removeContentProvider(b, stable);
            reply.writeNoException();
            return true;
        }
    ...
    }
}

3.2.3 AMS.removeContentProvider

public void removeContentProvider(IBinder connection, boolean stable) {
    enforceNotIsolatedCaller("removeContentProvider");
    long ident = Binder.clearCallingIdentity();
    try {
        synchronized (this) {
            ContentProviderConnection conn;
            conn = (ContentProviderConnection)connection;
            ...
            //[见小节3.2.4]
            if (decProviderCountLocked(conn, null, null, stable)) {
                updateOomAdjLocked();
            }
        }
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

3.2.4 AMS.decProviderCountLocked

boolean decProviderCountLocked(ContentProviderConnection conn,
        ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
    if (conn != null) {
        cpr = conn.provider;
        if (stable) {
            conn.stableCount--; //stable计数减1
        } else {
            conn.unstableCount--;  //unstable计数减1
        }

        //当provider连接的 stable和unstable引用次数都为0时,则移除该连接对象信息
        if (conn.stableCount == 0 && conn.unstableCount == 0) {
            cpr.connections.remove(conn);
            conn.client.conProviders.remove(conn);
            stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name);
            return true;
        }
        return false;
    }
    cpr.removeExternalProcessHandleLocked(externalProcessToken);
    return false;
}

3.3 小节

减小引用计数:

方法 stableCount unstableCount 条件
releaseProvider -1 0 lastRef=false
releaseProvider -1 1 lastRef=true
releaseUnstableProvider 0 -1 lastRef=false
releaseUnstableProvider 0 0 lastRef=true

减小引用计数的具体方法:

  • AT.releaseProvider ==> AMS.refContentProvider
  • AMS.decProviderCountLocked

当stable和unstable引用计数都为0时则移除connection信息

四. Provider死亡

4.1 进程死亡

对于unstable的provider可直接调用unstableProviderDied,或者是当provider进程死亡后会有死亡回调binderDied,这两个方法最终都会调用到appDiedLocked().

调用链如下:

    ACR.unstableProviderDied
        AT.handleUnstableProviderDied
            AT.handleUnstableProviderDiedLocked //[见小节4.2]
                AMP.unstableProviderDied
                    AMS.unstableProviderDied
                        AMS.appDiedLocked

4.2 AT.handleUnstableProviderDiedLocked

final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
    ProviderRefCount prc = mProviderRefCountMap.get(provider);
    if (prc != null) {

        mProviderRefCountMap.remove(provider);
        for (int i=mProviderMap.size()-1; i>=0; i--) {
            ProviderClientRecord pr = mProviderMap.valueAt(i);
            if (pr != null && pr.mProvider.asBinder() == provider) {
                mProviderMap.removeAt(i);
            }
        }

        if (fromClient) {
            //[见小节4.3]
            ActivityManagerNative.getDefault().unstableProviderDied(
                    prc.holder.connection);
        }
    }
}

4.3 AMS.unstableProviderDied

public void unstableProviderDied(IBinder connection) {
    ContentProviderConnection conn = (ContentProviderConnection)connection;

    IContentProvider provider;
    synchronized (this) {
        provider = conn.provider.provider;
    }

    if (provider == null) {
        return;
    }

    if (provider.asBinder().pingBinder()) {
        //provider进程仍然存活,则不清理
        synchronized (this) {
            return;
        }
    }

    synchronized (this) {
        if (conn.provider.provider != provider) {
            return;
        }

        ProcessRecord proc = conn.provider.proc;
        if (proc == null || proc.thread == null) {
            //进程信息已清理
            return;
        }

        final long ident = Binder.clearCallingIdentity();
        try {
            appDiedLocked(proc); //[见小节4.4]
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
}

4.4 AMS.cleanUpApplicationRecordLocked

private final boolean cleanUpApplicationRecordLocked(...) {
    ...
    for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
        //获取该进程已发布的ContentProvider
        ContentProviderRecord cpr = app.pubProviders.valueAt(i);
        // allowRestart=true,一般地always=false
        final boolean always = app.bad || !allowRestart;

        //ContentProvider服务端被杀,则client端进程也会被杀[见小节4.5]
        boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
        if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
            restart = true; //需要重启
        }

        cpr.provider = null;
        cpr.proc = null;
    }
    app.pubProviders.clear();

    //处理正在启动并且是有client端正在等待的ContentProvider
    if (cleanupAppInLaunchingProvidersLocked(app, false)) {
        restart = true;
    }

    //取消已连接的ContentProvider的注册
    if (!app.conProviders.isEmpty()) {
        for (int i = app.conProviders.size() - 1; i >= 0; i--) {
            ContentProviderConnection conn = app.conProviders.get(i);
            conn.provider.connections.remove(conn);

            stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
                    conn.provider.name);
        }
        app.conProviders.clear();
    }
    ...
}

4.5 AMS.removeDyingProviderLocked

private final boolean removeDyingProviderLocked(ProcessRecord proc,
          ContentProviderRecord cpr, boolean always) {
  final boolean inLaunching = mLaunchingProviders.contains(cpr);

  if (!inLaunching || always) {
      synchronized (cpr) {
          cpr.launchingApp = null;
          cpr.notifyAll(); //通知处于等待状态的进程
      }
      mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
      String names[] = cpr.info.authority.split(";");
      for (int j = 0; j < names.length; j++) {
          mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
      }
  }

  for (int i = cpr.connections.size() - 1; i >= 0; i--) {
      ContentProviderConnection conn = cpr.connections.get(i);
      if (conn.waiting) {
          if (inLaunching && !always) {
              continue;
          }
      }
      ProcessRecord capp = conn.client;
      conn.dead = true;
      if (conn.stableCount > 0) {
          if (!capp.persistent && capp.thread != null
                  && capp.pid != 0
                  && capp.pid != MY_PID) {
              //非persistent进程,则杀掉跟provider具有依赖关系的进程
              capp.kill("depends on provider "
                      + cpr.name.flattenToShortString()
                      + " in dying proc " + (proc != null ? proc.processName : "??"), true);
          }
      } else if (capp.thread != null && conn.provider.provider != null) {
          //unstable的类型则不会被杀,也会调用到[小节4.2]
          capp.thread.unstableProviderDied(conn.provider.provider.asBinder());

          cpr.connections.remove(i);
          if (conn.client.conProviders.remove(conn)) {
              stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
          }
      }
  }

  if (inLaunching && always) {
      mLaunchingProviders.remove(cpr);
  }
  return inLaunching;
}

removeDyingProviderLocked()方法的功能非常值得注意,引用计数跟进程的存活息息相关:

  • 对于stable类型的provider(即conn.stableCount > 0),则会杀掉所有跟该provider建立stable连接的非persistent进程.
  • 对于unstable类的provider(即conn.unstableCount > 0),并不会导致client进程被级联所杀.

五. 总结

provider引用计数的增加与减少关系: removePending是指即将被移除的引用, lastRef是指当前引用为0.

方法 stableCount unstableCount 条件
acquireProvider +1 0 removePending=false
acquireProvider +1 -1 removePending=true
acquireUnstableProvider 0 +1 removePending=false
acquireUnstableProvider 0 0 removePending=true
releaseProvider -1 0 lastRef=false
releaseProvider -1 1 lastRef=true
releaseUnstableProvider 0 -1 lastRef=false
releaseUnstableProvider 0 0 lastRef=true

当Client进程存在对某个provider的引用时,则会根据provider类型进行不同的处理:

  • 对于stable provider: 会杀掉所有跟该provider建立stable连接的非persistent进程.
  • 对于unstable provider: 不会导致client进程被级联所杀,只会回调unstableProviderDied来清理相关信息.

当stable和unstable引用计数都为0时则移除connection信息:

  • AMS.removeContentProvider()过程移除该connection相关的所有信息

微信公众号 Gityuan | 微博 weibo.com/gityuan | 博客 留言区交流