ContentService是Android平台中数据更新通知的执行者。本文介绍下ContentService的创建,向服务注册ContentObserver流程,以及通过服务进行数据更新通知流程。
首先看下ContentService的创建:
进入系统服务SystemServer中的startOtherServices方法,有如下这边代码:
mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
其中CONTENT_SERVICE_CLASS是:
private static final String CONTENT_SERVICE_CLASS =
"com.android.server.content.ContentService$Lifecycle";
接着进入SystemServiceManager中的startService:
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
final String name = serviceClass.getName();
final T service;
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
mServices.add(service);
service.onStart();
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
通过反射创建ContentService.Lifecycle实例,然后调用onStart方法:
public void onStart() {
final boolean factoryTest = (FactoryTest
.getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL);
mService = new ContentService(getContext(), factoryTest);
publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mService);
}
protected final void publishBinderService(String name, IBinder service) {
publishBinderService(name, service, false);
}
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated) {
ServiceManager.addService(name, service, allowIsolated);
}
可以看到最终将该服务发布到服务总管里面。
下面来跟踪下通知机制实施的第一步,即注册ContentObserver。该步骤由ContentResolver提供的registerContentObserver函数来实现
public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants,
@NonNull ContentObserver observer) {
Preconditions.checkNotNull(uri, "uri");
Preconditions.checkNotNull(observer, "observer");
registerContentObserver(
ContentProvider.getUriWithoutUserId(uri),
notifyForDescendants,
observer,
ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
}
/** @hide - designated user version */
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
ContentObserver observer, @UserIdInt int userHandle) {
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
observer.getContentObserver(), userHandle);
} catch (RemoteException e) {
}
}
其中uri是客户端设置的它需要监听的数据项的地址,observer是客户端设置的监听对象。下面看下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;
}
可以看到先从服务总管获取ContentService的binder对象,通过IContentService.Stub.asInterface(b)来获取本地代理,调用代理对象的registerContentObserver会通过binder机制跳转到服务的实现者,也就是实现IContentService.Stub的类ContentService:
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);
}
}
其中mRootNode是ObserverNode类型对象。调用addObserverLocked肯定是保存数据了。
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);
if (segment == null) {
throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer");
}
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);
}
仔细研究发现ObserverNode是以树的组织形式存在。最终的子节点为ObserverEntry,它保存着uri和对应的IContentObserver对象。这个IContentObserver对象看上去很像binder对象。返回去看下注册的时候客户端传递的是什么。
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
ContentObserver observer, @UserIdInt int userHandle) {
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
observer.getContentObserver(), userHandle);
} catch (RemoteException e) {
}
}
回到ContentResolver的registerContentObserver可到传递的是observer.getContentObserver()对象。它返回什么呢?
进一步跟踪发现它返回ContentObserver中的内部类Transport对象。
public IContentObserver getContentObserver() {
synchronized (mLock) {
if (mTransport == null) {
mTransport = new Transport(this);
}
return mTransport;
}
}
看下Transport:
private static final class Transport extends IContentObserver.Stub {
private ContentObserver mContentObserver;
public Transport(ContentObserver contentObserver) {
mContentObserver = contentObserver;
}
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
ContentObserver contentObserver = mContentObserver;
if (contentObserver != null) {
contentObserver.dispatchChange(selfChange, uri, userId);
}
}
public void releaseContentObserver() {
mContentObserver = null;
}
}
它继承IContentObserver.Stub,看来是服务的实现者(这里客户端作为服务端),里面保存着ContentObserver对象,并且看到onChange方法,猜测客户端那边肯定要调用该方法。
下面看下数据更新流程,数据通知是通过ContentResolver的notifyChange触发。
这里举例联系人的数据库的增删改函数最后都会调用endTransaction,这个方法里面会调用下面函数:
protected void notifyChange(boolean syncToNetwork) {
getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null,
syncToNetwork);
}
下面进入ContentResolver的notifyChange跟踪:
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) {
}
}
这里同样是IPC通信,通过binder机制进入到服务的实现者ContentService:
public void notifyChange(Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, int flags,
int userHandle) {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
flags, userHandle, calls);
}
final int numCalls = calls.size();
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
+ uri);
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
IBinder binder = oc.mObserver.asBinder();
final ArrayList<ObserverNode.ObserverEntry> list
= oc.mNode.mObservers;
int numList = list.size();
for (int j=0; j<numList; j++) {
ObserverNode.ObserverEntry oe = list.get(j);
if (oe.observer.asBinder() == binder) {
list.remove(j);
j--;
numList--;
}
}
}
}
}
}
这里通过ObserverNode来收集observer信息,下面看下collectObserversLocked的实现:
public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
boolean observerWantsSelfNotifications, int flags,
int targetUserHandle, ArrayList<ObserverCall> calls) {
String segment = null;
int segmentCount = countUriSegments(uri);
if (index >= segmentCount) {
// This is the leaf node, notify all observers
if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName);
collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
flags, targetUserHandle, calls);
} else if (index < segmentCount){
segment = getUriSegment(uri, index);
if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / "
+ segment);
// Notify any observers at this level who are interested in descendants
collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
flags, targetUserHandle, calls);
}
int N = mChildren.size();
for (int i = 0; i < N; i++) {
ObserverNode node = mChildren.get(i);
if (segment == null || node.mName.equals(segment)) {
// We found the child,
node.collectObserversLocked(uri, index + 1, observer,
observerWantsSelfNotifications, flags, targetUserHandle, calls);
if (segment != null) {
break;
}
}
}
}
仔细研究发现它会遍历以ObserverNode对节点的树,一旦找到对应的节点就会调用collectMyObserversLocked来收集observercall对象:
private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
boolean observerWantsSelfNotifications, int flags,
int targetUserHandle, ArrayList<ObserverCall> calls) {
int N = mObservers.size();
IBinder observerBinder = observer == null ? null : observer.asBinder();
for (int i = 0; i < N; i++) {
ObserverEntry entry = mObservers.get(i);
calls.add(new ObserverCall(this, entry.observer, selfChange,
UserHandle.getUserId(entry.uid)));
}
}
可以看到把子节点ObserverEntry信息取出,重新创建ObserverCall对象添加到列表里面。这里注意看到entry.observer这个binder对象。前面分析过它的真正实现在客户端ContentObserver中的内部类Transport里面。
收集完后调用oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);通过binder机制就会通知到客户端数据的更新。