Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android系統教程 >> Android開發教程 >> android安全問題(七) 搶先接收廣播 - 內因篇之廣播發送流程

android安全問題(七) 搶先接收廣播 - 內因篇之廣播發送流程

編輯:Android開發教程

現在給出第二步分的分析

下面就來看看發送廣播的流程

Context中的sendBroadCast函數的 實現是在ContextImpl中,和發送廣播相關的有如下六個函數

void android.app.ContextImpl.sendBroadcast(Intent intent)

void android.app.ContextImpl.sendBroadcast(Intent intent, String receiverPermission)

void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission)

void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)

void android.app.ContextImpl.sendStickyBroadcast(Intent intent)

void android.app.ContextImpl.sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)

可以分為3組:1普通廣播;2Ordered廣播;3Sticky廣播

不論哪種,最後都會 由ActivityManagerService處理

private final int broadcastIntentLocked(ProcessRecord 

callerApp,  
        String callerPackage, Intent intent, String resolvedType,  
        IIntentReceiver resultTo, int resultCode, String resultData,  
        Bundle map, String requiredPermission,  
        boolean ordered, boolean sticky, int callingPid, int callingUid)

以第一種情況為 例,流程圖大概是這個樣子的

ordered和sticky用來區分上面3組廣播

下面我們仔細看看這個方 法都干了些什麼

刪減了一些代碼

private final int broadcastIntentLocked

(ProcessRecord callerApp,  
        String callerPackage, Intent intent, String resolvedType,  
        IIntentReceiver resultTo, int resultCode, String resultData,  
        Bundle map, String requiredPermission,  
        boolean ordered, boolean sticky, int callingPid, int callingUid) {  
    ...//處理特殊intent  
    // Add to the sticky list if requested.  
    ...//處理sticky廣播  
    // Figure out who all will receive this broadcast.  
    List receivers = null;  
    List<BroadcastFilter> registeredReceivers = null;  
    try {  
        if (intent.getComponent() != null) {  
            // Broadcast is going to one specific receiver class...  
            ActivityInfo ai = AppGlobals.getPackageManager().  
                getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);  
            if (ai != null) {  
                receivers = new ArrayList();  
                ResolveInfo ri = new ResolveInfo();  
                ri.activityInfo = ai;  
                receivers.add(ri);  
            }  
        } else {  
            // Need to resolve the intent to interested receivers...  
            if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)  
                     == 0) {  
                receivers =  
                    AppGlobals.getPackageManager().queryIntentReceivers(  
                            intent, resolvedType, STOCK_PM_FLAGS);  
            }  
            registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);  
        }  
    } catch (RemoteException ex) {  
        // pm is in same process, this will never happen.  
    }  
      
    final boolean replacePending =  
            (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;  
    ...  
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;  
    ...//如果廣播是非ordered,先處理動態注冊的接收器  
    if (!ordered && NR > 0) {  
        // If we are not serializing this broadcast, then send the  
        // registered receivers separately so they don't wait for the  
        // components to be launched.  
        BroadcastRecord r = new BroadcastRecord(intent, callerApp,  
                callerPackage, callingPid, callingUid, requiredPermission,  
                registeredReceivers, resultTo, resultCode, resultData, map,  
                ordered, sticky, false);  
        ...  
    //mParallelBroadcasts只含有動態注冊的receiver  
        boolean replaced = false;  
        if (replacePending) {  
            for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {  
                if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {  
                    if (DEBUG_BROADCAST) Slog.v(TAG,  
                            "***** DROPPING PARALLEL: " + intent);  
                    mParallelBroadcasts.set(i, r);  
                    replaced = true;  
                    break;  
                }  
            }  
        }  
        if (!replaced) {  
            mParallelBroadcasts.add(r);  
            scheduleBroadcastsLocked();  
        }  
        registeredReceivers = null;  
        NR = 0;  
    }  
      
    // Merge into one list.  
    //如果廣播是ordered,合並靜態、動態接收器  
    //否則之前處理過動態接收器,這裡registeredReceivers為null  
    int ir = 0;  
    if (receivers != null) {  
        ...  
        //合並的過程,注意順序  
        int NT = receivers != null ? receivers.size() : 0;  
        int it = 0;  
        ResolveInfo curt = null;  
        BroadcastFilter curr = null;  
        while (it < NT && ir < NR) {  
            if (curt == null) {  
                curt = (ResolveInfo)receivers.get(it);  
            }  
            if (curr == null) {  
                curr = registeredReceivers.get(ir);  
            }  
            //如果動態接收器優先級高,那麼就插到前面  
            //否則進入else,然後進行下一輪比較,拿下一個靜態接收器與之前的動態接收器比較,直到找到自己的位置才插入進列表中  
            //在這裡,調整好接收器的順序,同等優先級的,顯然動態的要在靜態的前面  
            if (curr.getPriority() >= curt.priority) {  
                // Insert this broadcast record into the final list.  
                receivers.add(it, curr);  
                ir++;  
                curr = null;  
                it++;  
                NT++;  
            } else {  
                // Skip to the next ResolveInfo in the final list.  
                it++;  
                curt = null;  
            }  
        }  
    }  
    while (ir < NR) {  
        if (receivers == null) {  
            receivers = new ArrayList();  
        }  
        receivers.add(registeredReceivers.get(ir));  
        ir++;  
    }  
      
    if ((receivers != null && receivers.size() > 0)  
            || resultTo != null) {  
        BroadcastRecord r = new BroadcastRecord(intent, callerApp,  
                callerPackage, callingPid, callingUid, requiredPermission,  
                receivers, resultTo, resultCode, resultData, map, ordered,  
                sticky, false);  
        ...  
        if (!replaced) {  
            mOrderedBroadcasts.add(r);  
            scheduleBroadcastsLocked();  
        }  
    }  
      
    return BROADCAST_SUCCESS;  
}

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved