美文网首页
基于Andoird 4.2.2的同步框架源代码学习——同步发起端

基于Andoird 4.2.2的同步框架源代码学习——同步发起端

作者: 4528283108ee | 来源:发表于2015-07-22 09:08 被阅读63次

    关键组件:
    ContentResolver
    ContentService
    SyncManager
    SyncManager.ActiveSyncContext
    SyncManager.SyncOperation
    SyncManager.SyncHandler
    ContentResolver
    外部的应用程序通过调用ContentResolve.requestSync()静态方法发起同步:


    [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) {
            }
        }
    方法接收三个参数:

    - account:需要同步的帐号

    - authority:需要进行同步的authority

    - extras:需要传递给sync adapter的附加数据

    在这里,getContentService()方法返回系统服务ContentService的代理对象,然后通过它远程调用ContentService.requestSync()。


    ContentService
    ContentService是Android系统服务,它提供一系列数据同步及数据访问等相关的操作。它的行为在IContentService.aidl中描述。

    这里,通过远程调用ContentService.requestSync()方法来启动针对指定帐号(account)的指定内容(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 */);
                }
            }
            ...
        }
    在这个方法中,会获取一个SyncManager类的实例。顾名思义,SyncManager管理与同步相关的处理。


    SyncManager

    [java]
    public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority, 
            Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) { 
        ... 
        final boolean backgroundDataUsageAllowed = !mBootCompleted || 
                getConnectivityManager().getBackgroundDataSetting(); 
        ... 
         
        // 产生一个同步帐户列表。对于手动同步,列表中仅有一个AccountUser元素,它封装了需要同步的帐号以及对应的应用程序(userId)  
        AccountAndUser[] accounts; 
        if (requestedAccount != null && userId != UserHandle.USER_ALL) { 
            accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) }; 
        } 
        ... 
        for (AccountAndUser account : accounts) { 
            // 在这里,会扫描系统中所有提供了sync adapter的service:根据intent filter  
            // 然后从得到service info中取得各自的authority。service info从对应服务的meta-data标签中指定的sync adapter描述文件中解析出来。  
            final HashSet<String> syncableAuthorities = new HashSet<String>(); 
            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> 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<SyncAdapterType> 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();
            ...
           
            // 产生一个同步帐户列表。对于手动同步,列表中仅有一个AccountUser元素,它封装了需要同步的帐号以及对应的应用程序(userId)
            AccountAndUser[] accounts;
            if (requestedAccount != null && userId != UserHandle.USER_ALL) {
                accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
            }
            ...
            for (AccountAndUser account : accounts) {
                // 在这里,会扫描系统中所有提供了sync adapter的service:根据intent filter
                // 然后从得到service info中取得各自的authority。service info从对应服务的meta-data标签中指定的sync adapter描述文件中解析出来。
                final HashSet<String> syncableAuthorities = new HashSet<String>();
                for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> 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<SyncAdapterType> 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));
                    }
                    ...
                }
            }
        }
    这里,首先从系统中筛选出符合限定条件的service的信息,然后发起对应的同步。

    首先为每一个同步操作生成一个SyncOperation实例,它封装了同步操作需要的全部信息:


    [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;
    然后调用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实例插入队列mSyncQueue然后向SyncManager中定义的SyncHandler发送消息,通知其队列发生变化:


    [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处理这个消息:


    [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()方法经过一系列的检查,确认执行同步的全部条件已经达到之后,对SyncOperation进行分发:


    [java]
    private long maybeStartNextSyncLocked() { 
            ... 
            dispatchSyncOperation(candidate); 
        } 
     
        return nextReadyToRunTime; 

            private long maybeStartNextSyncLocked() {
                    ...
                    dispatchSyncOperation(candidate);
                }

                return nextReadyToRunTime;
            }
    接下来,将绑定到提供sync adapter的应用程序中对应的service:

    [java]
    private boolean dispatchSyncOperation(SyncOperation op) { 
        ... 
        // connect to the sync adapter  
        SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type); 
        final RegisteredServicesCache.ServiceInfo<SyncAdapterType> 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<SyncAdapterType> 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()中创建相应的Intent,发起绑定。

    然后,因为本类实现了ServiceConnection接口,所以当绑定成功时,将回调本类的onServiceConnected()方法。在这个回调中,向SyncHandler发送一条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;
                        }
    这里主要就是调用了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); 
        } 
        ... 

    相关文章

      网友评论

          本文标题:基于Andoird 4.2.2的同步框架源代码学习——同步发起端

          本文链接:https://www.haomeiwen.com/subject/lvipqttx.html