關(guān)鍵組件:
ContentResolver
ContentService
SyncManager
SyncManager.ActiveSyncContext
SyncManager.SyncOperation
SyncManager.SyncHandler
ContentResolver
外部的應(yīng)用程序通過調(diào)用ContentResolve.requestSync()靜態(tài)方法發(fā)起同步:
[java]
/**
* @param account which account should be synced
* @param authority which authority should be synced
* @param extras any extras to pass to the SyncAdapter.
*/
public static void requestSync(Account account, String authority, Bundle extras) {
validateSyncExtrasBundle(extras);
try {
getContentService().requestSync(account, authority, extras);
} catch (RemoteException e) {
}
}
/**
* @param account which account should be synced
* @param authority which authority should be synced
* @param extras any extras to pass to the SyncAdapter.
*/
public static void requestSync(Account account, String authority, Bundle extras) {
validateSyncExtrasBundle(extras);
try {
getContentService().requestSync(account, authority, extras);
} catch (RemoteException e) {
}
}
方法接收三個(gè)參數(shù):
- account:需要同步的帳號(hào)
- authority:需要進(jìn)行同步的authority
- extras:需要傳遞給sync adapter的附加數(shù)據(jù)
在這里训貌,getContentService()方法返回系統(tǒng)服務(wù)ContentService的代理對象扶歪,然后通過它遠(yuǎn)程調(diào)用ContentService.requestSync()北专。
ContentService
ContentService是Android的系統(tǒng)服務(wù)吼和,它提供一系列數(shù)據(jù)同步及數(shù)據(jù)訪問等相關(guān)的操作兼蕊。它的行為在IContentService.aidl中描述。
這里,通過遠(yuǎn)程調(diào)用ContentService.requestSync()方法來啟動(dòng)針對指定帳號(hào)(account)的指定內(nèi)容(authority)的同步:
[java]
public void requestSync(Account account, String authority, Bundle extras) {
...
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
false /* onlyThoseWithUnkownSyncableState */);
}
}
...
}
public void requestSync(Account account, String authority, Bundle extras) {
...
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
false /* onlyThoseWithUnkownSyncableState */);
}
}
...
}
在這個(gè)方法中砌函,會(huì)獲取一個(gè)SyncManager類的實(shí)例。顧名思義,SyncManager管理與同步相關(guān)的處理讹俊。
SyncManager
[java]
public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority,
Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
...
final boolean backgroundDataUsageAllowed = !mBootCompleted ||
getConnectivityManager().getBackgroundDataSetting();
...
// 產(chǎn)生一個(gè)同步帳戶列表垦沉。對于手動(dòng)同步,列表中僅有一個(gè)AccountUser元素仍劈,它封裝了需要同步的帳號(hào)以及對應(yīng)的應(yīng)用程序(userId)
AccountAndUser[] accounts;
if (requestedAccount != null && userId != UserHandle.USER_ALL) {
accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
}
...
for (AccountAndUser account : accounts) {
// 在這里厕倍,會(huì)掃描系統(tǒng)中所有提供了sync adapter的service:根據(jù)intent filter
// 然后從得到service info中取得各自的authority。service info從對應(yīng)服務(wù)的meta-data標(biāo)簽中指定的sync adapter描述文件中解析出來贩疙。
final HashSet syncableAuthorities = new HashSet();
for (RegisteredServicesCache.ServiceInfo syncAdapter :
mSyncAdapters.getAllServices(account.userId)) {
syncableAuthorities.add(syncAdapter.type.authority);
}
...
for (String authority : syncableAuthorities) {
// 檢查帳戶是否能夠同步
int isSyncable = mSyncStorageEngine.getIsSyncable(account.account, account.userId,
authority);
if (isSyncable == 0) {
continue;
}
final RegisteredServicesCache.ServiceInfo syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(
SyncAdapterType.newKey(authority, account.account.type), account.userId);
...
if (isSyncable < 0) {
Bundle newExtras = new Bundle();
newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
...
// 部署同步操作
scheduleSyncOperation(
new SyncOperation(account.account, account.userId, source, authority,
newExtras, 0, backoffTime, delayUntil, allowParallelSyncs));
}
...
}
}
}
public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority,
Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
...
final boolean backgroundDataUsageAllowed = !mBootCompleted ||
getConnectivityManager().getBackgroundDataSetting();
...
// 產(chǎn)生一個(gè)同步帳戶列表绑青。對于手動(dòng)同步,列表中僅有一個(gè)AccountUser元素屋群,它封裝了需要同步的帳號(hào)以及對應(yīng)的應(yīng)用程序(userId)
AccountAndUser[] accounts;
if (requestedAccount != null && userId != UserHandle.USER_ALL) {
accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
}
...
for (AccountAndUser account : accounts) {
// 在這里闸婴,會(huì)掃描系統(tǒng)中所有提供了sync adapter的service:根據(jù)intent filter
// 然后從得到service info中取得各自的authority。service info從對應(yīng)服務(wù)的meta-data標(biāo)簽中指定的sync adapter描述文件中解析出來芍躏。
final HashSet syncableAuthorities = new HashSet();
for (RegisteredServicesCache.ServiceInfo syncAdapter :
mSyncAdapters.getAllServices(account.userId)) {
syncableAuthorities.add(syncAdapter.type.authority);
}
...
for (String authority : syncableAuthorities) {
// 檢查帳戶是否能夠同步
int isSyncable = mSyncStorageEngine.getIsSyncable(account.account, account.userId,
authority);
if (isSyncable == 0) {
continue;
}
final RegisteredServicesCache.ServiceInfo syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(
SyncAdapterType.newKey(authority, account.account.type), account.userId);
...
if (isSyncable < 0) {
Bundle newExtras = new Bundle();
newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
...
// 部署同步操作
scheduleSyncOperation(
new SyncOperation(account.account, account.userId, source, authority,
newExtras, 0, backoffTime, delayUntil, allowParallelSyncs));
}
...
}
}
}
這里邪乍,首先從系統(tǒng)中篩選出符合限定條件的service的信息,然后發(fā)起對應(yīng)的同步对竣。
首先為每一個(gè)同步操作生成一個(gè)SyncOperation實(shí)例庇楞,它封裝了同步操作需要的全部信息:
[java]
public class SyncOperation implements Comparable {
public final Account account;
public final int userId;
public int syncSource;
public String authority;
public final boolean allowParallelSyncs;
public Bundle extras;
public final String key;
public long earliestRunTime;
public boolean expedited;
public SyncStorageEngine.PendingOperation pendingOperation;
public Long backoff;
public long delayUntil;
public long effectiveRunTime;
public class SyncOperation implements Comparable {
public final Account account;
public final int userId;
public int syncSource;
public String authority;
public final boolean allowParallelSyncs;
public Bundle extras;
public final String key;
public long earliestRunTime;
public boolean expedited;
public SyncStorageEngine.PendingOperation pendingOperation;
public Long backoff;
public long delayUntil;
public long effectiveRunTime;
然后調(diào)用scheduleSyncOperation方法:
[java]
public void scheduleSyncOperation(SyncOperation syncOperation) {
boolean queueChanged;
synchronized (mSyncQueue) {
queueChanged = mSyncQueue.add(syncOperation);
}
if (queueChanged) {
...
sendCheckAlarmsMessage();
}
...
}
public void scheduleSyncOperation(SyncOperation syncOperation) {
boolean queueChanged;
synchronized (mSyncQueue) {
queueChanged = mSyncQueue.add(syncOperation);
}
if (queueChanged) {
...
sendCheckAlarmsMessage();
}
...
}
首先將SyncOperation實(shí)例插入隊(duì)列mSyncQueue然后向SyncManager中定義的SyncHandler發(fā)送消息,通知其隊(duì)列發(fā)生變化:
[java]
private void sendCheckAlarmsMessage() {
...
mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS);
mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
}
private void sendCheckAlarmsMessage() {
...
mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS);
mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
}
隨后否纬,SyncHandler處理這個(gè)消息:
[java] v
public void handleMessage(Message msg) {
...
try {
...
switch (msg.what) {
...
case SyncHandler.MESSAGE_CHECK_ALARMS:
...
nextPendingSyncTime = maybeStartNextSyncLocked();
break;
}
}
...
}
public void handleMessage(Message msg) {
...
try {
...
switch (msg.what) {
...
case SyncHandler.MESSAGE_CHECK_ALARMS:
...
nextPendingSyncTime = maybeStartNextSyncLocked();
break;
}
}
...
}
這里吕晌,maybeStartNextSyncLocked()方法經(jīng)過一系列的檢查,確認(rèn)執(zhí)行同步的全部條件已經(jīng)達(dá)到之后临燃,對SyncOperation進(jìn)行分發(fā):
[java]
private long maybeStartNextSyncLocked() {
...
dispatchSyncOperation(candidate);
}
return nextReadyToRunTime;
}
private long maybeStartNextSyncLocked() {
...
dispatchSyncOperation(candidate);
}
return nextReadyToRunTime;
}
接下來睛驳,將綁定到提供sync adapter的應(yīng)用程序中對應(yīng)的service:
[java]
private boolean dispatchSyncOperation(SyncOperation op) {
...
// connect to the sync adapter
SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
final RegisteredServicesCache.ServiceInfo syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, op.userId);
...
ActiveSyncContext activeSyncContext =
new ActiveSyncContext(op, insertStartSyncEvent(op), syncAdapterInfo.uid);
activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
mActiveSyncContexts.add(activeSyncContext);
...
if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo, op.userId)) {
Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
closeActiveSyncContext(activeSyncContext);
return false;
}
return true;
}
private boolean dispatchSyncOperation(SyncOperation op) {
...
// connect to the sync adapter
SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
final RegisteredServicesCache.ServiceInfo syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, op.userId);
...
ActiveSyncContext activeSyncContext =
new ActiveSyncContext(op, insertStartSyncEvent(op), syncAdapterInfo.uid);
activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
mActiveSyncContexts.add(activeSyncContext);
...
if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo, op.userId)) {
Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
closeActiveSyncContext(activeSyncContext);
return false;
}
return true;
}
與前面的AccountManager非常的雷同,這里通過ActiveSyncContext類來完成service的綁定:
[java]
class ActiveSyncContext extends ISyncContext.Stub
implements ServiceConnection, IBinder.DeathRecipient {
...
public void onServiceConnected(ComponentName name, IBinder service) {
Message msg = mSyncHandler.obtainMessage();
msg.what = SyncHandler.MESSAGE_SERVICE_CONNECTED;
msg.obj = new ServiceConnectionData(this, ISyncAdapter.Stub.asInterface(service));
mSyncHandler.sendMessage(msg);
}
...
boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "bindToSyncAdapter: " + info.componentName + ", connection " + this);
}
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(info.componentName);
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.sync_binding_label);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
null, new UserHandle(userId)));
mBound = true;
final boolean bindResult = mContext.bindService(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
| Context.BIND_ALLOW_OOM_MANAGEMENT,
mSyncOperation.userId);
if (!bindResult) {
mBound = false;
}
return bindResult;
}
...
}
class ActiveSyncContext extends ISyncContext.Stub
implements ServiceConnection, IBinder.DeathRecipient {
...
public void onServiceConnected(ComponentName name, IBinder service) {
Message msg = mSyncHandler.obtainMessage();
msg.what = SyncHandler.MESSAGE_SERVICE_CONNECTED;
msg.obj = new ServiceConnectionData(this, ISyncAdapter.Stub.asInterface(service));
mSyncHandler.sendMessage(msg);
}
...
boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "bindToSyncAdapter: " + info.componentName + ", connection " + this);
}
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(info.componentName);
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.sync_binding_label);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
null, new UserHandle(userId)));
mBound = true;
final boolean bindResult = mContext.bindService(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
| Context.BIND_ALLOW_OOM_MANAGEMENT,
mSyncOperation.userId);
if (!bindResult) {
mBound = false;
}
return bindResult;
}
...
}其中膜廊,bindToSyncAdapter()中創(chuàng)建相應(yīng)的Intent乏沸,發(fā)起綁定。
然后爪瓜,因?yàn)楸绢悓?shí)現(xiàn)了ServiceConnection接口蹬跃,所以當(dāng)綁定成功時(shí),將回調(diào)本類的onServiceConnected()方法铆铆。在這個(gè)回調(diào)中蝶缀,向SyncHandler發(fā)送一條MESSAGE_SERVICE_CONNECTED消息。
緊接著薄货,輪到SyncHandler來處理消息:
case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
ServiceConnectionData msgData = (ServiceConnectionData)msg.obj;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
+ msgData.activeSyncContext);
}
// check that this isn't an old message
if (isSyncStillActive(msgData.activeSyncContext)) {
runBoundToSyncAdapter(msgData.activeSyncContext, msgData.syncAdapter);
}
break;
}
case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
ServiceConnectionData msgData = (ServiceConnectionData)msg.obj;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
+ msgData.activeSyncContext);
}
// check that this isn't an old message
if (isSyncStillActive(msgData.activeSyncContext)) {
runBoundToSyncAdapter(msgData.activeSyncContext, msgData.syncAdapter);
}
break;
}
這里主要就是調(diào)用了runBoundToSyncAdapter()方法:
[java]
private void runBoundToSyncAdapter(final ActiveSyncContext activeSyncContext,
ISyncAdapter syncAdapter) {
activeSyncContext.mSyncAdapter = syncAdapter;
final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
try {
...
syncAdapter.startSync(activeSyncContext, syncOperation.authority,
syncOperation.account, syncOperation.extras);
}
...
}