美文网首页
跨进程广播的工作原理(4)

跨进程广播的工作原理(4)

作者: snake_6d77 | 来源:发表于2019-10-10 15:03 被阅读0次

    动态广播接收者的查询

    上一篇文章我们分析了静态广播接收者的查找实现,接下来我们继续分析动态广播接收者的查找以及之后的广播分发逻辑

    动态广播接收者的查询实现

    image.png

    动态广播接收者的查询用的是ActivityManagerService中的成员变量mReceiverResolver,mReceiverResolver也是IntentResolver的实例化对象,所以里面的查询方法和静态广播接收者的查询方法是一样的,而mReceiverResolver缓存数据的添加则是在registerReceiver方法内完成了。这边对动态广播接收者的查找我们就不再深入分析。

    广播的最后分发

    我们找到Intent匹配的接收者后就只剩下最后的工作了:在对应的进程内回调对应接收者的onReceive方法。

    public final class BroadcastQueue {
        .....
        public void scheduleBroadcastsLocked() {
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                    + mQueueName + "]: current="
                    + mBroadcastsScheduled);
    
            if (mBroadcastsScheduled) {
                return;
            }
            mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
            mBroadcastsScheduled = true;
        }
    
        final BroadcastHandler mHandler;
    
        private final class BroadcastHandler extends Handler {
            public BroadcastHandler(Looper looper) {
                super(looper, null, true);
            }
    
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case BROADCAST_INTENT_MSG: {
                        if (DEBUG_BROADCAST) Slog.v(
                                TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
                        processNextBroadcast(true);
                    } break;
                    case BROADCAST_TIMEOUT_MSG: {
                        synchronized (mService) {
                            broadcastTimeoutLocked(true);
                        }
                    } break;
                }
            }
        }
    
        final void processNextBroadcast(boolean fromMsg) {
            synchronized(mService) {
                BroadcastRecord r;
    
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
                        + mQueueName + "]: "
                        + mParallelBroadcasts.size() + " parallel broadcasts, "
                        + mOrderedBroadcasts.size() + " ordered broadcasts");
                //更新cpu使用状态
                mService.updateCpuStats();
                //重置mBroadcastsScheduled广播执行标志
                if (fromMsg) {
                    mBroadcastsScheduled = false;
                }
    
                // First, deliver any non-serialized broadcasts right away.
                //首先分发无序广播
                while (mParallelBroadcasts.size() > 0) {
                    //获取集合中的第一个动态广播接收者记录
                    r = mParallelBroadcasts.remove(0);
                    r.dispatchTime = SystemClock.uptimeMillis();
                    r.dispatchClockTime = System.currentTimeMillis();
    
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                            System.identityHashCode(r));
                        Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                            System.identityHashCode(r));
                    }
                   
                    final int N = r.receivers.size();
                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                            + mQueueName + "] " + r);
                   //遍历匹配的广播接收者,然后发送广播到动态广播接收者
                    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);
                }
    
                // Now take care of the next serialized one...
                //接下来考虑有序的
    
                // If we are waiting for a process to come up to handle the next
                // broadcast, then do nothing at this point.  Just in case, we
                // check that the process we're waiting for still exists.
                //如果我们正在等待一个进程出现来处理下一个广播,
                //那么此时什么也不要做。以防万一,我们检查正在等待的进程是否仍然存在。
                if (mPendingBroadcast != null) {
                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                            "processNextBroadcast [" + mQueueName + "]: waiting for "
                            + mPendingBroadcast.curApp);
    
                    boolean isDead;
                    synchronized (mService.mPidsSelfLocked) {
                        ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
                        isDead = proc == null || proc.crashing;
                    }
                    if (!isDead) {
                        // It's still alive, so keep waiting
                        return;
                    } else {
                        Slog.w(TAG, "pending app  ["
                                + mQueueName + "]" + mPendingBroadcast.curApp
                                + " died before responding to broadcast");
                        mPendingBroadcast.state = BroadcastRecord.IDLE;
                        mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                        mPendingBroadcast = null;
                    }
                }
    
                boolean looped = false;
                
                do {
                    if (mOrderedBroadcasts.size() == 0) {
                        // No more broadcasts pending, so all done!
                        //没有其它接收者在等待了,触发垃圾回收
                        mService.scheduleAppGcsLocked();
                        if (looped) {
                            // If we had finished the last ordered broadcast, then
                            // make sure all processes have correct oom and sched
                            // adjustments.
                            mService.updateOomAdjLocked();
                        }
                        return;
                    }
                    r = mOrderedBroadcasts.get(0);
                    boolean forceReceive = false;
    
                    // Ensure that even if something goes awry with the timeout
                    // detection, we catch "hung" broadcasts here, discard them,
                    // and continue to make progress.
                    //
                    // This is only done if the system is ready so that PRE_BOOT_COMPLETED
                    // receivers don't get executed with timeouts. They're intended for
                    // one time heavy lifting after system upgrades and can take
                    // significant amounts of time.
                    //确保即使超时检测出现错误,我们也能在这里捕获“挂起”广播,丢弃它们,并继续执行
                    //只有当系统准备好了,这样PRE_BOOT_COMPLETED接收器才不会在超时的情况下执行时,才会执行此操作。
                    //它们只适用于系统升级后的一次繁重工作,并且可能会花费大量时间。
                    int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
                    if (mService.mProcessesReady && r.dispatchTime > 0) {
                        long now = SystemClock.uptimeMillis();
                        if ((numReceivers > 0) &&
                                (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
                            Slog.w(TAG, "Hung broadcast ["
                                    + mQueueName + "] discarded after timeout failure:"
                                    + " now=" + now
                                    + " dispatchTime=" + r.dispatchTime
                                    + " startTime=" + r.receiverTime
                                    + " intent=" + r.intent
                                    + " numReceivers=" + numReceivers
                                    + " nextReceiver=" + r.nextReceiver
                                    + " state=" + r.state);
                            //强行发送超时广播
                            broadcastTimeoutLocked(false); // forcibly finish this broadcast
                            forceReceive = true;
                            r.state = BroadcastRecord.IDLE;
                        }
                    }
    
                    if (r.state != BroadcastRecord.IDLE) {
                        if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
                                "processNextBroadcast("
                                + mQueueName + ") called when not idle (state="
                                + r.state + ")");
                        return;
                    }
    
                    if (r.receivers == null || r.nextReceiver >= numReceivers
                            || r.resultAbort || forceReceive) {
                        // No more receivers for this broadcast!  Send the final
                        // result if requested...
                       //这次广播没有接收器了!如果需要,发送广播到目标进程的分发器…
                        if (r.resultTo != null) {
                            try {
                                if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                                        "Finishing broadcast [" + mQueueName + "] "
                                        + r.intent.getAction() + " app=" + r.callerApp);
                                performReceiveLocked(r.callerApp, r.resultTo,
                                    new Intent(r.intent), r.resultCode,
                                    r.resultData, r.resultExtras, false, false, r.userId);
                                // Set this to null so that the reference
                                // (local and remote) isn't kept in the mBroadcastHistory.
                                r.resultTo = null;
                            } catch (RemoteException e) {
                                r.resultTo = null;
                                Slog.w(TAG, "Failure ["
                                        + mQueueName + "] sending broadcast result of "
                                        + r.intent, e);
    
                            }
                        }
    
                        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
                        cancelBroadcastTimeoutLocked();
    
                        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                                "Finished with ordered broadcast " + r);
    
                        // ... and on to the next...添加广播发送记录
                        addBroadcastToHistoryLocked(r);
                        if (r.intent.getComponent() == null && r.intent.getPackage() == null
                                && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                            // This was an implicit broadcast... let's record it for posterity.
                            //隐藏广播,保存待后续执行
                            mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                                    r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
                        }
                        mOrderedBroadcasts.remove(0);
                        r = null;
                        looped = true;
                        continue;
                    }
                } while (r == null);
    
                // 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();
                if (recIdx == 0) {
                    r.dispatchTime = r.receiverTime;
                    r.dispatchClockTime = System.currentTimeMillis();
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                            System.identityHashCode(r));
                        Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                            System.identityHashCode(r));
                    }
                    if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
                            + mQueueName + "] " + r);
                }
                if (! mPendingBroadcastTimeoutMessage) {
                    long timeoutTime = r.receiverTime + mTimeoutPeriod;
                    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                            "Submitting BROADCAST_TIMEOUT_MSG ["
                            + mQueueName + "] for " + r + " at " + timeoutTime);
                    setBroadcastTimeoutLocked(timeoutTime);
                }
    
                final BroadcastOptions brOptions = r.options;
                final Object nextReceiver = r.receivers.get(recIdx);
    
                if (nextReceiver instanceof BroadcastFilter) {
                    // Simple case: this is a registered receiver who gets
                    // a direct call.
                    //这是一个指定目标的动态广播接收者
                    BroadcastFilter filter = (BroadcastFilter)nextReceiver;
                    if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                            "Delivering ordered ["
                            + mQueueName + "] to registered "
                            + filter + ": " + r);
                    deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
                    if (r.receiver == null || !r.ordered) {
                        // The receiver has already finished, so schedule to
                        // process the next one.
                        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
                                + mQueueName + "]: ordered="
                                + r.ordered + " receiver=" + r.receiver);
                        r.state = BroadcastRecord.IDLE;
                        scheduleBroadcastsLocked();
                    } else {
                        if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                            scheduleTempWhitelistLocked(filter.owningUid,
                                    brOptions.getTemporaryAppWhitelistDuration(), r);
                        }
                    }
                    return;
                }
    
                // Hard case: need to instantiate the receiver, possibly
                // starting its application process to host it.
                //案例:需要实例化接收器,可能需要启动它的应用程序进程来加载它。
    
                ResolveInfo info =
                    (ResolveInfo)nextReceiver;
                ComponentName component = new ComponentName(
                        info.activityInfo.applicationInfo.packageName,
                        info.activityInfo.name);
    
                boolean skip = false;
                if (brOptions != null &&
                        (info.activityInfo.applicationInfo.targetSdkVersion
                                < brOptions.getMinManifestReceiverApiLevel() ||
                        info.activityInfo.applicationInfo.targetSdkVersion
                                > brOptions.getMaxManifestReceiverApiLevel())) {
                    skip = true;
                }
                //权限检查
                int perm = mService.checkComponentPermission(info.activityInfo.permission,
                        r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
                        info.activityInfo.exported);
                if (!skip && perm != PackageManager.PERMISSION_GRANTED) {
                    if (!info.activityInfo.exported) {
                        Slog.w(TAG, "Permission Denial: broadcasting "
                                + r.intent.toString()
                                + " from " + r.callerPackage + " (pid=" + r.callingPid
                                + ", uid=" + r.callingUid + ")"
                                + " is not exported from uid " + info.activityInfo.applicationInfo.uid
                                + " due to receiver " + component.flattenToShortString());
                    } else {
                        Slog.w(TAG, "Permission Denial: broadcasting "
                                + r.intent.toString()
                                + " from " + r.callerPackage + " (pid=" + r.callingPid
                                + ", uid=" + r.callingUid + ")"
                                + " requires " + info.activityInfo.permission
                                + " due to receiver " + component.flattenToShortString());
                    }
                    skip = true;
                } else if (!skip && info.activityInfo.permission != null) {
                    final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
                    if (opCode != AppOpsManager.OP_NONE
                            && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
                                    r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
                        Slog.w(TAG, "Appop Denial: broadcasting "
                                + r.intent.toString()
                                + " from " + r.callerPackage + " (pid="
                                + r.callingPid + ", uid=" + r.callingUid + ")"
                                + " requires appop " + AppOpsManager.permissionToOp(
                                        info.activityInfo.permission)
                                + " due to registered receiver "
                                + component.flattenToShortString());
                        skip = true;
                    }
                }
                if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
                    r.requiredPermissions != null && r.requiredPermissions.length > 0) {
                    for (int i = 0; i < r.requiredPermissions.length; i++) {
                        String requiredPermission = r.requiredPermissions[i];
                        try {
                            perm = AppGlobals.getPackageManager().
                                    checkPermission(requiredPermission,
                                            info.activityInfo.applicationInfo.packageName,
                                            UserHandle
                                                    .getUserId(info.activityInfo.applicationInfo.uid));
                        } catch (RemoteException e) {
                            perm = PackageManager.PERMISSION_DENIED;
                        }
                        if (perm != PackageManager.PERMISSION_GRANTED) {
                            Slog.w(TAG, "Permission Denial: receiving "
                                    + r.intent + " to "
                                    + component.flattenToShortString()
                                    + " requires " + requiredPermission
                                    + " due to sender " + r.callerPackage
                                    + " (uid " + r.callingUid + ")");
                            skip = true;
                            break;
                        }
                        int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
                        if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
                                && mService.mAppOpsService.noteOperation(appOp,
                                info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
                                != AppOpsManager.MODE_ALLOWED) {
                            Slog.w(TAG, "Appop Denial: receiving "
                                    + r.intent + " to "
                                    + component.flattenToShortString()
                                    + " requires appop " + AppOpsManager.permissionToOp(
                                    requiredPermission)
                                    + " due to sender " + r.callerPackage
                                    + " (uid " + r.callingUid + ")");
                            skip = true;
                            break;
                        }
                    }
                }
                if (!skip && r.appOp != AppOpsManager.OP_NONE
                        && mService.mAppOpsService.noteOperation(r.appOp,
                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
                        != AppOpsManager.MODE_ALLOWED) {
                    Slog.w(TAG, "Appop Denial: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString()
                            + " requires appop " + AppOpsManager.opToName(r.appOp)
                            + " due to sender " + r.callerPackage
                            + " (uid " + r.callingUid + ")");
                    skip = true;
                }
                //Intent防火墙过滤
                if (!skip) {
                    skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
                            r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
                }
                boolean isSingleton = false;
                try {
                    isSingleton = mService.isSingleton(info.activityInfo.processName,
                            info.activityInfo.applicationInfo,
                            info.activityInfo.name, info.activityInfo.flags);
                } catch (SecurityException e) {
                    Slog.w(TAG, e.getMessage());
                    skip = true;
                }
                if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                    if (ActivityManager.checkUidPermission(
                            android.Manifest.permission.INTERACT_ACROSS_USERS,
                            info.activityInfo.applicationInfo.uid)
                                    != PackageManager.PERMISSION_GRANTED) {
                        Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
                                + " requests FLAG_SINGLE_USER, but app does not hold "
                                + android.Manifest.permission.INTERACT_ACROSS_USERS);
                        skip = true;
                    }
                }
                if (!skip && info.activityInfo.applicationInfo.isInstantApp()
                        && r.callingUid != info.activityInfo.applicationInfo.uid) {
                    Slog.w(TAG, "Instant App Denial: receiving "
                            + r.intent
                            + " to " + component.flattenToShortString()
                            + " due to sender " + r.callerPackage
                            + " (uid " + r.callingUid + ")"
                            + " Instant Apps do not support manifest receivers");
                    skip = true;
                }
                if (!skip && r.callerInstantApp
                        && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0
                        && r.callingUid != info.activityInfo.applicationInfo.uid) {
                    Slog.w(TAG, "Instant App Denial: receiving "
                            + r.intent
                            + " to " + component.flattenToShortString()
                            + " requires receiver have visibleToInstantApps set"
                            + " due to sender " + r.callerPackage
                            + " (uid " + r.callingUid + ")");
                    skip = true;
                }
                if (!skip) {
                    r.manifestCount++;
                } else {
                    r.manifestSkipCount++;
                }
                //如果目标进程崩溃了,就跳过它。
                if (r.curApp != null && r.curApp.crashing) {
                    // If the target process is crashing, just skip it.
                    Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
                            + " to " + r.curApp + ": process crashing");
                    skip = true;
                }
                if (!skip) {
                    boolean isAvailable = false;
                    try {
                        isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
                                info.activityInfo.packageName,
                                UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
                    } catch (Exception e) {
                        // all such failures mean we skip this receiver
                        Slog.w(TAG, "Exception getting recipient info for "
                                + info.activityInfo.packageName, e);
                    }
                    if (!isAvailable) {
                        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                                "Skipping delivery to " + info.activityInfo.packageName + " / "
                                + info.activityInfo.applicationInfo.uid
                                + " : package no longer available");
                        skip = true;
                    }
                }
    
                // If permissions need a review before any of the app components can run, we drop
                // the broadcast and if the calling app is in the foreground and the broadcast is
                // explicit we launch the review UI passing it a pending intent to send the skipped
                // broadcast.
                //如果权限需要在任何应用程序组件运行之前进行审查,我们将删除广播;
                //如果调用应用程序位于前台,并且广播是显式的,我们将启动审查UI,
                //并将一个pending intent传递给它,以发送跳过的广播。
                if (mService.mPermissionReviewRequired && !skip) {
                    if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
                            info.activityInfo.packageName, UserHandle.getUserId(
                                    info.activityInfo.applicationInfo.uid))) {
                        skip = true;
                    }
                }
    
                // This is safe to do even if we are skipping the broadcast, and we need
                // this information now to evaluate whether it is going to be allowed to run.
                //即使我们跳过广播,这样做也是安全的,我们现在需要这个信息来评估是否允许它运行。
                final int receiverUid = info.activityInfo.applicationInfo.uid;
                // If it's a singleton, it needs to be the same app or a special app
                //如果它是一个单例,它需要是相同的应用程序或一个特殊的应用程序
                if (r.callingUid != Process.SYSTEM_UID && isSingleton
                        && mService.isValidSingletonCall(r.callingUid, receiverUid)) {
                    info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
                }
                String targetProcess = info.activityInfo.processName;
                //获取目标接收者所在进程
                ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                        info.activityInfo.applicationInfo.uid, false);
    
                if (!skip) {
                    final int allowed = mService.getAppStartModeLocked(
                            info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
                            info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false);
                    if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                        // We won't allow this receiver to be launched if the app has been
                        // completely disabled from launches, or it was not explicitly sent
                        // to it and the app is in a state that should not receive it
                        // (depending on how getAppStartModeLocked has determined that).
                        //如果应用程序在启动时被完全禁用,或者它没有被显式地发送给应用程序,
                        //并且应用程序处于不应该接收它的状态,我们将不允许启动这个接收器
                        if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                            Slog.w(TAG, "Background execution disabled: receiving "
                                    + r.intent + " to "
                                    + component.flattenToShortString());
                            skip = true;
                        } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
                                || (r.intent.getComponent() == null
                                    && r.intent.getPackage() == null
                                    && ((r.intent.getFlags()
                                            & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
                                    && !isSignaturePerm(r.requiredPermissions))) {
                            mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
                                    component.getPackageName());
                            Slog.w(TAG, "Background execution not allowed: receiving "
                                    + r.intent + " to "
                                    + component.flattenToShortString());
                            skip = true;
                        }
                    }
                }
    
                if (skip) {
                    if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                            "Skipping delivery of ordered [" + mQueueName + "] "
                            + r + " for whatever reason");
                    r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
                    r.receiver = null;
                    r.curFilter = null;
                    r.state = BroadcastRecord.IDLE;
                    scheduleBroadcastsLocked();
                    return;
                }
    
                r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
                r.state = BroadcastRecord.APP_RECEIVE;
                r.curComponent = component;
                r.curReceiver = info.activityInfo;
                if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
                    Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
                            + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
                            + info.activityInfo.applicationInfo.uid);
                }
    
                if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                    scheduleTempWhitelistLocked(receiverUid,
                            brOptions.getTemporaryAppWhitelistDuration(), r);
                }
    
                // Broadcast is being executed, its package can't be stopped.
                 //广播正在执行,它的包进程无法停止。
                try {
                    AppGlobals.getPackageManager().setPackageStoppedState(
                            r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
                } catch (RemoteException e) {
                } catch (IllegalArgumentException e) {
                    Slog.w(TAG, "Failed trying to unstop package "
                            + r.curComponent.getPackageName() + ": " + e);
                }
    
                // Is this receiver's application already running?
                if (app != null && app.thread != null && !app.killed) {//这个接收者进程已存在
                    try {
                        app.addPackage(info.activityInfo.packageName,
                                info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                        //发送广播到相应进程处理
                        processCurBroadcastLocked(r, app);
                        return;
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception when sending broadcast to "
                              + r.curComponent, e);
                    } catch (RuntimeException e) {
                        Slog.wtf(TAG, "Failed sending broadcast to "
                                + r.curComponent + " with " + r.intent, e);
                        // If some unexpected exception happened, just skip
                        // this broadcast.  At this point we are not in the call
                        // from a client, so throwing an exception out from here
                        // will crash the entire system instead of just whoever
                        // sent the broadcast.
                        logBroadcastReceiverDiscardLocked(r);
                        finishReceiverLocked(r, r.resultCode, r.resultData,
                                r.resultExtras, r.resultAbort, false);
                        scheduleBroadcastsLocked();
                        // We need to reset the state if we failed to start the receiver.
                        r.state = BroadcastRecord.IDLE;
                        return;
                    }
    
                    // If a dead object exception was thrown -- fall through to
                    // restart the application.
                }
    
                // Not running -- get it started, to be executed when the app comes up.
                //接收者进程未运行——启动它,在应用程序出现时执行广播发送。
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Need to start app ["
                        + mQueueName + "] " + targetProcess + " for broadcast " + r);
                if ((r.curApp=mService.startProcessLocked(targetProcess,
                        info.activityInfo.applicationInfo, true,
                        r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                        "broadcast", r.curComponent,
                        (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                                == null) {
                    // Ah, this recipient is unavailable.  Finish it if necessary,
                    // and mark the broadcast record as ready for the next.
                    Slog.w(TAG, "Unable to launch app "
                            + info.activityInfo.applicationInfo.packageName + "/"
                            + info.activityInfo.applicationInfo.uid + " for broadcast "
                            + r.intent + ": process is bad");
                    logBroadcastReceiverDiscardLocked(r);
                    finishReceiverLocked(r, r.resultCode, r.resultData,
                            r.resultExtras, r.resultAbort, false);
                    scheduleBroadcastsLocked();
                    r.state = BroadcastRecord.IDLE;
                    return;
                }
                //将 r赋值给mPendingBroadcast,待进程起来后触发发送
                mPendingBroadcast = r;
                mPendingBroadcastRecvIndex = recIdx;
            }
        }
    
        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);
                    // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
                    // DeadObjectException when the process isn't actually dead.
                    //} catch (DeadObjectException ex) {
                    // Failed to call into the process.  It's dying so just let it die and move on.
                    //    throw ex;
                    } 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;
                    }
                } else {
                    // Application has died. Receiver doesn't exist.
                    throw new RemoteException("app.thread must not be null");
                }
            } else {
                receiver.performReceive(intent, resultCode, data, extras, ordered,
                        sticky, sendingUser);
            }
        }
    }
    

    上面一大串的代码,总结起来就做了以下几件事情:
    1、广播分发花了很大的篇幅来处理权限、合法性等校验,主题流程其实并不复杂;
    2、广播分发分为动态广播分发和静态广播分发两部分;动态广播分发直接发送到对应进程,如果进程不存在则直接丢弃;静态广播分发也是分发到对应进程中,如果进程不存在则缓存广播,拉起进程后在发送。
    3、广播Intent发送到对应进程是通过IIntentReceiver或IApplicationThread接口来实现的;继续跟踪代码到应用进程,最终广播Intent都是会在ActivityThread中、继承Handler类的mH对象中处理,所以BroadcastReceiver的onReceive方法最终跑在主线程中。

    当广播Intent分发到应用进程后,经过了一系列的中转处理,但最终的广播接收者onReceive方法回调是在ActivityThread 类中实现的。

    public final class ActivityThread {
    
        //经过各种转发后最终执行Receiver的代码
        private void handleReceiver(ReceiverData data) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
    
            String component = data.intent.getComponent().getClassName();
    
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
    
            IActivityManager mgr = ActivityManager.getService();
    
            Application app;
            BroadcastReceiver receiver;
            ContextImpl context;
            try {
                app = packageInfo.makeApplication(false, mInstrumentation);
                context = (ContextImpl) app.getBaseContext();
                if (data.info.splitName != null) {
                    context = (ContextImpl) context.createContextForSplit(data.info.splitName);
                }
                java.lang.ClassLoader cl = context.getClassLoader();
                data.intent.setExtrasClassLoader(cl);
                data.intent.prepareToEnterProcess();
                data.setExtrasClassLoader(cl);
                receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
            } catch (Exception e) {
                if (DEBUG_BROADCAST) Slog.i(TAG,
                        "Finishing failed broadcast to " + data.intent.getComponent());
                data.sendFinished(mgr);
                throw new RuntimeException(
                    "Unable to instantiate receiver " + component
                    + ": " + e.toString(), e);
            }
    
            try {
                if (localLOGV) Slog.v(
                    TAG, "Performing receive of " + data.intent
                    + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + packageInfo.getPackageName()
                    + ", comp=" + data.intent.getComponent().toShortString()
                    + ", dir=" + packageInfo.getAppDir());
    
                sCurrentBroadcastIntent.set(data.intent);
                receiver.setPendingResult(data);
                receiver.onReceive(context.getReceiverRestrictedContext(),
                        data.intent);
            } catch (Exception e) {
                if (DEBUG_BROADCAST) Slog.i(TAG,
                        "Finishing failed broadcast to " + data.intent.getComponent());
                data.sendFinished(mgr);
                if (!mInstrumentation.onException(receiver, e)) {
                    throw new RuntimeException(
                        "Unable to start receiver " + component
                        + ": " + e.toString(), e);
                }
            } finally {
                sCurrentBroadcastIntent.set(null);
            }
    
            if (receiver.getPendingResult() != null) {
                data.finish();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:跨进程广播的工作原理(4)

          本文链接:https://www.haomeiwen.com/subject/aqarectx.html