<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                **SystemServer.java::ServerThread.run** ~~~ ...... //注冊AccountManagerService到ServiceManager,服務名為“account” ServiceManager.addService(Context.ACCOUNT_SERVICE, newAccountManagerService(context)); ~~~ 其構造函數的代碼如下: **AccountManagerService.java::AccountManagerService** ~~~ public AccountManagerService(Context context) { //調用另外一個構造函數,其第三個參數將構造一個AccountAuthenticatorCache對象,它是 //什么呢?見下文分析 this(context,context.getPackageManager(), new AccountAuthenticatorCache(context)); } ~~~ 在AccountManagerService構造函數中創建了一個AccountAuthenticatorCache對象,它是什么?來看下文。 1. AccountAuthenticatorCache分析 AccountAuthenticatorCache是Android平臺中賬戶驗證服務(Account AuthenticatorService,AAS)的管理中心。而AAS則由應用程序通過在AndroidManifest.xml中輸出符合指定要求的Service信息而來。稍后讀者將看到這些要求的具體格式。 先來看AccountAuthenticatorCache的派生關系,如圖8-3所示。 :-: ![](http://img.blog.csdn.net/20150803131407976?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-3 AccountAuthenticatorCache類圖 由圖8-3可知: - AccountAuthenticatorCache從RegisteredServicesCache<AuthenticatorDescription>派生。RegisteredServicesCache是一個模板類,專門用于管理系統中指定Service的信息收集和更新,而具體是哪些Service由RegisteredServicesCache構造時的參數指定。AccountAuthenticatorCache對外輸出由RegisteredServicesCache模板參數指定的類的實例。在圖8-3中應該就是AuthenticatorDescription。 - AuthenticatorDescription繼承了Parcelable接口,這代表它可以跨Binder傳遞。該類描述了AAS相關的信息。 - AccountAuthenticatorCache實現了IAccountAuthenticatorCache接口。這個接口供外部調用者使用以獲取AAS的信息。 下面看AccountAuthenticatorCache的創建,其相關代碼如下: **AccountAuthenticatorCache.java::AccountAuthenticatorCache** ~~~ public AccountAuthenticatorCache(Context context){ /* ACTION_AUTHENTICATOR_INTENT值為"android.accounts.AccountAuthenticator" AUTHENTICATOR_META_DATA_NAME值為"android.accounts.AccountAuthenticator" AUTHENTICATOR_ATTRIBUTES_NAME值為"account-authenticator" */ super(context, AccountManager.ACTION_AUTHENTICATOR_INTENT, AccountManager.AUTHENTICATOR_META_DATA_NAME, AccountManager.AUTHENTICATOR_ATTRIBUTES_NAME, sSerializer); } ~~~ AccountAuthenticatorCache調用在其基類RegisteredServicesCache的構造函數時,傳遞了3個字符串參數,這3個參數用于控制RegisteredServicesCache從PackageManagerService獲取哪些Service的信息。 (1) RegisteredServicesCache分析 **RegisteredServicesCache.java::RegisteredServicesCache** ~~~ public RegisteredServicesCache(Context context,String interfaceName, StringmetaDataName, String attributeName, XmlSerializerAndParser<V>serializerAndParser) { mContext= context; //保存傳遞進來的參數 mInterfaceName = interfaceName; mMetaDataName = metaDataName; mAttributesName = attributeName; mSerializerAndParser = serializerAndParser; FiledataDir = Environment.getDataDirectory(); FilesystemDir = new File(dataDir, "system"); //syncDir指向/data/system/registered_service目錄 FilesyncDir = new File(systemDir, "registered_services"); //下面這個文件指向syncDir目錄下的android.accounts.AccountAuthenticator.xml mPersistentServicesFile = new AtomicFile(new File(syncDir, interfaceName+ ".xml")); //生成服務信息 generateServicesMap(); finalBroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context1, Intent intent) { generateServicesMap(); } }; //注冊Package安裝、卸載和更新等廣播監聽者 mReceiver = new AtomicReference<BroadcastReceiver>(receiver); IntentFilter intentFilter = newIntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); mContext.registerReceiver(receiver, intentFilter); IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mContext.registerReceiver(receiver, sdFilter); } ~~~ 由以上代碼可知: - 成員變量mPersistentServicesFile指向/data/system/registered_service/目錄下的一個文件,該文件保存了以前獲取的對應Service的信息。就AccountAuthenticator而言,mPersistentServicesFile指向該目錄的android.accounts.AccountAuthenticator.xml文件。 - 由于RegisteredServicesCache管理的是系統中指定Service的信息,當系統中有Package安裝、卸載或更新時,RegisteredServicesCache也需要對應更新自己的信息,因為有些Service可能會隨著APK被刪除而不復存在。 generateServiceMap函數將獲取指定的Service信息,其代碼如下: **RegisteredServicesCache.java::generateServicesMap** ~~~ void generateServicesMap() { //獲取PackageManager接口,用來和PackageManagerService交互 PackageManager pm = mContext.getPackageManager(); ArrayList<ServiceInfo<V>> serviceInfos = newArrayList<ServiceInfo<V>>(); /* 在本例中,查詢PKMS中滿足Intent Action為"android.accounts.AccountAuthenticator" 的服務信息。由以下代碼可知,這些信息指的是Service中聲明的MetaData信息 */ List<ResolveInfo> resolveInfos = pm.queryIntentServices( new Intent(mInterfaceName),PackageManager.GET_META_DATA); for(ResolveInfo resolveInfo : resolveInfos) { try { /* 調用parserServiceInfo函數解析從PKMS中獲得的MetaData信息,該函數 返回的是一個模板類對象。就本例而言,這個函數返回一個 ServiceInfo<AccountAuthenticator>類型的對象 */ ServiceInfo<V> info = parseServiceInfo(resolveInfo); serviceInfos.add(info); } } synchronized (mServicesLock) { if(mPersistentServices == null) readPersistentServicesLocked(); mServices = Maps.newHashMap(); StringBuilder changes = new StringBuilder(); ......//檢查mPersistentServices保存的服務信息和當前從PKMS中取出來的PKMS //信息,判斷是否有變化,如果有變化,需要通知監聽者。讀者可自行閱讀這段代碼, //注意其中uid的作用 mPersistentServicesFileDidNotExist = false; } } ~~~ 接下來解析Service的parseServiceInfo函數。 (2) parseServiceInfo函數分析 **RegisteredServicesCache.java::parseServiceInfo** ~~~ private ServiceInfo<V>parseServiceInfo(ResolveInfo service) throws XmlPullParserException, IOException { android.content.pm.ServiceInfo si = service.serviceInfo; ComponentName componentName = new ComponentName(si.packageName, si.name); PackageManager pm = mContext.getPackageManager(); XmlResourceParser parser = null; try { //解析MetaData信息 parser = si.loadXmlMetaData(pm, mMetaDataName); AttributeSet attrs = Xml.asAttributeSet(parser); inttype; ...... StringnodeName = parser.getName(); //調用子類實現的parseServiceAttributes得到一個真實的對象,在本例中它是 //AuthenticatorDescription。注意,傳遞給parseServiceAttributes的第一個 //參數代表MetaData中的resource信息。詳細內容見下文的圖例 V v=parseServiceAttributes( pm.getResourcesForApplication(si.applicationInfo), si.packageName, attrs); finalandroid.content.pm.ServiceInfo serviceInfo = service.serviceInfo; finalApplicationInfo applicationInfo = serviceInfo.applicationInfo; finalint uid = applicationInfo.uid; returnnew ServiceInfo<V>(v, componentName, uid); } ...... finally { if (parser != null) parser.close(); } } ~~~ parseServiceInfo將解析Service中的MetaData信息,然后調用子類實現的parseServiceAttributes函數,以獲取特定類型Service的信息。 下面通過實例向讀者展示最終的解析結果。 (3) AccountAuthenticatorCache分析總結 在Email應用的AndroidManifest.xml中定義了一個AAS,如圖8-4所示。 :-: ![](http://img.blog.csdn.net/20150803131422504?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-4 Email AAS定義 由圖8-4可知,在Email中這個Service對應為EasAuthenticatorService,其Intent匹配的Action為“android.accounts.AccountAuthenticator”,其MetaData的name為“android.accounts.AccountAuthenticator”,而MetaData的具體信息保存在resource資源中,在本例中,它指向另外一個xml文件,即eas_authenticator.xml,此文件的內容如圖8-5所示。 :-: ![](http://img.blog.csdn.net/20150803131437028?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-5 eas_authenticator.xml的內容 圖8-5為Email中eas_authenticator.xml的內容。這個xml中的內容是有嚴格要求的,其中: - accountType標簽用于指定賬戶類型(賬戶類型和具體應用有關,Android并未規定賬戶的類型)。 - icon、smallIcon、label和accountPreferences等用于界面顯示。例如,當需要用戶輸入賬戶信息時,系統會彈出一個Activity,上述幾個標簽就用于界面顯示。詳細情況可閱讀SDK文檔AbstractAccountAuthenticator的說明。 而android.accounts.AccountAuthenticator.xml的內容如圖8-6所示。 :-: ![](http://img.blog.csdn.net/20150803131452038?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-6 android.accounts.AccountAuthenticator.xml的內容 由圖8-6可知,筆者的測試機器上有3個AAS服務,其中同一個uid有兩個服務(即uid為10015對應的兩個Service)。 * * * * * **提示**:uid是在為PackageManagerService解析APK文件時賦予APK的。讀者不妨自行閱讀frameworks/base/services/java/com/android/server/pm/Settings.java中的newUserIdLPw函數。 * * * * * 下面來看AccountManagerService的構造函數。 2. AccountManagerService構造函數分析 **AccountManagerService.java::AccountManagerService** ~~~ public AccountManagerService(Context context,PackageManager packageManager, IAccountAuthenticatorCache authenticatorCache) { mContext= context; mPackageManager = packageManager; synchronized (mCacheLock) { //此數據庫文件對應為/data/system/accounts.db mOpenHelper = new DatabaseHelper(mContext); } mMessageThread = new HandlerThread("AccountManagerService"); mMessageThread.start(); mMessageHandler = new MessageHandler(mMessageThread.getLooper()); mAuthenticatorCache = authenticatorCache; //為AccountAuthenticatorCache設置一個監聽者,一旦AAS服務發生變化, //AccountManagerService需要做對應處理 mAuthenticatorCache.setListener(this, null /* Handler */); sThis.set(this); //監聽ACTION_PACKAGE_REMOVED廣播 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addDataScheme("package"); mContext.registerReceiver(new BroadcastReceiver() { publicvoid onReceive(Context context1, Intent intent) { purgeOldGrants(); } },intentFilter); /* accounts.db數據庫中有一個grants表,用于存儲授權信息,該信息用于保存哪些Package 有權限獲取賬戶信息。下面的函數將根據grants表中的數據查詢PKMS,以判斷這些 Package是否還存在。如果系統中已經不存在這些Package,則grants表需要更新 */ purgeOldGrants(); /* accounts.db中有一個accounts表,該表中存儲了賬戶類型和賬戶名。其中,賬戶類型 就是AuthenticatorDescription中的accountType,它和具體應用有關。下面這個 函數將比較accounts表中的內容與AccountAuthenticatorCache中服務的信息,如果 AccountAuthenticatorCache已經不存在對應賬戶類型的服務,則需要刪除accounts表 中的對應項 */ validateAccountsAndPopulateCache(); } ~~~ AccountManagerService的構造函數較簡單,有興趣的讀者可自行研究以上代碼中未詳細分析的函數。下面將通過一個具體的例子來分析AccountManagerService的工作流程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看