Android System Server大纲之ContentService和ContentProvider原理剖析

内容提供程序

观察内容提供商

  • Android System Server大纲之ContentService和ContentProvider原理剖析
    • 前言
    • APP发起查询
    • 深入ContentResolver
      • 准备工作
      • 获取ContentProvider
      • 公布ContentProvider
      • 关系图
    • ContentProvider数据监听
      • 观察者注册过程
      • 数据变化通知过程
    • 总结

前言

ContentService是Android四大组件之一的ContentProvider密切相关的一个系统服务,且和AccountManagerService也有着紧密的联系。ContentService以功能来划分,就两大模块:

  • 提供管理通知监听ContentProvider数据变化的观察者的服务
  • 同步功能:同步日历、Email等

第一个功能,对于很多开发者来说可能熟悉。而对于第二个,可能就会陌生一点,这个是Android提供的同步功能,很多APP开发者,也很难用到这个Android的同步功能。ContentService的同步功能和AccountManagerService往往紧密联系在一起。本文将不再阐述ContentService的同步功能,有兴趣的读者可以自行阅读Android的参考文档了解该功能的使用方法https://developer.android.google.cn/reference/android/content/SyncRequest.html。那么本文将阐述的内容是:

  • ContentProvider的原理
  • ContentProvider的观察者服务

ContentProvider是Android的四大组件之一,是提供APP间安全共享数据的方式之一,APP可以通过ContentProvider从其它APP中获取到想要的数据,例如读取手机的联系人。也可以通过ContentProvider把APP的数据共享出去给其它APP使用。

以查询ContentProvider的数据的流程为线索,一步一步分析这个过程,从而了解ContentProvider的过程和原理。

APP发起查询

引用官方的一段话:如果您想要访问内容提供程序中的数据,可以将应用的 Context 中的 ContentResolver 对象用作客户端来与提供程序通信。 ContentResolver 对象会与提供程序对象(即实现 ContentProvider 的类实例)通信。 提供程序对象从客户端接收数据请求,执行请求的操作并返回结果。

APP发起查询,很简单,如下:

ContentResolver cr = getContentResolver();cr.query(Uri uri, ....);

首先通过getContentResolver()获取到ContentResolver对象,ContentResolver对象好比内容分解器,能够分解出来需要调用哪个内容提供程序即ContentProvider。ContentResolver分解的依据便是参数Uri。Uri是如何把ContentResolver和ContentProvider联系起来的呢?Uri可以看作是一个地址描述,随意举一个Uri可描述的地址例子:

content://user_dictionary

可以和平时上网的网址做一个类比,如访问百度:

https://www.baidu.com

Uri和网址结构有很大相似性,https表示的是网络技术中的传输协议,那么content也可以当做ContentProvider中的一种协议,那么content就代表当前需要通过ContentProvider进行数据通信。www.baidu.com是百度的域名,表示需要访问网站的位置,user_dictionary也就可以比作ContentProvider的域名,user_dictionary表示是那个ContentProvider。换句话说,ContentResolver接收到content://user_dictionary这个Uri时,就知道当前需要发起ContentProvider数据交互,通过user_dictionary可以寻找用user_dictionary表示的ContentProvider。

深入ContentResolver

准备工作

查看ContentResolver的定义,如下:

public abstract class ContentResolver {    ......}

可见ContentResolver是一个抽象类,所以说getContentResolver()所获取到实例本质是ContentResolver的子类,查看getContentResolver()的具体实现:

private final ApplicationContentResolver mContentResolver;public ContentResolver getContentResolver() {    return mContentResolver;}

上面的代码定义在文件frameworks/base/core/java/android/app/ContextImpl.java中

从上面的代码可知,getContentResolver()获取到的实际是ApplicationContentResolver的实例mContentResolver。cr.query(Uri uri, ….)的实现如下:

public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,......) {    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);            if (stableProvider == null) {                return null;            }            qCursor = stableProvider.query(mPackageName, uri, projection,                    selection, selectionArgs, sortOrder, remoteCancellationSignal);        }        if (qCursor == null) {            return null;        }        ......}

这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。

这里用文字描述一下上面代码的过程,先声明两个相同类型的局部变量unstableProvider、stableProvider,都是IContentProvider的实例,IContentProvider是AIDL的接口,所以IContentProvider所调用的方法是远程调用。通过acquireUnstableProvider()方法给unstableProvider变量赋值,unstableProvider调用query()方法,如果发生DeadObjectException异常,调用acquireProvider()方法给stableProvider赋值,然后调用stableProvider的query()方法。

这里有点奇怪,为什么要声明两个一样的IContentProvider变量,且调用相同的方法query()。从变量的命名上,也能找到一点线索,unstableProvider和stableProvider,前者是不稳定的provider,后者是稳定的provider。什么样表示稳定的,什么样表示不稳定的?从上面的代码来看,不稳定的provider,调用query()方法会抛出DeadObjectException。下面先看看unstableProvider的赋值过程:

public final IContentProvider acquireExistingProvider(......) {    synchronized (mProviderMap) {        final ProviderKey key = new ProviderKey(auth, userId);        final ProviderClientRecord pr = mProviderMap.get(key);        if (pr == null) {            return null;        }        IContentProvider provider = pr.mProvider;        IBinder jBinder = provider.asBinder();        ......        return provider;    }}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

可见unstableProvider是从变量mProviderMap的实例中遍历出来,也就是说,在调用者的进程内部,对provider会缓存到mProviderMap这个变量中。而IContentProvider是一个跨进程的远程调用。换句话说,调用者的进程内部所缓存的unstableProvider实例所对应的远程进程不能保证还正常运行着,如果所对应的远程进程没有运行,那么就会抛出DeadObjectException异常,并调用unstableProviderDied()方法把本地的缓存清除。然后通过acquireProvider()重新生产一个新的stableProvider,且Android系统会启动和stableProvider对应的远程进程,这个过程下文会阐述。可见Android这个举措是为了性能考虑,目的让APP的运行仅可能的快。

获取ContentProvider

回到上文中实例化变量unstableProvider和stableProvider的代码,unstableProvider或stableProvider实例化后,直接调用query()方法,然后直接就可以返回Cursor给调用者了,说明在这里的query()这一步,已经拿到调用者需要的数据。所以理解unstableProvider和stableProvider的实质至关重要。那么unstableProvider和stableProvider所对应的远程进程的服务是哪一个呢?是不是就直接对应ContentProvider呢?

由于unstableProvider是一个调用者进程中缓存的实例,所以需要对stableProvider下手,了解stableProvider的实例化过程即可,如下:

public final IContentProvider acquireProvider(......) {    ......    IActivityManager.ContentProviderHolder holder = null;    try {        holder = ActivityManagerNative.getDefault().getContentProvider(                getApplicationThread(), auth, userId, stable);    } catch (RemoteException ex) {        throw ex.rethrowFromSystemServer();    }    ......    return holder.provider;}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

stableProvider被封装到ContentProviderHolder的变量中provider中。通过调用ActivityManagerNative.getContentProvider()获取ContentProviderHolder,ActivityManagerNative的所对应的远程服务是system_process中的ActivityManagerService,接着看getContentProvider()这个方法:

public final ContentProviderHolder getContentProvider(        IApplicationThread caller, String name, int userId, boolean stable) {    ......    return getContentProviderImpl(caller, name, null, stable, userId);}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

这里直接调用了getContentProviderImpl()方法:

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,        String name, IBinder token, boolean stable, int userId) {    ContentProviderRecord cpr;    ContentProviderConnection conn = null;    synchronized(this) {        ......        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;        if (providerRunning) {            ......        }        if (!providerRunning) {            ......            // If the provider is not already being launched, then get it            // started.            if (i >= N) {                try {                    // Content provider is now in use, its package can't be stopped.                    ......                    if (proc != null && proc.thread != null && !proc.killed) {                        ......                    } else {                        proc = startProcessLocked(cpi.processName,                                cpr.appInfo, false, 0, "content provider",                                new ComponentName(cpi.applicationInfo.packageName,                                        cpi.name), false, false, false);                       ......                    }                    cpr.launchingApp = proc;                    mLaunchingProviders.add(cpr);                } finally {                    Binder.restoreCallingIdentity(origId);                }            }            ......            mProviderMap.putProviderByName(name, cpr);            conn = incProviderCountLocked(r, cpr, token, stable);            if (conn != null) {                conn.waiting = true;            }        }    }    // Wait for the provider to be published...    synchronized (cpr) {        while (cpr.provider == null) {            ......                cpr.wait();            ......        }    }    return cpr != null ? cpr.newHolder(conn) : null;}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

由于这个方法的代码篇幅非常大,这里省略了很多代码,省略的代码主要就是一些缓存、权限等等相关的代码。这里假设provider的进程没有启动,从最原始,最干净的时候分析ContentProvider的这个过程。聚焦上面的代码,首先分两种情况,providerRunning和!providerRunning,providerRunning是基于!providerRunning为前提的,因此provider第一次启动是运行!providerRunning这个代码路径。假若provider没有运行过,Android首先通过startProcessLocked()把provider所在的应用启动起来,这个过程这里暂时先放下,继续往下看,在最后面,有一个while循环,循环条件是cpr.provider == null?这里会一直等待cpr的provider变量被赋值,回到上文中的acquireProvider()方法的代码,acquireProvider()首先要获取的是ContentProviderHolder的实例,上面的代码如果cpr != null,就返回一个ContentProviderHolder对象(cpr.newHolder(conn))。所以这里的cpr.provider就是上文中acquireProvider()需要获取的IContentProvider的实例对象。

公布ContentProvider

因此,只要继续分析清楚cpr.provider的赋值过程,就知道开始的时候ContentResolver.query()所调用的真正的远程服务。回到上面的代码,startProcessLocked()启动应用时,运行到如下代码(APP的启动过程本文不再赘述):

public static void main(String[] args) {    ......    Looper.prepareMainLooper();    ActivityThread thread = new ActivityThread();    thread.attach(false);    ......}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

生成ActivityThread实例,也就是常说的主线程(UI线程了),然后调用attach()方法:

private void attach(boolean system) {    ......    final IActivityManager mgr = ActivityManagerNative.getDefault();    try {        mgr.attachApplication(mAppThread);    } catch (RemoteException ex) {        throw ex.rethrowFromSystemServer();    }    ......}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

又回到ActivityManagerService了,接着往下看:

public final void attachApplication(IApplicationThread thread) {    ......    attachApplicationLocked(thread, callingPid);    ......}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

这里没有需要看的代码,继续往下跟踪:

 private final boolean attachApplicationLocked(IApplicationThread thread,.....) {    List providers = normalMode ? generateApplicationProvidersLocked(app) : null;    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,......);}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

IApplicationThread实例thread是远程APP的远程调用端,所以thread.bindApplication()实际又从system_process进程回到了APP所在的进程,注意第三个参数providers,providers是封装了应用的所有的ContentProvider,详情读者可以阅读generateApplicationProvidersLocked(app)方法,本文不再阐述。继续往下看:

public final void bindApplication(String processName, ApplicationInfo appInfo,        List providers, ComponentName instrumentationName,......) {    ......    data.providers = providers;    data.compatInfo = compatInfo;    data.initProfilerInfo = profilerInfo;    sendMessage(H.BIND_APPLICATION, data);}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

发送了一个H.BIND_APPLICATION的消息,注意data.providers = providers。该消息的处理是在:

private void handleBindApplication(AppBindData data) {if (!data.restrictedBackupMode) {    if (!ArrayUtils.isEmpty(data.providers)) {        installContentProviders(app, data.providers);        ......    }}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

调用了installContentProviders()方法,注意参数data.providers,如下:

private void installContentProviders(        Context context, List providers) {    final ArrayList results =        new ArrayList();    for (ProviderInfo cpi : providers) {        IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);        if (cph != null) {            cph.noReleaseNeeded = true;            results.add(cph);        }    }    try {        ActivityManagerNative.getDefault().publishContentProviders(            getApplicationThread(), results);    } catch (RemoteException ex) {        throw ex.rethrowFromSystemServer();    }}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

把应用的所有的ContentProvider信息封装到ContentProviderHolder中,这里要回到上文中acquireProvider()方法,获取IContentProvider的实例正好是ContentProviderHolder的中的变量provider,因此,这里需要了解上面代码ContentProviderHolder的实例cph的实例化过程,看installProvider()方法:

private IActivityManager.ContentProviderHolder installProvider(Context context,        IActivityManager.ContentProviderHolder holder, ProviderInfo info,.....) {    ContentProvider localProvider = null;    IContentProvider provider;    if (holder == null || holder.provider == null) {        ......        try {            final java.lang.ClassLoader cl = c.getClassLoader();            localProvider = (ContentProvider)cl.                loadClass(info.name).newInstance();            provider = localProvider.getIContentProvider();            ......    IActivityManager.ContentProviderHolder retHolder;    synchronized (mProviderMap) {        IBinder jBinder = provider.asBinder();        if (localProvider != null) {            ComponentName cname = new ComponentName(info.packageName, info.name);            ProviderClientRecord pr = mLocalProvidersByName.get(cname);            if (pr != null) {                ......            } else {                holder = new IActivityManager.ContentProviderHolder(info);                holder.provider = provider;                ......            }            retHolder = pr.mHolder;        } else {            ......    return retHolder;}

这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

上面的代码通过ClassLoader映射ContentProvider的对象实例,然后调用getIContentProvider()方法,获取到IContentProvider的实例provider,然后赋值给ContentProviderHolder的实例holder的变量provider,所以provider正是acquireProvider()中获取的的IContentProvider的实例,而继续看getIContentProvider()方法查看provider的本质是:

......private Transport mTransport = new Transport();public IContentProvider getIContentProvider() {    return mTransport;}class Transport extends ContentProviderNative {    public Cursor query(.....){        ......    }    ......}......

这个代码定义在文件frameworks/base/core/java/android/content/ContentProvider.java中。

上面的代码可见,provider实质是Transport的实例mTransport,Transport是ContentProviderNative的子类,而ContentProviderNative是IContentProvider的子类。

下面继续看看provider和ActivityManagerService的关系,回到上文中的installContentProviders()方法,调用了publishContentProviders()方法,如下:

public final void publishContentProviders(IApplicationThread caller,        List providers) {    ......    final int N = providers.size();    for (int i = 0; i < N; i++) {        ContentProviderHolder src = providers.get(i);        if (src == null || src.info == null || src.provider == null) {            continue;        }        ContentProviderRecord dst = r.pubProviders.get(src.info.name);        if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);        if (dst != null) {            ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);            mProviderMap.putProviderByClass(comp, dst);            String names[] = dst.info.authority.split(";");            for (int j = 0; j < names.length; j++) {                mProviderMap.putProviderByName(names[j], dst);            }            ......            synchronized (dst) {                dst.provider = src.provider;                dst.proc = r;                dst.notifyAll();            }        }    }}

这个代码定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

把应用的ContentProvider信息缓存到mProviderMap中,这里重点关注语句dst.provider = src.provider,回到上文中getContentProviderImpl()方法中的代码,后面的while循环,等待cpr.provider的赋值,dst.provider = src.provider正好就是这个赋值过程,cpr.provider赋值后,getContentProviderImpl()返回ContentProviderHolder的实例cpr.newHolder(conn),而这个实例持有变量provider指向Transport的实例mTransport,也就是应用的ContentProvider。

关系图

这个过程非常绕乱人的头绪,下面把这个过程简单转换成一张简单的关系图,理清这个过程和关系,如下:

ContentProvider数据监听

观察者注册过程

有时APP开发的时候,APP运行时,需要实时监听一些ContentProvider数据的变化。如用户添加了一个联系人,APP需要接收到联系人添加的通知。由于ContentProvider的提供者,和需求者不是同一个APP,所以,这个通知的纽带,就需要ContentService来完成。从注册一个观察者开始,分析这个通知的来龙去脉,注册代码如下:

ContentResolver cr = getContentResolver();cr.registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants,            @NonNull ContentObserver observer);

当ContentProvider的数据发生变化时,便会回调到ContentObserver的onChange()方法,观察者ContentObserver observer被注册到哪里去呢?继续进入分析:

public final void registerContentObserver(Uri uri, boolean notifyForDescendents,        ContentObserver observer, @UserIdInt int userHandle) {    try {        getContentService().registerContentObserver(uri, notifyForDescendents,                observer.getContentObserver(), userHandle);    } catch (RemoteException e) {    }}

这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。

上面的代码getContentService()获取到的对象是:

public static IContentService getContentService() {    if (sContentService != null) {        return sContentService;    }    IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME);    if (false) Log.v("ContentService", "default service binder = " + b);    sContentService = IContentService.Stub.asInterface(b);    if (false) Log.v("ContentService", "default service = " + sContentService);    return sContentService;}

这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。

阅读《Android系统之System Server大纲 》可知,启动的CONTENT_SERVICE_NAME的系统服务如下:

private static final String CONTENT_SERVICE_CLASS =            "com.android.server.content.ContentService$Lifecycle";traceBeginAndSlog("StartContentService");mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

这个方法定义在文件frameworks/base/services/java/com/android/server/SystemServer.java中。

所以getContentService()获取到的是ContentService,继续往下分析registerContentObserver():

public void registerContentObserver(Uri uri, boolean notifyForDescendants,                                    IContentObserver observer, int userHandle) {    ......    synchronized (mRootNode) {        mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,                uid, pid, userHandle);        if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +                " with notifyForDescendants " + notifyForDescendants);    }}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/content/ContentService.java中。

上面的代码把观察者observer通过addObserverLocked放置在mRootNode对象中

private void addObserverLocked(Uri uri, int index, IContentObserver observer,                               boolean notifyForDescendants, Object observersLock,                               int uid, int pid, int userHandle) {    // If this is the leaf node add the observer    if (index == countUriSegments(uri)) {        mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,                uid, pid, userHandle));        return;    }    // Look to see if the proper child already exists    String segment = getUriSegment(uri, index);    int N = mChildren.size();    for (int i = 0; i < N; i++) {        ObserverNode node = mChildren.get(i);        if (node.mName.equals(segment)) {            node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,                    observersLock, uid, pid, userHandle);            return;        }    }    // No child found, create one    ObserverNode node = new ObserverNode(segment);    mChildren.add(node);    node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,            observersLock, uid, pid, userHandle);    }

这个方法定义在文件frameworks/base/services/core/java/com/android/server/content/ContentService.java中。

首先把观察者observer再次封装到mObservers中,mObservers是ArrayList的实例,后面依次遍历整个需要监听的Uri,用segment生产一个ObserverNode实例,保存在ArrayList的实例mChildren中。

观察者都被封装好以后,就等待数据的变化了。在上文ContentProvider的原理中,可知,ContentProvider的需求者拿到ContentProvider提供者的远程调用后,两个APP直接进行交互了,任何数据变化并没有经过ContentService,因此,ContentService是如何监测ContentProvider数据发生变化并通知到观察者呢?这里的机制便是ContentProvider提供者的数据发生变化时,ContentProvider提供者必须主动通过notifyChange()方法通知ContentService数据发生了变化。下面以联系人的数据库变化为例,阐述这个过程。

数据变化通知过程

添加一个联系人,调用ContactsProvider的insert()方法,如下:

public Uri insert(Uri uri, ContentValues values) {    incrementStats(mInsertStats, mInsertInBatchStats);    ContactsTransaction transaction = startTransaction(false);    try {        Uri result = insertInTransaction(uri, values);        if (result != null) {            transaction.markDirty();        }        transaction.markSuccessful(false);        return result;    } finally {        endTransaction(false);    }}

这个方法定义在文件packages/providers/ContactsProvider/src/com/android/providers/contacts/AbstractContactsProvider.java中。

上面的代码中,一次插入的业务抽象成一个ContactsTransaction,然后调用insertInTransaction()方法把数据插入数据库成功后,调用transaction.markDirty()标记当前的数据状态有变化,然后调用endTransaction()结束当前的业务。如下:

private void endTransaction(boolean callerIsBatch) {    ContactsTransaction transaction = mTransactionHolder.get();    if (transaction != null && (!transaction.isBatch() || callerIsBatch)) {        boolean notify = false;        try {            if (transaction.isDirty()) {                notify = true;            }            transaction.finish(callerIsBatch);            if (notify) {                notifyChange();            }        } finally {            // No matter what, make sure we clear out the thread-local transaction reference.            mTransactionHolder.set(null);        }    }}

这个方法定义在文件packages/providers/ContactsProvider/src/com/android/providers/contacts/AbstractContactsProvider.java中。

上面的代码,通过mTransactionHolder.get()获取刚刚进行的业务transaction,如果的这个业务被标记为markDirty(),transaction.isDirty()返回true,所以notify被置成true,所以会调用notifyChange()。往下看这个方法:

protected void notifyChange(boolean syncToNetwork, boolean syncToMetadataNetwork) {    getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null,            syncToNetwork);    getContext().getContentResolver().notifyChange(MetadataSync.METADATA_AUTHORITY_URI,            null, syncToMetadataNetwork);}

这个方法定义在文件packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsProvider2.java中。

上面的代码,获取到ContentResolver()对象,和query()类似,然后调用notifyChange()通知ContentResolver数据发生了变化,如下:

public void notifyChange(@NonNull Uri uri, ContentObserver observer, boolean syncToNetwork,        @UserIdInt int userHandle) {    try {        getContentService().notifyChange(                uri, observer == null ? null : observer.getContentObserver(),                observer != null && observer.deliverSelfNotifications(),                syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,                userHandle);    } catch (RemoteException e) {    }}

这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。

上面的代码调用getContentService()方法,从上文可知,getContentService()获取到的是ContentService的远程调用,因此getContentService().notifyChange()实质会运行到ContentService的notifyChange()方法,如下:

public void notifyChange(Uri uri, ......) {    ......    try {        ArrayList calls = new ArrayList();        synchronized (mRootNode) {            mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,                    flags, userHandle, calls);        }        final int numCalls = calls.size();        for (int i=0; itry {                oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);            } catch (RemoteException ex) {                ......            }        }        ......        }    } finally {        restoreCallingIdentity(identityToken);    }}

这个方法定义在文件frameworks/base/services/core/java/com/android/server/content/ContentService.java中。

上面的代码中的mRootNode变量,在注册观察者的章节中,mRootNode封装了所有的观察者。调用collectObserversLocked()根据观察者监听的Uri类型把观察者封装到ArrayList的实例calls中,然后调用oc.mObserver.onChange()方法通知APP数据发生变化。

总结

本文详细阐述了ContentProvider的原理,从ContentProvider的query过程入手,全面详细分析了从query()的发起APP到ActivityManagerService,再到ContentProvider提供程序的整个流程和交互过程。以及分析了ContentService在ContentProvider的数据变化监测通知的架构中,扮演了观察者模式中的抽象主题,具体主题部分。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android(安卓)WebView 开发详解(一)
  5. Android中widget组件的开发流程
  6. android 进程优先级
  7. android的adb详解(多设备时adb调用)
  8. Android手动显示和隐藏软键盘方法总结
  9. Testing和Instrumentation

随机推荐

  1. Android操作HTTP实现与服务器通信
  2. android中activity的四种加载模式
  3. 转:android listView 继承ListActivity的
  4. Android深入浅出之Zygote[1]
  5. Android(安卓)SDK安装Android4.0“冰激淋
  6. Android(安卓)快速开发框架:推荐10个框架
  7. Android中解析XML
  8. Android(安卓)中LayoutInflater(布局加载
  9. Android(安卓)DexClassLoader动态加载类
  10. Android(安卓)全景框架了解