BroadcastReceiver流程解析

 

ContextImplregisterReceiver方法

首先查看註冊方法

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
        int flags) {
    return registerReceiver(receiver, filter, null, null, flags);
}

 

內部調用了registerReceiverInternal方法,這個方法裏面會調用AMSregisterReceiver方法,這裏有個參數rd,很重要,因爲後面我們的回調就是在這裏類裏面。IIntentReceiver是個啥呢,在as裏面按ctrl是點不出來的,查看android系統源碼,

 

發現是個AIDL文件。先往下走

 

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true);
        } else {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = new LoadedApk.ReceiverDispatcher(
                    receiver, context, scheduler, null, true).getIIntentReceiver();
        }
    }
    try {
        final Intent intent = ActivityManager.getService().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                broadcastPermission, userId, flags);
        if (intent != null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

AMSregisterReceiver方法,將APP端傳過來的receiver參數封裝到一個ReceiverList對象。

ReceiverList對象又封裝到BroadcastFilter對象,BroadcastFilter對象又添加到mReceiverResolver的一個集合裏,現在我們知道我們的receiver對象是存到了mReceiverResolver

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
        int flags) {
    enforceNotIsolatedCaller("registerReceiver");
    ArrayList<Intent> stickyIntents = null;
    ProcessRecord callerApp = null;
    final boolean visibleToInstantApps
            = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
    int callingUid;
    int callingPid;
    boolean instantApp;
    synchronized (this) {
        if (callerApp != null && (callerApp.thread == null
                || callerApp.thread.asBinder() != caller.asBinder())) {
            // Original caller already died
            return null;
        }


        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {

//receiver封裝到一個ReceiverList對象
            rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                    userId, receiver);
            if (rl.app != null) {
                rl.app.receivers.add(rl);
            } else {
                try {
                    receiver.asBinder().linkToDeath(rl, 0);
                } catch (RemoteException e) {
                    return sticky;
                }
                rl.linkedToDeath = true;
            }
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        }         

//rl又封裝到BroadcastFilter

BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId, instantApp, visibleToInstantApps);
        rl.add(bf);
        if (!bf.debugCheck()) {
            Slog.w(TAG, "==> For Dynamic broadcast");
        }

//bf添加到mReceiverResolver內部的ArraySet集合中了
        mReceiverResolver.addFilter(bf);

        
        return sticky;
    }
}

 

查看發送廣播的方法

ContextImpl類裏面。調用了AMSbroadcastIntent方法

@Override
public void sendBroadcast(Intent intent) {
    warnIfCallingFromSystemProcess();
    String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
    try {
        intent.prepareToLeaveProcess(this);
        ActivityManager.getService().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                getUserId());
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

 

 

AMS broadcastIntent方法,

public final int broadcastIntent(IApplicationThread caller,
        Intent intent, String resolvedType, IIntentReceiver resultTo,
        int resultCode, String resultData, Bundle resultExtras,
        String[] requiredPermissions, int appOp, Bundle bOptions,
        boolean serialized, boolean sticky, int userId) {
    enforceNotIsolatedCaller("broadcastIntent");
    synchronized(this) {
        intent = verifyBroadcastLocked(intent);

        final ProcessRecord callerApp = getRecordForAppLocked(caller);
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        int res = broadcastIntentLocked(callerApp,
                callerApp != null ? callerApp.info.packageName : null,
                intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                requiredPermissions, appOp, bOptions, serialized, sticky,
                callingPid, callingUid, userId);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}

內部調用了broadcastIntentLocked方法。這個方法比較長,前面的流程是在判斷是否是系統的廣播,如果是系統的廣播,則拋出安全權限異常。獲取所有接收該廣播的廣播接收器,然後封裝到BroadcastRecord對象,並且添加到BroadcastQueue中。省略了部分代碼

final int broadcastIntentLocked(省略參數) {
    intent = new Intent(intent);
    final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
  
    userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
            ALLOW_NON_FULL, "broadcast", callerPackage);
    BroadcastOptions brOptions = null;

    // Verify that protected broadcasts are only being sent by system code,
    // and that system code is only sending protected broadcasts.
    final String action = intent.getAction();
    final boolean isProtectedBroadcast;
    final boolean isCallerSystem;
    int[] users;
    if (userId == UserHandle.USER_ALL) {
        // Caller wants broadcast to go to all started users.
        users = mUserController.getStartedUserArrayLocked();
    } else {
        // Caller wants broadcast to go to one specific user.
        users = new int[] {userId};
    }
if (intent.getComponent() == null) {
    if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
        // Query one target user at a time, excluding shell-restricted users
        for (int i = 0; i < users.length; i++) {
            if (mUserController.hasUserRestriction(
                    UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                continue;
            }
            List<BroadcastFilter> registeredReceiversForUser =
                    mReceiverResolver.queryIntent(intent,
                            resolvedType, false /*defaultOnly*/, users[i]);
            if (registeredReceivers == null) {
                registeredReceivers = registeredReceiversForUser;
            } else if (registeredReceiversForUser != null) {
                registeredReceivers.addAll(registeredReceiversForUser);
            }
        }
    } else {
        registeredReceivers = mReceiverResolver.queryIntent(intent,
                resolvedType, false /*defaultOnly*/, userId);
    }
}


    // Figure out who all will receive this broadcast.
    List receivers = null;
    List<BroadcastFilter> registeredReceivers = null;
     final boolean replacePending =
            (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    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.
        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, registeredReceivers);
        }
        final BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                resultCode, resultData, resultExtras, ordered, sticky, false, userId);
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
        final boolean replaced = replacePending
                && (queue.replaceParallelBroadcastLocked(r) != null);
        // Note: We assume resultTo is null for non-ordered broadcasts.
        if (!replaced) {
            queue.enqueueParallelBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        NR = 0;
    }
    if ((receivers != null && receivers.size() > 0)
            || resultTo != null) {
        BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                resultData, resultExtras, ordered, sticky, false, userId);

        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
                + ": prev had " + queue.mOrderedBroadcasts.size());
        if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                "Enqueueing broadcast " + r.intent.getAction());

        final BroadcastRecord oldRecord =
                replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
        if (oldRecord != null) {
            // Replaced, fire the result-to receiver.
            if (oldRecord.resultTo != null) {
                final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                try {
                    oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                            oldRecord.intent,
                            Activity.RESULT_CANCELED, null, null,
                            false, false, oldRecord.userId);
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failure ["
                            + queue.mQueueName + "] sending broadcast result of "
                            + intent, e);

                }
            }
        } else {
            queue.enqueueOrderedBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
    }   

}

    return ActivityManager.BROADCAST_SUCCESS;
}

方法判斷也很多,不過最終也會走到

queue.enqueueOrderedBroadcastLocked方法和scheduleBroadcastsLocked方法

BroadcastQueue看名字就可知道,廣播隊列

enqueueOrderedBroadcastLocked方法把廣播添加到當前mParallelBroadcasts集合

public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
    mParallelBroadcasts.add(r);
    enqueueBroadcastHelper(r);
}

scheduleBroadcastsLocked方法,發送了一個消息

public void scheduleBroadcastsLocked() {
    if (mBroadcastsScheduled) {
        return;
    }
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

 

查看處理消息的地方

case BROADCAST_INTENT_MSG: {
    if (DEBUG_BROADCAST) Slog.v(
            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
    processNextBroadcast(true);
}

processNextBroadcast方法也是很長很長,不過看重點代碼

前面我們知道enqueueOrderedBroadcastLocked方法的時候在mParallelBroadcasts裏面就添加一條信息,現在這裏取出來,然後拿到所有receivers對象,receivers就是我們前面獲取到的。

final void processNextBroadcast(boolean fromMsg) {
    synchronized(mService) {
        BroadcastRecord r;

//省略部分代碼
        // First, deliver any non-serialized broadcasts right away.
        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);
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Delivering non-ordered on [" + mQueueName + "] to registered "
                        + target + ": " + r);
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
            }
            addBroadcastToHistoryLocked(r);
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                    + mQueueName + "] " + r);
        }
  
        boolean looped = false;
         // Get the next receiver...
        int recIdx = r.nextReceiver++;

        // Keep track of when this receiver started, and make sure there
        // is a timeout message pending to kill it if need be.
        r.receiverTime = SystemClock.uptimeMillis();

....省略後面代碼
    }

 

deliverToRegisteredReceiverLocked方法,裏面調用了performReceiveLocked方法

 

 

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
        BroadcastFilter filter, boolean ordered, int index) {
    boolean skip = false;
    try {
        if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                "Delivering to " + filter + " : " + r);
        if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
            // Skip delivery if full backup in progress
            // If it's an ordered broadcast, we need to continue to the next receiver.
            if (ordered) {
                skipReceiverLocked(r);
            }
        } else {
            performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode, r.resultData,
                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
        }
      
}

performReceiveLocked方法

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
        Intent intent, int resultCode, String data, Bundle extras,
        boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
    // Send the intent to the receiver asynchronously using one-way binder calls.
    if (app != null) {
        if (app.thread != null) {
            // If we have an app thread, do the call through that so it is
            // correctly ordered with other one-way calls.
            try {
                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                        data, extras, ordered, sticky, sendingUser, app.repProcState);
                } catch (RemoteException ex) {
                // Failed to call into the process. It's either dying or wedged. Kill it gently.
                synchronized (mService) {
                    Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                            + " (pid " + app.pid + "). Crashing it.");
                    app.scheduleCrash("can't deliver broadcast");
                }
                throw ex;
            }
        } }

調用了ActivityThreadscheduleRegisteredReceiver方法

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
        int resultCode, String dataStr, Bundle extras, boolean ordered,
        boolean sticky, int sendingUser, int processState) throws RemoteException {
    updateProcessState(processState, false);
    receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
            sticky, sendingUser);
}

這裏調用了receiverperformReceive方法,應該猜想裏面應該會回調我們的onReceive方法

而這個receiver就是我們註冊的時候設置的

再看註冊的方法

 

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    IIntentReceiver rd = null;
    if (receiver != null) {
        if (mPackageInfo != null && context != null) {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true);
        } else {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }
            rd = new LoadedApk.ReceiverDispatcher(
                    receiver, context, scheduler, null, true).getIIntentReceiver();
        }
    }
}

LoadedApk.ReceiverDispatcher

static final class ReceiverDispatcher {
    final static class InnerReceiver extends IIntentReceiver.Stub {
        final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
        final LoadedApk.ReceiverDispatcher mStrongRef;
         @Override
        public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            final LoadedApk.ReceiverDispatcher rd;
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
                rd = null;
            } else {
                rd = mDispatcher.get();
            }
            if (rd != null) {
                rd.performReceive(intent, resultCode, data, extras,
                        ordered, sticky, sendingUser);
            }         }
    }

調用了LoadedApkperformReceive方法

查看LoadedApkperformReceive方法

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final Args args = new Args(intent, resultCode, data, extras, ordered,
            sticky, sendingUser);
        if (intent == null || !mActivityThread.post(args.getRunnable())) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManager.getService();
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing sync broadcast to " + mReceiver);
            args.sendFinished(mgr);
        }
    }
}

post了一個Runnable

這個Runnable裏面的代碼就會調用我們的onReceive方法

public final Runnable getRunnable() {
    return () -> {
        final BroadcastReceiver receiver = mReceiver;
        final IActivityManager mgr = ActivityManager.getService();
        final Intent intent = mCurIntent;
        mCurIntent = null;
        mDispatched = true;
        mPreviousRunStacktrace = new Throwable("Previous stacktrace");
        try {
            ClassLoader cl = mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
            receiver.onReceive(mContext, intent);
        } catch (Exception e) {
          }
          };
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章