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

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。

关系图

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

Android System Server大纲之ContentService和ContentProvider原理剖析_第1张图片

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的数据变化监测通知的架构中,扮演了观察者模式中的抽象主题,具体主题部分。

你可能感兴趣的:(Android,system,server,area,Android,system,Android系统服务,内容提供商,内容观察者,监听Provider)