<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國際加速解決方案。 廣告
                BROADCAST_INTENT_MSG消息將觸發processNextBroadcast函數,下面分階段來分析它。 1. processNextBroadcast分析之一 **ActivityManagerService.java::processNextBroadcast** ~~~ private final void processNextBroadcast(booleanfromMsg) { //如果是BROADCAST_INTENT_MSG消息觸發該函數,則fromMsg為true synchronized(this) { BroadcastRecord r; updateCpuStats();//更新CPU使用情況 if(fromMsg) mBroadcastsScheduled = false; //先處理mParallelBroadcasts中的成員。如前所述,AMS在一個循環中處理它們 while(mParallelBroadcasts.size() > 0) { r =mParallelBroadcasts.remove(0); r.dispatchTime =SystemClock.uptimeMillis(); r.dispatchClockTime =System.currentTimeMillis(); final int N = r.receivers.size(); for(int i=0; i<N; i++) { Object target = r.receivers.get(i); //①mParallelBroadcasts中的成員全為BroadcastFilter類型,所以下面的函數 //將target直接轉換成BroadcastFilter類型。注意,最后一個參數為false deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } //將這條處理過的記錄保存到mHistoryBroadcast中,供調試使用 addBroadcastToHistoryLocked(r); } ~~~ deliverToRegisteredReceiverLocked函數的功能就是派發廣播給接收者,其代碼如下: **ActivityManagerService.java::deliverToRegisteredReceiverLocked** ~~~ private final voiddeliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, booleanordered) { booleanskip = false; //檢查發送進程是否有filter要求的權限 if(filter.requiredPermission != null) { intperm = checkComponentPermission(filter.requiredPermission, r.callingPid, r.callingUid, -1, true); if(perm != PackageManager.PERMISSION_GRANTED) skip = true; } //檢查接收者是否有發送者要求的權限 if(r.requiredPermission != null) { intperm = checkComponentPermission(r.requiredPermission, filter.receiverList.pid, filter.receiverList.uid, -1, true); if(perm != PackageManager.PERMISSION_GRANTED) skip = true; } if(!skip) { if(ordered) { ......//設置一些狀態,成員變量等信息,不涉及廣播發送 } try { //發送廣播 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky); if(ordered) r.state = BroadcastRecord.CALL_DONE_RECEIVE; }...... } } } ~~~ 來看performReceiveLocked函數,其代碼如下: **ActivityManagerService.java::performReceiveLocked** ~~~ static void performReceiveLocked(ProcessRecordapp, IIntentReceiver receiver, Intentintent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) throws RemoteException { if(app != null && app.thread != null) { //如果app及app.thread不為null,則調度scheduleRegisteredReceiver, //注意這個函數名為scheduleRegisteredReceiver,它只針對動態注冊的廣播接收者 app.thread.scheduleRegisteredReceiver(receiver,intent, resultCode, data, extras, ordered, sticky); } else{ //否則調用IIntentReceiver的performReceive函數 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky); } } ~~~ 對于動態注冊者而言,在大部分情況下會執行if分支,所以應用進程ApplicationThread的scheduleRegisteredReceiver函數將被調用。稍后再分析應用進程的廣播處理流程。 2. processNextBroadcast分析之二 至此,processNextBroadcast已經在一個while循環中處理完mParallelBroadcasts的所有成員了,實際上,這種處理方式也會造成驚群效應,但影響相對較少。這是因為對于動態注冊者來說,它們所在的應用進程已經創建并初始化成功。此處的廣播發送只是調用應用進程的一個函數而已。相比于創建進程,再初始化Android運行環境所需的工作量,調用scheduleRegisteredReceiver的工作就比較輕松了。 來看processNextBroadcast第二階段的工作,代碼如下: **ActivityManagerService.java::processNextBroadcast** ~~~ /* 現在要處理mOrderedBroadcasts中的成員。如前所述,它要處理一個接一個的接受者,如果 接收者所在進程還未啟動,則需要等待。mPendingBroadcast變量用于標識因為應用進程還未 啟動而處于等待狀態的BroadcastRecord。 */ if(mPendingBroadcast != null) { boolean isDead; synchronized (mPidsSelfLocked) { isDead= (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null); } /*重要說明 判斷要等待的進程是否為dead進程,如果沒有dead進程,則繼續等待。仔細思考,此處直接 返回會有什么問題。 問題不小!假設有兩個ordered廣播A和B,有兩個接收者,AR和BR,并且BR所 在進程已經啟動并完成初始化Android運行環境。如果processNextBroadcast先處理A, 再處理B,那么此處B的處理將因為mPendingBroadcast不為空而被延后。雖然B和A 之間沒有任何關系(例如完全是兩個不同的廣播消息), 但是事實上,大多數開發人員理解的order是針對單個廣播的,例如A有5個接收者,那么對這 5個接收者的廣播的處理是串行的。通過此處的代碼發現,系統竟然串行處理A和B廣播,即 B廣播要待到A的5個接收者都處理完了才能處理。 */ if(!isDead) return; else { mPendingBroadcast.state = BroadcastRecord.IDLE; mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex; mPendingBroadcast = null; } } boolean looped = false; do { // mOrderedBroadcasts處理完畢 if (mOrderedBroadcasts.size() == 0) { scheduleAppGcsLocked(); if (looped) updateOomAdjLocked(); return; } r =mOrderedBroadcasts.get(0); boolean forceReceive = false; //下面這段代碼用于判斷此條廣播是否處理時間過長 //先得到該條廣播的所有接收者 intnumReceivers = (r.receivers != null) ? r.receivers.size() : 0; if(mProcessesReady && r.dispatchTime > 0) { long now = SystemClock.uptimeMillis(); //如果總耗時超過2倍的接收者個數*每個接收者最長處理時間(10秒),則 //強制結束這條廣播的處理 if ((numReceivers > 0) && (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))){ broadcastTimeoutLocked(false);//讀者閱讀完本節后可自行研究該函數 forceReceive = true; r.state = BroadcastRecord.IDLE; } }//if(mProcessesReady...)判斷結束 if (r.state != BroadcastRecord.IDLE) return; //如果下面這個if條件滿足,則表示該條廣播要么已經全部被處理,要么被中途取消 if(r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { if(r.resultTo != null) { try { //將該廣播的處理結果傳給設置了resultTo的接收者 performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false); r.resultTo = null; }...... } cancelBroadcastTimeoutLocked(); addBroadcastToHistoryLocked(r); mOrderedBroadcasts.remove(0); r = null; looped = true; continue; } } while (r== null); ~~~ processNextBroadcast第二階段的工作比較簡單: - 首先根據是否處于pending狀態(mPendingBroadcast不為null)進行相關操作。讀者要認真體會代碼中的重要說明。 - 處理超時的廣播記錄。這個超時時間是2*BROADCAST_TIMEOUT*numReceivers。BROADCAST_TIMEOUT默認為10秒。由于涉及創建進程,初始化Android運行環境等重體力活,故此處超時時間還乘以一個固定倍數2。 3. processNextBroadcast分析之三 來看processNextBroadcast第三階段的工作,代碼如下: **ActivityManagerService.java::processNextBroadcast** ~~~ int recIdx= r.nextReceiver++; r.receiverTime = SystemClock.uptimeMillis(); if (recIdx== 0) { r.dispatchTime = r.receiverTime;//記錄本廣播第一次處理開始的時間 r.dispatchClockTime= System.currentTimeMillis(); } //設置廣播處理超時時間,BROADCAST_TIMEOUT為10秒 if (!mPendingBroadcastTimeoutMessage) { longtimeoutTime = r.receiverTime + BROADCAST_TIMEOUT; setBroadcastTimeoutLocked(timeoutTime); } //取該條廣播下一個接收者 ObjectnextReceiver = r.receivers.get(recIdx); if(nextReceiver instanceof BroadcastFilter) { //如果是動態接收者,則直接調用deliverToRegisteredReceiverLocked處理 BroadcastFilter filter = (BroadcastFilter)nextReceiver; deliverToRegisteredReceiverLocked(r, filter, r.ordered); if(r.receiver == null || !r.ordered) { r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); } return;//已經通知一個接收者去處理該廣播,需要等它的處理結果,所以此處直接返回 } //如果是靜態接收者,則它的真實類型是ResolveInfo ResolveInfo info = (ResolveInfo)nextReceiver; booleanskip = false; //檢查權限 int perm =checkComponentPermission(info.activityInfo.permission, r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid, info.activityInfo.exported); if (perm!= PackageManager.PERMISSION_GRANTED) skip = true; if(info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && r.requiredPermission != null) { ...... } //設置skip為true if(r.curApp != null && r.curApp.crashing) skip = true; if (skip){ r.receiver = null; r.curFilter = null; r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked();//再調度一次廣播處理 return; } r.state= BroadcastRecord.APP_RECEIVE; StringtargetProcess = info.activityInfo.processName; r.curComponent = new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); r.curReceiver = info.activityInfo; try { //設置Package stopped的狀態為false AppGlobals.getPackageManager().setPackageStoppedState( r.curComponent.getPackageName(),false); } ...... ProcessRecord app = getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid); //如果該接收者對應的進程已經存在 if (app!= null && app.thread != null) { try { app.addPackage(info.activityInfo.packageName); //該函數內部調用應用進程的scheduleReceiver函數,讀者可自行分析 processCurBroadcastLocked(r, app); return;//已經觸發該接收者處理本廣播,需要等待處理結果 }...... } //最糟的情況就是該進程還沒有啟動 if((r.curApp=startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true,......)!= 0)) == null) { ......//進程啟動失敗的處理 return; } mPendingBroadcast = r; //設置mPendingBroadcast mPendingBroadcastRecvIndex = recIdx; } ~~~ 對processNextBroadcast第三階段的工作總結如下: - 如果廣播接收者為動態注冊對象,則直接調用deliverToRegisteredReceiverLocked處理它。 - 如果廣播接收者為靜態注冊對象,并且該對象對應的進程已經存在,則調用processCurBroadcastLocked處理它。 - 如果廣播接收者為靜態注冊對象,并且該對象對應的進程還不存在,則需要創建該進程。這是最糟糕的情況。 此處,不再討論新進程創建及Android運行環境初始化相關的邏輯,讀者可返回閱讀“attachApplicationLocked分析之三”,其中有處理mPendingBroadcast的內容。
                  <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>

                              哎呀哎呀视频在线观看