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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                在SDK中同樣定義了好幾個函數用于發送廣播。不過,根據之前的經驗,最終和AMS交互的函數可能通過一個接口就能完成。來看最簡單的廣播發送函數sendBroadcast,其代碼如下: **ContextImpl.java::sendBroadcast** ~~~ public void sendBroadcast(Intent intent) { StringresolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.setAllowFds(false); //調用AMS的brodcastIntent,在SDK中定義的廣播發送函數最終都會調用它 ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false); }...... } ~~~ AMS的broadcastIntent函數的主要工作將交由AMS的broadcastIntentLocked來完成,故此處直接分析broadcastIntentLocked。 1. broadcastIntentLocked分析 我們分階段來分析broadcastIntentLocked的工作,先來看第一階段工作。 (1) broadcastIntentLocked分析之一 **ActivityManagerService.java::broadcastIntentLocked** ~~~ private final int broadcastIntentLocked(ProcessRecordcallerApp, StringcallerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundlemap, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid) { intent =new Intent(intent); //為Intent增加FLAG_EXCLUDE_STOPPED_PACKAGES標志,表示該廣播不會傳遞給被STOPPED //的Package intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); //處理一些特殊的廣播,包括UID_REMOVED,PACKAGE_REMOVED和PACKAGE_ADDED等 finalboolean uidRemoved = Intent.ACTION_UID_REMOVED.equals( intent.getAction()); ......//處理特殊的廣播,主要和PACKAGE相關,例如接收到PACKAGE_REMOVED廣播后,AMS //需將該Package的組件從相關成員中刪除,相關代碼可自行閱讀 //處理TIME_ZONE變化廣播 if(intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); //處理CLEAR_DNS_CACHE廣播 if(intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) mHandler.sendEmptyMessage(CLEAR_DNS_CACHE); //處理PROXY_CHANGE廣播 if(Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) { ProxyProperties proxy = intent.getParcelableExtra("proxy"); mHandler.sendMessage(mHandler.obtainMessage( UPDATE_HTTP_PROXY,proxy)); } ~~~ 從以上代碼可知,broadcastIntentLocked第一階段的工作主要是處理一些特殊的廣播消息。 下面來看broadcastIntentLocked第二階段的工作。 (2) broadcastIntentLocked分析之二 **ActivityManagerService.java::broadcastIntentLocked** ~~~ //處理發送sticky廣播的情況 if(sticky) { ......//檢查發送進程是否有BROADCAST_STICKY權限 if(requiredPermission != null) { //在發送Sticky廣播的時候,不能攜帶權限信息 returnBROADCAST_STICKY_CANT_HAVE_PERMISSION; } //在發送Stikcy廣播的時候,也不能指定特定的接收對象 if(intent.getComponent() != null) ......//拋異常 //將這個Sticky的Intent保存到mStickyBroadcasts中 ArrayList<Intent> list =mStickyBroadcasts.get(intent.getAction()); if (list== null) { list= new ArrayList<Intent>(); mStickyBroadcasts.put(intent.getAction(), list); } ......//如果list中已經有該intent,則直接用新的intent替換舊的intent //否則將該intent加入到list中保存 if (i >= N) list.add(new Intent(intent)); } //定義兩個變量,其中receivers用于保存匹配該Intent的所有廣播接收者,包括靜態或動態 //注冊的廣播接收者,registeredReceivers用于保存符合該Intent的所有動態注冊者 Listreceivers = null; List<BroadcastFilter>registeredReceivers = null; try { if(intent.getComponent() != null) { ......//如果指定了接收者,則從PKMS中查詢它的信息 }else { //FLAG_RECEIVER_REGISTERED_ONLY標簽表明該廣播只能發給動態注冊者 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)== 0) { //如果沒有設置前面的標簽,則需要查詢PKMS,獲得那些在AndroidManifest.xml //中聲明的廣播接收者,即靜態廣播接收者的信息,并保存到receivers中 receivers = AppGlobals.getPackageManager().queryIntentReceivers( intent, resolvedType,STOCK_PM_FLAGS); } //再從AMS的mReceiverResolver中查詢符合條件的動態廣播接收者 registeredReceivers =mReceiverResolver.queryIntent(intent, resolvedType, false); } }...... /* 判斷該廣播是否設置了REPLACE_PENDING標簽。如果設置了該標簽,并且之前的那個Intent還 沒有被處理,則可以用新的Intent替換舊的Intent。這么做的目的是為了減少不必要的廣播發送, 但筆者感覺,這個標簽的作用并不靠譜,因為只有舊的Intent沒被處理的時候,它才能被替換。 因為舊Intent被處理的時間不能確定,所以不能保證廣播發送者的一番好意能夠實現。因此, 在發送廣播時,千萬不要以為設置了該標志就一定能節約不必要的廣播發送。 */ final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; //先處理動態注冊的接收者 int NR =registeredReceivers != null ? registeredReceivers.size() : 0; //如果此次廣播為非串行化發送,并且符合條件的動態注冊接收者個數不為零 if(!ordered && NR > 0) { //創建一個BroadcastRecord對象即可,注意,一個BroadcastRecord對象可包括所有的 //接收者(可參考圖6-19) BroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, registeredReceivers, resultTo, resultCode, resultData, map, ordered, sticky, false); boolean replaced = false; if (replacePending) { ......//從mParalledBroadcasts中查找是否有舊的Intent,如果有就替代它,并設置 //replaced為true } if(!replaced) {//如果沒有被替換,則保存到mParallelBroadcasts中 mParallelBroadcasts.add(r); scheduleBroadcastsLocked();//調度一次廣播發送 } //至此,動態注冊的廣播接收者已處理完畢,設置registeredReceivers為null registeredReceivers = null;// NR =0; } ~~~ broadcastIntentLocked第二階段的工作有兩項: - 查詢滿足條件的動態廣播接收者及靜態廣播接收者。 - 當本次廣播不為ordered時,需要盡快發送該廣播。另外,非ordered的廣播都被AMS保存在mParallelBroadcasts中。 (3) broadcastIntentLocked分析之三 下面來看broadcastIntentLocked最后一階段的工作,其代碼如下: **ActivityManagerService.java::broadcastIntentLocked** ~~~ int ir = 0; if(receivers != null) { StringskipPackages[] = null; ......//處理PACKAGE_ADDED的Intent,系統不希望有些應用程序一安裝就啟動。 //這類程序的工作原理是什么呢?即在該程序內部監聽PACKAGE_ADDED廣播。如果系統 //沒有這一招防備,則PKMS安裝完程序后所發送的PAKCAGE_ADDED消息將觸發該應用的啟動 ......//處理ACTION_EXTERNAL_APPLICATIONS_AVAILABLE廣播 ......//將動態注冊的接收者registeredReceivers的元素合并到receivers中去 //處理完畢后,所有的接收者(無論動態還是靜態注冊的)都存儲到receivers變量中了 if((receivers != null && receivers.size() > 0) || resultTo != null) { //創建一個BroadcastRecord對象,注意它的receivers中包括所有的接收者 BroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false); booleanreplaced = false; if (replacePending) { ......//替換mOrderedBroadcasts中舊的Intent }// if(!replaced) {//如果沒有替換,則添加該條廣播記錄到mOrderedBroadcasts中 mOrderedBroadcasts.add(r); scheduleBroadcastsLocked();//調度AMS進行廣播發送工作 } } returnBROADCAST_SUCCESS; } ~~~ 由以上代碼可知,AMS將動態注冊者和靜態注冊者都合并到receivers中去了。注意,如果本次廣播不是ordered,那么表明動態注冊者就已經在第二階段工作中被處理了。因此在合并時,將不會有動態注冊者被加到receivers中。最終所創建的廣播記錄存儲在mOrderedBroadcasts中,也就是說,不管是否串行化發送,靜態接收者對應的廣播記錄都將保存在mOrderedBroadcasts中。 為什么不將它們保存在mParallelBroadcasts中呢? 結合代碼會發現,保存在mParallelBroadcasts中的BroadcastRecord所包含的都是動態注冊的廣播接收者信息,這是因為動態接收者所在的進程是已經存在的(如果該進程不存在,如何去注冊動態接收者呢?),而靜態廣播接收者就不能保證它已經和一個進程綁定在一起了(靜態廣播接收者此時可能還僅僅是在AndroidManifest.xml中聲明的一個信息,相應的進程并未創建和啟動)。根據前一節所分析的Activity啟動流程,AMS還需要進行創建應用進程,初始化Android運行環境等一系列復雜的操作。讀到后面內容時會發現,AMS將在一個循環中逐條處理mParallelBroadcasts中的成員(即派發給接收者)。如果將靜態廣播接收者也保存到mParallelBroadcasts中,會有什么后果呢?假設這些靜態接收者所對應的進程全部未創建和啟動,那么AMS將在那個循環中創建多個進程!結果讓人震驚,系統壓力一下就上去了。所以,對于靜態注冊者,它們對應的廣播記錄都被放到mOrderedBroadcasts中保存。AMS在處理這類廣播信息時,一個進程一個進程地處理,只有處理完一個接收者,才繼續下一個接收者。這種做法的好處是,避免了驚群效應的出現,壞處則是延時較長。 下面進入AMS的BROADCAST_INTENT_MSG消息處理函數,看看情況是否如上所說。
                  <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>

                              哎呀哎呀视频在线观看