ContentService:第一部分数据更新和账户同步

ContentService的两大作用

android平台数据更新的执行者
android平台数据同步服务的管理中枢


目录

数据更新机制
数据同步机制之AccountManagerService
数据同步机制之SyncManager
ContentObserver概览

1.数据更新机制

通知机制的实施包括两个部分:
第一是:注册观察者
第二是:数据改变时通知观察者
在android平台中,这两个部分都离不开ContentService

1.1对ContentService的认识:ContentService创建的过程

概述:在SystemServer中调用ContentService的静态main方法来创建一个ContentService实例,并调用systemReady实例方法创建SyncManager。

继承关系:ContentService继承自 IContentService.Stub
IContentService.Stub继承自Binder并实现了IContentService接口

public final class ContentService extends IContentService.Stub
public static abstract class Stub extends android.os.Binder
 implements android.content.IContentService

第一个:SystemServer中调用ContentService的静态main函数创建ContentService,并调用systemReady函数来确定调用SyncManager是否成功

public void run{
       ...//
      contentService = ContentService.main(context,
                factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
       ...
            try {
                if (contentService != null)
                    contentService.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Content Service ready", e);
                }
} 

第二个:ContentService的静态main函数调用构造函数创建ContentService对象实例,并把该对象实例添加给ServiceManger

    public static ContentService main(Context context, boolean factoryTest) {
        ContentService service = new ContentService(context, factoryTest);
        ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
        return service;
    }

第三个:ContentService 的构造函数和systemReady函数

ContentService(Context context, boolean factoryTest) {
        mContext = context;
        mFactoryTest = factoryTest;
    }

    public void systemReady() {
        getSyncManager();
    }

第五个:getSyncManager函数

    private SyncManager getSyncManager() {
        synchronized(mSyncManagerLock) {
            try {
                // Try to create the SyncManager, return null if it fails 
                if (mSyncManager == null) 
                         mSyncManager = new SyncManager(mContext, mFactoryTest);
            } catch (SQLiteException e) {//创建异常
                Log.e(TAG, "Can't create SyncManager", e);
            }
            return mSyncManager;
        }
    }

1.2ContentResolver的registerContentObserver分析:更新机制的第一部分注册ContentObserver

1:ContentResolver的registerContentObserver
该方法会调用getContentService.registerContentObserver方法
uri:客户端设置的需要监听的数据项地址
notifyForDescendents:true则所有包含uri的数据发生变化都会触发通知,否则只有uri指定数据改变的会触发通知
observer:监听对象,当监听的数据发生改变时,该对象的onChange方法会被调用

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

2:getContentService方法
从ServiceManager中根据字符串CONTENT_SERVICE_NAME去获取ConentService实例对象
在ContentService 的main方法中,执行完ContentService 的构造函数之后有这样一行代码

 ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); 

也就是将CONTENT_SERVICE_NAME和contentService对象相关联

    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;
    }

3:observer.getContentObserver()

返回的是一个Transport类的对象实例
该类继承自IConentObserver.Stub
而IConentObserver.Stub继承了Binder同时实现了IConentObserver
所以Transport类用于Binder通信

    public IContentObserver getContentObserver() {
        synchronized (mLock) {
            if (mTransport == null) {
                mTransport = new Transport(this);
            }
            return mTransport;
        }
    }

4:ContentService 的registerContentObserver

这里实现的功能是:保存uri和observer的对应关系到其内部变量mRootNode中
mRootNode的类型是ObserverNode,ObserverNode的组织形式是树,其叶子节点是ObserverEntry,它保存了uri和对应的IContentObserver对象

    @Override
    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
            IContentObserver observer, int userHandle) { 
       ...
         synchronized (mRootNode) {
            mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
                    Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
           ...
        }
    }


1.3ContentResolver的notifyChange分析:更新机制的第二部分通知

通知由ContentResolver的notifyChange触发

1ContentResolver的notifyChange会调用ContentService的notifyChange

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

2 ContentService的notifyChange方法

    @Override
    public void notifyChange(Uri uri, IContentObserver observer,
            boolean observerWantsSelfNotifications, boolean syncToNetwork,
            int userHandle) { 
         try {
            ArrayList calls = new ArrayList();
            synchronized (mRootNode) {//从根节点开始搜索所有需要通知的观察者,结果保存在calls中
                mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
                        userHandle, calls);
            }
            final int numCalls = calls.size();
            for (int i=0; i

2.数据同步机制之AccountManagerService

AccountManagerService负责管理手机中的online账户,主要涉及账户的添加和删除,authtoken的获取和更新等
authtoken:有了authtoken,客户端无须每次操作都想服务器发送密码

2.1认识AccountManagerService

2.1.1AccountManagerService的创建

1:在SystemServer中:和ContentService的创建基本一样,不同的是ContentService是调用main方法来创建,因为创建之后还初始化了SyncManager

            try { 
                accountManager = new AccountManagerService(context);
                ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);
            } catch (Throwable e) {
                Slog.e(TAG, "Failure starting Account Manager", e);
            }

2: AccountManagerService的构造方法


    public AccountManagerService(Context context) {
        this(context, context.getPackageManager(), new AccountAuthenticatorCache(context));
    }

    public AccountManagerService(Context context, PackageManager packageManager,
            IAccountAuthenticatorCache authenticatorCache) {
        mContext = context;
        mPackageManager = packageManager;

        mMessageThread = new HandlerThread("AccountManagerService");
        mMessageThread.start();
        mMessageHandler = new MessageHandler(mMessageThread.getLooper());

        mAuthenticatorCache = authenticatorCache;
        mAuthenticatorCache.setListener(this, null /* Handler */);

        sThis.set(this);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addDataScheme("package");
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context1, Intent intent) {
                purgeOldGrantsAll();
            }
        }, intentFilter);

        IntentFilter userFilter = new IntentFilter();
        userFilter.addAction(Intent.ACTION_USER_REMOVED);
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                onUserRemoved(intent);
            }
        }, userFilter);
    }

2.1.2 AccountAuthenticatorCache的分析

AccountAuthenticatorCache是android authenticator service的管理中心
大致的功能就是通过PMS分析所有指定的action和metadata的service,并记录这些service的uid和type(账户类型)到指定文件中(pms的数据更新是通过RegisteredAutheticator注册观察者来实现数据更新)

(data/system/resigered_services/android.accounts.AccountAuthenticator.xml)

2.1.2.1 AuthenticatorDescription 源码
public class AuthenticatorDescription implements Parcelable {
 
    final public String type; 
    final public int labelId; 
    final public int iconId;  
    final public int smallIconId;  
    final public int accountPreferencesId;  
    final public String packageName;  
    final public boolean customTokens; 
   
    public AuthenticatorDescription(String type, String packageName, int labelId, int iconId,
            int smallIconId, int prefId, boolean customTokens) {
        if (type == null) throw new IllegalArgumentException("type cannot be null");
        if (packageName == null) throw new IllegalArgumentException("packageName cannot be null");
        this.type = type;
        this.packageName = packageName;
        this.labelId = labelId;
        this.iconId = iconId;
        this.smallIconId = smallIconId;
        this.accountPreferencesId = prefId;
        this.customTokens = customTokens;
    }

 
 
 

    private AuthenticatorDescription(Parcel source) {
        this.type = source.readString();
        this.packageName = source.readString();
        this.labelId = source.readInt();
        this.iconId = source.readInt();
        this.smallIconId = source.readInt();
        this.accountPreferencesId = source.readInt();
        this.customTokens = source.readByte() == 1;
    }

 
 

    /** @inheritDoc */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(type);
        dest.writeString(packageName);
        dest.writeInt(labelId);
        dest.writeInt(iconId);
        dest.writeInt(smallIconId);
        dest.writeInt(accountPreferencesId);
        dest.writeByte((byte) (customTokens ? 1 : 0));
    }

    /** Used to create the object from a parcel. */
    public static final Creator CREATOR =
            new Creator() {
        /** @inheritDoc */
        public AuthenticatorDescription createFromParcel(Parcel source) {
            return new AuthenticatorDescription(source);
        }

        /** @inheritDoc */
        public AuthenticatorDescription[] newArray(int size) {
            return new AuthenticatorDescription[size];
        }
    };
}

2.1.2.2 AccountAuthenticatorCache源码
    public static final String ACTION_AUTHENTICATOR_INTENT =
            "android.accounts.AccountAuthenticator";
    public static final String AUTHENTICATOR_META_DATA_NAME =
            "android.accounts.AccountAuthenticator";
    public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";

这三个参数用于控制RegisteredServicesCache从PMS中获取哪些Service的信息

 class AccountAuthenticatorCache
        extends RegisteredServicesCache
        implements IAccountAuthenticatorCache {
    private static final String TAG = "Account";
    private static final MySerializer sSerializer = new MySerializer();

    public AccountAuthenticatorCache(Context context) {
        super(context, AccountManager.ACTION_AUTHENTICATOR_INTENT,
                AccountManager.AUTHENTICATOR_META_DATA_NAME,
                AccountManager.AUTHENTICATOR_ATTRIBUTES_NAME, sSerializer);
    }

    public AuthenticatorDescription parseServiceAttributes(Resources res,
            String packageName, AttributeSet attrs) {
        TypedArray sa = res.obtainAttributes(attrs,
                com.android.internal.R.styleable.AccountAuthenticator);
        try {
            final String accountType =
                    sa.getString(com.android.internal.R.styleable.AccountAuthenticator_accountType);
            final int labelId = sa.getResourceId(
                    com.android.internal.R.styleable.AccountAuthenticator_label, 0);
            final int iconId = sa.getResourceId(
                    com.android.internal.R.styleable.AccountAuthenticator_icon, 0);
            final int smallIconId = sa.getResourceId(
                    com.android.internal.R.styleable.AccountAuthenticator_smallIcon, 0);
            final int prefId = sa.getResourceId(
                    com.android.internal.R.styleable.AccountAuthenticator_accountPreferences, 0);
            final boolean customTokens = sa.getBoolean(
                    com.android.internal.R.styleable.AccountAuthenticator_customTokens, false);
            if (TextUtils.isEmpty(accountType)) {
                return null;
            }
            return new AuthenticatorDescription(accountType, packageName, labelId, iconId,
                    smallIconId, prefId, customTokens);
        } finally {
            sa.recycle();
        }
    }

    private static class MySerializer implements XmlSerializerAndParser {
        public void writeAsXml(AuthenticatorDescription item, XmlSerializer out)
                throws IOException {
            out.attribute(null, "type", item.type);
        }

        public AuthenticatorDescription createFromXml(XmlPullParser parser)
                throws IOException, XmlPullParserException {
            return AuthenticatorDescription.newKey(parser.getAttributeValue(null, "type"));
        }
    }
}

2.1.2.3 RegisteredServicesCache的分析

mPersistentServicesFile 保存了之前获取的指定的Service的信息
由于安装卸载以及sdcard的挂载可能会造成应用的改变,所以发生这些事件的时候会再一次获取指定的Service信息

    public RegisteredServicesCache(Context context, String interfaceName, String metaDataName,
            String attributeName, XmlSerializerAndParser serializerAndParser) {
        mContext = context;
       //保存传递过来的参数
        mInterfaceName = interfaceName;
        mMetaDataName = metaDataName;
        mAttributesName = attributeName;
        mSerializerAndParser = serializerAndParser;
       
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        //syncDir 目录指向/data/system/registered_services目录
        File syncDir = new File(systemDir, "registered_services");
        //文件指向syncDir目录下interfaceName.xml文件,interfaceName有参数传递
        //AccountAuthenticatorCache传递过来的是“android.accounts.AccountAuthenticator”
        mPersistentServicesFile = new AtomicFile(new File(syncDir, interfaceName + ".xml"));

        // Load persisted services from disk
        readPersistentServicesLocked();

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addDataScheme("package");
        //注册apk安装卸载监听
        mContext.registerReceiverAsUser(mPackageReceiver, UserHandle.ALL, intentFilter, null, null);

        // Register for events related to sdcard installation.
        //注册sdcard的挂载监听
        IntentFilter sdFilter = new IntentFilter();
        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
        mContext.registerReceiver(mExternalReceiver, sdFilter);
    }

    private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
            if (uid != -1) {
                generateServicesMap(UserHandle.getUserId(uid));
            }
        }
    };

    private final BroadcastReceiver mExternalReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // External apps can't coexist with multi-user, so scan owner
            generateServicesMap(UserHandle.USER_OWNER);
        }
    };
2.1.2.4 RegisteredServicesCache的generateServicesMap

首先从PMS中获取metadata是android.accounts.AccountAuthenticator的Service
对比persistentServices保存的服务信息和当前获取到的服务信息,判断是否有变化,如果有变化通知监听者

     private void generateServicesMap(int userId) { 
        final PackageManager pm = mContext.getPackageManager();
        final ArrayList> serviceInfos = new ArrayList>();
        //从pms中获取metadata为指定信息的Service并保存
        final List resolveInfos = pm.queryIntentServicesAsUser(
                new Intent(mInterfaceName), PackageManager.GET_META_DATA, userId);
        for (ResolveInfo resolveInfo : resolveInfos) {
            try { 
                ServiceInfo info = parseServiceInfo(resolveInfo);
                if (info == null) {
                    Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
                    continue;
                }
                serviceInfos.add(info);
            } catch (XmlPullParserException e) { 
            } catch (IOException e) {
           
            }
        }

        synchronized (mServicesLock) {
           //获取或创建以前保存的Service信息
            final UserServices user = findOrCreateUserLocked(userId);
            final boolean firstScan = user.services == null;
            if (firstScan) {
                user.services = Maps.newHashMap();
            } else {
                user.services.clear();
            }

            StringBuilder changes = new StringBuilder();
            boolean changed = false;
            //对比获取到的Service 和之前保存的Service,如果发生改变就通知监听者
            for (ServiceInfo info : serviceInfos) {
                // four cases:
                // - doesn't exist yet  
                //   - add, notify user that it was added  
                // - exists and the UID is the same
                //   - replace, don't notify user
                // - exists, the UID is different, and the new one is not a system package
                //   - ignore
                // - exists, the UID is different, and the new one is a system package
                //   - add, notify user that it was added
                Integer previousUid = user.persistentServices.get(info.type);
                if (previousUid == null) { 
                    changed = true;
                    user.services.put(info.type, info);
                    user.persistentServices.put(info.type, info.uid);
                    if (!(mPersistentServicesFileDidNotExist && firstScan)) {
                        notifyListener(info.type, userId, false /* removed */);
                    }
                } else if (previousUid == info.uid) { 
                    user.services.put(info.type, info);//更新,但不用通知
                } else if (inSystemImage(info.uid)
                        || !containsTypeAndUid(serviceInfos, info.type, previousUid)) { 
                    changed = true;
                    user.services.put(info.type, info);
                    user.persistentServices.put(info.type, info.uid);
                    notifyListener(info.type, userId, false /* removed */);
                } else {
  
                }
            }

            ArrayList toBeRemoved = Lists.newArrayList();
            for (V v1 : user.persistentServices.keySet()) {
                if (!containsType(serviceInfos, v1)) {
                    toBeRemoved.add(v1);
                }
            }
            for (V v1 : toBeRemoved) { 
                changed = true;
                user.persistentServices.remove(v1);
                notifyListener(v1, userId, true /* removed */);
            } 
            if (changed) {
                writePersistentServicesLocked();
            }
        }
    }

2.1.2.5 RegisteredServicesCache的 监听的设置和响应
    public void setListener(RegisteredServicesCacheListener listener, Handler handler) {
        if (handler == null) {
            handler = new Handler(mContext.getMainLooper());
        }
        synchronized (this) {
            mHandler = handler;
            mListener = listener;
        }
    }

    private void notifyListener(final V type, final int userId, final boolean removed) {
      
        RegisteredServicesCacheListener listener;
        Handler handler; 
        synchronized (this) {
            listener = mListener;
            handler = mHandler;
        }
        if (listener == null) {
            return;
        }
        
        final RegisteredServicesCacheListener listener2 = listener;
        handler.post(new Runnable() {
            public void run() {
                listener2.onServiceChanged(type, userId, removed);
            }
        });
    }

listener的实现类

public class AccountManagerService
        extends IAccountManager.Stub
        implements RegisteredServicesCacheListener 

listener的设置

    public AccountManagerService(Context context, PackageManager packageManager,
            IAccountAuthenticatorCache authenticatorCache) {
        mContext = context;
        mPackageManager = packageManager;

        mMessageThread = new HandlerThread("AccountManagerService");
        mMessageThread.start();
        mMessageHandler = new MessageHandler(mMessageThread.getLooper());

        mAuthenticatorCache = authenticatorCache;
        //设置监听,在Service
        mAuthenticatorCache.setListener(this, null /* Handler */);
2.1.2.6 AccountAuthenticatorCache的分析总结

AccountAuthenticator相关服务的定义
一个Service的action和metadata为AccountAuthenticatorCache指定的action和metadata如:

    
        
            
        

        
    

而metadata的具体信息保存在resource文件中


系统中存在的此类服务在/data/system/registered_services/android.accounts.AccountAuthenticator.xml文件中
从整个文件中可以看到当前手机上有多少个AAS服务(accout authenticator service)




 

 

2.2AccountManger的addAccout方法的流程分析

AccountMangerService有一个重要的函数addAccount,该函数的作用是为某个账户添加一个用户,AccountMangerService是一个服务,客户端进程需要通过AccountManager提供的api来使用AccountMangerService服务。所以流程的开端是AccountManager的addAccount方法

流程总结:

2.2.1AccountManager的addAccount发起请求

    public AccountManagerFuture addAccount(final String accountType,
          //accountType是账户类型,不能为空,email的账户类型是"com.android.email"
            final String authTokenType, final String[] requiredFeatures,
            final Bundle addAccountOptions,
            //第二到第四个参数与具体的AAS服务有关
            //activity是指如果需要输入用户名密码的话,要启动的activity
            //callback和handler与获取返回值有关,如果这两个参数是空,客户端需要启动一个线程去获取AccountManagerFuture的getResult
            final Activity activity, AccountManagerCallback callback, Handler handler) {
        if (accountType == null) throw new IllegalArgumentException("accountType is null");
        final Bundle optionsIn = new Bundle();
        if (addAccountOptions != null) {//保存客户端传入的addAccountOptions
            optionsIn.putAll(addAccountOptions);
        }
        optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
         //AmsTask类
        return new AmsTask(activity, handler, callback) {
            public void doWork() throws RemoteException {
                mService.addAccount(mResponse, accountType, authTokenType,
                        requiredFeatures, activity != null, optionsIn);
            }
        }.start();
    }

2.2.1.1AmsTask类的介绍

ContentService:第一部分数据更新和账户同步_第1张图片
AmsTask继承关系.png
  • AmsTask继承自FutureTask,并实现了AccountManagerFutrue接口,AmsTask定义了一个doWork虚函数,该函数必须由子类实现
  • AmsTask对象中有一个mResponse成员,该成员的类型是AmsTask的内部类Response,从Response的派生关系可知,Response将参与Binder通信并且它是Binder的Bn端,而AccountManagerService会得到Binder的Bp端对象,当添加完账户之后,AccountManagerService会通过Bp端对象的onResult或者onError函数向Response通知处理结果。

IAccountManagerResponse
onResponse和onError

public interface IAccountManagerResponse extends android.os.IInterface { 
    public static abstract class Stub extends android.os.Binder implements
            android.accounts.IAccountManagerResponse {
        private static final java.lang.String DESCRIPTOR = "android.accounts.IAccountManagerResponse"; 
     

        @Override
        public boolean onTransact(int code, android.os.Parcel data,
                android.os.Parcel reply, int flags)
                throws android.os.RemoteException {
            switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_onResult: {
                ...
                this.onResult(_arg0);//回调onResult
                return true;
            }
            case TRANSACTION_onError: {
                data.enforceInterface(DESCRIPTOR);
                ...
                this.onError(_arg0, _arg1);//回调onError
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements
                android.accounts.IAccountManagerResponse {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public void onResult(android.os.Bundle value)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    ....
                    //这里的调用会被onTransact响应到
                    mRemote.transact(Stub.TRANSACTION_onResult, _data, null,
                            android.os.IBinder.FLAG_ONEWAY);
                } finally {
                    _data.recycle();
                }
            }

            @Override
            public void onError(int errorCode, java.lang.String errorMessage)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    ....
                    mRemote.transact(Stub.TRANSACTION_onError, _data, null,
                            android.os.IBinder.FLAG_ONEWAY);
                } finally {
                    _data.recycle();
                }
            }
        } 
        static final int TRANSACTION_onResult = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_onError = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public void onResult(android.os.Bundle value)
            throws android.os.RemoteException;

    public void onError(int errorCode, java.lang.String errorMessage)
            throws android.os.RemoteException;
}

AmsTask的分析

        final IAccountManagerResponse mResponse;
        final Handler mHandler;
        final AccountManagerCallback mCallback;
        final Activity mActivity;
        public AmsTask(Activity activity, Handler handler, AccountManagerCallback callback) {
            super(new Callable() {
                public Bundle call() throws Exception {
                    throw new IllegalStateException("this should never be called");
                }
            });

            mHandler = handler;
            mCallback = callback;
            mActivity = activity;
            mResponse = new Response();
        }
       //start会调用doWork
        public final AccountManagerFuture start() {
            try {
                doWork();
            } catch (RemoteException e) {
                setException(e);
            }
            return this;
        }

2.2.2AccountManagerService的addAccount转发请求

 
    public void addAcount(final IAccountManagerResponse response, final String accountType,
            final String authTokenType, final String[] requiredFeatures,
            final boolean expectActivityLaunch, final Bundle optionsIn) {
        //检查客户端进程是否有MANAGE_ACCOUNTS的权限
        checkManageAccountsPermission();

        UserAccounts accounts = getUserAccountsForCaller();
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        //将传入的optionsIn保存到options中
        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
        options.putInt(AccountManager.KEY_CALLER_UID, uid);
        options.putInt(AccountManager.KEY_CALLER_PID, pid);

        long identityToken = clearCallingIdentity();
        //调用Session的bind函数
        try {
            new Session(accounts, response, accountType, expectActivityLaunch,
                    true /* stripAuthTokenFromResult */) {
                public void run() throws RemoteException {
                    mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
                            options);
                }

                protected String toDebugString(long now) { 
                    ...
                }
            }.bind();
        } finally {
            restoreCallingIdentity(identityToken);
        }
    }

Session的介绍

ContentService:第一部分数据更新和账户同步_第2张图片
Session示意图.png
  • Session从IAccountAuthenticatorResponse.Stub派生,表名它会参与Binder通信,并且它是Bn端,通信的目标是具体的AAS服务,AccountManagerService会将自己传给AAS,这样AAS就得到IAccountAuthenticatorResponse的Bp对象,当AAS完成了账户添加工作之后,就会通过IAccountAuthenticatorResponse的Bp端往Session返回结果。
  • Session的mResponse变量指向指向客户端的IAccountManagerResponse接口,当Session收到AAS的返回结果后,又通过IAccountManagerService的Bp端对象向客户端返回处理结果
  • mAuthenticator变量的类型是IAccountAuthenticator,用于和ASS通信,客户端发起的请求通过Session由mAuthenticator调用对应的AAS的函数

客户端将请求发送给AccountManagerService,AccountManagerService再将请求转发给对应的AAS

AAS处理完成之后,先将结果交给AccountManagerService,然后AccountManagerService再将结果返回给客户端

2.2.2.1Session处理流程分析

1.Session的构造函数

    /**
     * @param accounts
     * @param response
     * @param accountType
     * @param expectActivityLaunch有客戶端傳遞,表示是否需要activity
     * @param stripAuthTokenFromResult
     */
    public Session(UserAccounts accounts, IAccountManagerResponse response, String accountType,
            boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
        super();
        ...
        synchronized (mSessions) {
            //把當前的Session對象保存到AccountManagerService的mSessions成員中
            mSessions.put(toString(), this);
        }
        try {//監聽客戶端死亡的消息
            response.asBinder().linkToDeath(this, 0 /* flags */);
        } catch (RemoteException e) {
            mResponse = null;
            binderDied();
        }
    }

2.bind方法,bindToAutheticator

        void bind() { 
            //绑定到mAccontType指定的AAS,email的AAS是com.android.email
           //davdroid指定的AAS是bitfire.at.davdroid
            if (!bindToAuthenticator(mAccountType)) {
                Log.d(TAG, "bind attempt failed for " + toDebugString());
                //onError回调
                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
            }
        }

3.bindToAuthenticator

    private boolean bindToAuthenticator(String authenticatorType) {
        //从AccountAuthenticatorCache中获取authenticatorType对应的Service
        final AccountAuthenticatorCache.ServiceInfo authenticatorInfo;
        authenticatorInfo = mAuthenticatorCache.getServiceInfo(
                AuthenticatorDescription.newKey(authenticatorType),
                mAccounts.userId);
        if (authenticatorInfo == null) { 
            return false;
        }

        Intent intent = new Intent();
        intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
        //设置目标的componentName
        intent.setComponent(authenticatorInfo.componentName);
        //通过bindService启动指定的服务
        if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE,
                mAccounts.userId)) { 
            
            return false;
        } 
        return true;
    }

4.Session的bind函数会通过bindService来启动指定的Service,如果服务启动成功,那么Session的onServiceConnected函数将被调用,onServiceConnected会调用run方法

        public void onServiceConnected(ComponentName name, IBinder service) {
            mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
            try {
                run();
            } catch (RemoteException e) {
                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
                        "remote exception");
            }
        }

5.run方法,调用mAuthenticator的addAccount方法
也就是说最终是调用AAS的addAccount方法去实现

            new Session(accounts, response, accountType, expectActivityLaunch,
                    true /* stripAuthTokenFromResult */) {
                public void run() throws RemoteException {
                    mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
                            options);
                } 
            }.bind();

2.2.3返回值的处理流程

AbstractAuthenticator通过IAccountAuthenticatorService的onResult将结果返回给AccountManagerService创建的匿名Session类对象,Session的onResult函数

    public void onResult(Bundle result) {
        mNumResults++;
        if (result != null
                && !TextUtils.isEmpty(result
                        .getString(AccountManager.KEY_AUTHTOKEN))) {
                        //从返回的result中取出相关的信息
            String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
            String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
            if (!TextUtils.isEmpty(accountName)&& !TextUtils.isEmpty(accountType)) {
                Account account = new Account(accountName, accountType);
                cancelNotification(
                        getSigninRequiredNotificationId(mAccounts, account),
                        new UserHandle(mAccounts.userId));
            }
        }
        IAccountManagerResponse response;
               //AAS返回keyIntent表明需要弹出activity以输入用户名和密码
        if (mExpectActivityLaunch && result != null
                && result.containsKey(AccountManager.KEY_INTENT)) {
            response = mResponse;
        } else {
            response = getResponseAndClose();
        }
        if (response != null) {
            try {
                if (result == null) { 
                    response.onError(
                            AccountManager.ERROR_CODE_INVALID_RESPONSE,
                            "null bundle returned");
                } else {
                    if (mStripAuthTokenFromResult) {
                        result.remove(AccountManager.KEY_AUTHTOKEN);
                    } 
                                        //调用位于客户端的IAccountManagerService的onResult函数
                    response.onResult(result);
                }
            } catch (RemoteException e) {
                // if the caller is dead then there is no one to care about
                // remote exceptions 
            }
        }
    }

客户端的IAccountManagerService由AmsTask的内部类Response实现

        private class Response extends IAccountManagerResponse.Stub {
            public void onResult(Bundle bundle) {
                Intent intent = bundle.getParcelable(KEY_INTENT);
                if (intent != null && mActivity != null) {
                     //如果需要启动activity,则要启动ASS指定的activity
                    mActivity.startActivity(intent);
                    // leave the Future running to wait for the real response to this request
                } else if (bundle.getBoolean("retry")) {
                   //如果需要重试,则再次调用doWork方法
                    try {
                        doWork();
                    } catch (RemoteException e) {
                        // this will only happen if the system process is dead, which means
                        // we will be dying ourselves
                    }
                } else {//将返回结果保存起来,当客户端调用getResult的时候,将会得到相应的结果
                    set(bundle);
                }
            }

2.2.4addAccount的分析总结

ContentService:第一部分数据更新和账户同步_第3张图片
addAccount流程.png

你可能感兴趣的:(ContentService:第一部分数据更新和账户同步)