说说Android的广播(6) - 广播消息的接收和派发
广播消息的接收过程
并发队列的处理
我们还是继续上一讲的讲法,先把干货提炼出来,然后再看完整的流程.
654 // First, deliver any non-serialized broadcasts right away.
655 while (mParallelBroadcasts.size() > 0) {
656 r = mParallelBroadcasts.remove(0);
657 r.dispatchTime = SystemClock.uptimeMillis();
658 r.dispatchClockTime = System.currentTimeMillis();
659 final int N = r.receivers.size();
...
662 for (int i=0; i<N; i++) {
663 Object target = r.receivers.get(i);
...
667 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
668 }
669 addBroadcastToHistoryLocked(r);
...
672 }
针对每个receiver,都调用deliverToRegisteredReceiverLocked方法去处理,没有返回值,没有等待。
最后加入到广播历史中,结束,就这么简单.
有序广播处理结束,返回结果的处理
754
755 if (r.receivers == null || r.nextReceiver >= numReceivers
756 || r.resultAbort || forceReceive) {
757 // No more receivers for this broadcast! Send the final
758 // result if requested...
759 if (r.resultTo != null) {
760 try {
...
既然结束了,就可以调用performReceiveLocked返回最终的结果给调用者了。
764 performReceiveLocked(r.callerApp, r.resultTo,
765 new Intent(r.intent), r.resultCode,
766 r.resultData, r.resultExtras, false, false, r.userId);
767 // Set this to null so that the reference
768 // (local and remote) isn't kept in the mBroadcastHistory.
769 r.resultTo = null;
770 } catch (RemoteException e) {
771 r.resultTo = null;
772 Slog.w(TAG, "Failure ["
773 + mQueueName + "] sending broadcast result of "
774 + r.intent, e);
775 }
776 }
...
结束了,清理timer吧:
779 cancelBroadcastTimeoutLocked();
...
下面记录一下历史,把当前组件从队列中去掉,进行下一次循环。
784 // ... and on to the next...
785 addBroadcastToHistoryLocked(r);
786 mOrderedBroadcasts.remove(0);
787 r = null;
788 looped = true;
789 continue;
790 }
791 } while (r == null);
BroadcastHandler
前面我们分析过了,发送广播时,不管是有序的还是无序的,都会是发送一个BROADCAST_INTENT_MSG的消息出来。
下面我们看看Handler中是如何处理的:
157 private final class BroadcastHandler extends Handler {
158 public BroadcastHandler(Looper looper) {
159 super(looper, null, true);
160 }
161
162 @Override
163 public void handleMessage(Message msg) {
164 switch (msg.what) {
165 case BROADCAST_INTENT_MSG: {
166 if (DEBUG_BROADCAST) Slog.v(
167 TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
168 processNextBroadcast(true);
169 } break;
170 case BROADCAST_TIMEOUT_MSG: {
171 synchronized (mService) {
172 broadcastTimeoutLocked(true);
173 }
174 } break;
175 case SCHEDULE_TEMP_WHITELIST_MSG: {
176 DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
177 if (dic != null) {
178 dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
179 msg.arg2, true, (String)msg.obj);
180 }
181 } break;
182 }
183 }
184 };
如上面所看到的,BROADCAST_INTENT_MSG会去调用processNextBroadcast方法。
processNextBroadcast
processNextBroadcast是整个逻辑的核心。
639 final void processNextBroadcast(boolean fromMsg) {
640 synchronized(mService) {
641 BroadcastRecord r;
642
...
647
648 mService.updateCpuStats();
649
650 if (fromMsg) {
651 mBroadcastsScheduled = false;
652 }
第一步是处理动态注册的广播,这个前面我们已经分析过了。
653
654 // First, deliver any non-serialized broadcasts right away.
655 while (mParallelBroadcasts.size() > 0) {
656 r = mParallelBroadcasts.remove(0);
657 r.dispatchTime = SystemClock.uptimeMillis();
658 r.dispatchClockTime = System.currentTimeMillis();
659 final int N = r.receivers.size();
660 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
661 + mQueueName + "] " + r);
662 for (int i=0; i<N; i++) {
663 Object target = r.receivers.get(i);
664 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
665 "Delivering non-ordered on [" + mQueueName + "] to registered "
666 + target + ": " + r);
667 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
668 }
669 addBroadcastToHistoryLocked(r);
670 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
671 + mQueueName + "] " + r);
672 }
第二步,开始处理有序广播,当然,如前面我们反复所讲的,非动态注册的也是按有序广播处理的。
674 // Now take care of the next serialized one...
675
676 // If we are waiting for a process to come up to handle the next
677 // broadcast, then do nothing at this point. Just in case, we
678 // check that the process we're waiting for still exists.
679 if (mPendingBroadcast != null) {
680 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
681 "processNextBroadcast [" + mQueueName + "]: waiting for "
682 + mPendingBroadcast.curApp);
683
684 boolean isDead;
685 synchronized (mService.mPidsSelfLocked) {
686 ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
687 isDead = proc == null || proc.crashing;
688 }
689 if (!isDead) {
690 // It's still alive, so keep waiting
691 return;
692 } else {
693 Slog.w(TAG, "pending app ["
694 + mQueueName + "]" + mPendingBroadcast.curApp
695 + " died before responding to broadcast");
696 mPendingBroadcast.state = BroadcastRecord.IDLE;
697 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
698 mPendingBroadcast = null;
699 }
700 }
701
前面处理一些异常情况,下面开始第三步,先处理下有序队列为空的性况。
如果是最后一条,就调整一下OOM Adj之类的,为系统做点贡献。
702 boolean looped = false;
703
704 do {
705 if (mOrderedBroadcasts.size() == 0) {
706 // No more broadcasts pending, so all done!
707 mService.scheduleAppGcsLocked();
708 if (looped) {
709 // If we had finished the last ordered broadcast, then
710 // make sure all processes have correct oom and sched
711 // adjustments.
712 mService.updateOomAdjLocked();
713 }
714 return;
715 }
如果不为空,我们就take一个记录,开始干活。先处理超时的情况,如果超时的话,就调用broadcastTimeoutLocked来结束广播。
716 r = mOrderedBroadcasts.get(0);
717 boolean forceReceive = false;
718
719 // Ensure that even if something goes awry with the timeout
720 // detection, we catch "hung" broadcasts here, discard them,
721 // and continue to make progress.
722 //
723 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
724 // receivers don't get executed with timeouts. They're intended for
725 // one time heavy lifting after system upgrades and can take
726 // significant amounts of time.
727 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
728 if (mService.mProcessesReady && r.dispatchTime > 0) {
729 long now = SystemClock.uptimeMillis();
730 if ((numReceivers > 0) &&
731 (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
732 Slog.w(TAG, "Hung broadcast ["
733 + mQueueName + "] discarded after timeout failure:"
734 + " now=" + now
735 + " dispatchTime=" + r.dispatchTime
736 + " startTime=" + r.receiverTime
737 + " intent=" + r.intent
738 + " numReceivers=" + numReceivers
739 + " nextReceiver=" + r.nextReceiver
740 + " state=" + r.state);
741 broadcastTimeoutLocked(false); // forcibly finish this broadcast
742 forceReceive = true;
743 r.state = BroadcastRecord.IDLE;
744 }
745 }
如果拿到的这个广播记录已经是在非空闲状态了,那就let it be.
746
747 if (r.state != BroadcastRecord.IDLE) {
748 if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
749 "processNextBroadcast("
750 + mQueueName + ") called when not idle (state="
751 + r.state + ")");
752 return;
753 }
如果已经是最后一个接收者了,说明一切该结束了,那么就调用performReceiveLocked返回值吧。有序广播是要求返回结果的。
755 if (r.receivers == null || r.nextReceiver >= numReceivers
756 || r.resultAbort || forceReceive) {
757 // No more receivers for this broadcast! Send the final
758 // result if requested...
759 if (r.resultTo != null) {
760 try {
...
764 performReceiveLocked(r.callerApp, r.resultTo,
765 new Intent(r.intent), r.resultCode,
766 r.resultData, r.resultExtras, false, false, r.userId);
767 // Set this to null so that the reference
768 // (local and remote) isn't kept in the mBroadcastHistory.
769 r.resultTo = null;
770 } catch (RemoteException e) {
771 r.resultTo = null;
772 Slog.w(TAG, "Failure ["
773 + mQueueName + "] sending broadcast result of "
774 + r.intent, e);
775 }
776 }
777
既然处理完了,超时就可以停掉了。
779 cancelBroadcastTimeoutLocked();
记录历史,进行下一个。
784 // ... and on to the next...
785 addBroadcastToHistoryLocked(r);
786 mOrderedBroadcasts.remove(0);
787 r = null;
788 looped = true;
789 continue;
790 }
791 } while (r == null);
处理下一个receiver:
793 // Get the next receiver...
794 int recIdx = r.nextReceiver++;
795
796 // Keep track of when this receiver started, and make sure there
797 // is a timeout message pending to kill it if need be.
798 r.receiverTime = SystemClock.uptimeMillis();
799 if (recIdx == 0) {
800 r.dispatchTime = r.receiverTime;
801 r.dispatchClockTime = System.currentTimeMillis();
...
如果有mPendingBroadcastTimeoutMessage的欠债,就赶快还了吧。
805 if (! mPendingBroadcastTimeoutMessage) {
806 long timeoutTime = r.receiverTime + mTimeoutPeriod;
807 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
808 "Submitting BROADCAST_TIMEOUT_MSG ["
809 + mQueueName + "] for " + r + " at " + timeoutTime);
810 setBroadcastTimeoutLocked(timeoutTime);
811 }
812
813 final BroadcastOptions brOptions = r.options;
814 final Object nextReceiver = r.receivers.get(recIdx);
815
816 if (nextReceiver instanceof BroadcastFilter) {
817 // Simple case: this is a registered receiver who gets
818 // a direct call.
819 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
核心逻辑是下面调用的deliverToRegisteredReceiverLocked。
824 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
825 if (r.receiver == null || !r.ordered) {
826 // The receiver has already finished, so schedule to
827 // process the next one.
...
831 r.state = BroadcastRecord.IDLE;
832 scheduleBroadcastsLocked();
833 } else {
834 if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
835 scheduleTempWhitelistLocked(filter.owningUid,
836 brOptions.getTemporaryAppWhitelistDuration(), r);
837 }
838 }
839 return;
840 }
下面开始进入Hard case,就是该启动新的进程了去接收消息了。
842 // Hard case: need to instantiate the receiver, possibly
843 // starting its application process to host it.
844
845 ResolveInfo info =
846 (ResolveInfo)nextReceiver;
847 ComponentName component = new ComponentName(
848 info.activityInfo.applicationInfo.packageName,
849 info.activityInfo.name);
850
851 boolean skip = false;
...
中间有大段的权限相关的处理,我们暂时不关注。
944 boolean isSingleton = false;
945 try {
946 isSingleton = mService.isSingleton(info.activityInfo.processName,
947 info.activityInfo.applicationInfo,
948 info.activityInfo.name, info.activityInfo.flags);
949 } catch (SecurityException e) {
950 Slog.w(TAG, e.getMessage());
951 skip = true;
952 }
953 if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
954 if (ActivityManager.checkUidPermission(
955 android.Manifest.permission.INTERACT_ACROSS_USERS,
956 info.activityInfo.applicationInfo.uid)
957 != PackageManager.PERMISSION_GRANTED) {
958 Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
959 + " requests FLAG_SINGLE_USER, but app does not hold "
960 + android.Manifest.permission.INTERACT_ACROSS_USERS);
961 skip = true;
962 }
963 }
964 if (r.curApp != null && r.curApp.crashing) {
965 // If the target process is crashing, just skip it.
966 Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
967 + " to " + r.curApp + ": process crashing");
968 skip = true;
969 }
970 if (!skip) {
971 boolean isAvailable = false;
972 try {
973 isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
974 info.activityInfo.packageName,
975 UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
976 } catch (Exception e) {
977 // all such failures mean we skip this receiver
978 Slog.w(TAG, "Exception getting recipient info for "
979 + info.activityInfo.packageName, e);
980 }
981 if (!isAvailable) {
982 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
983 "Skipping delivery to " + info.activityInfo.packageName + " / "
984 + info.activityInfo.applicationInfo.uid
985 + " : package no longer available");
986 skip = true;
987 }
988 }
989
990 if (skip) {
991 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
992 "Skipping delivery of ordered [" + mQueueName + "] "
993 + r + " for whatever reason");
994 r.receiver = null;
995 r.curFilter = null;
996 r.state = BroadcastRecord.IDLE;
997 scheduleBroadcastsLocked();
998 return;
999 }
1000
1001 r.state = BroadcastRecord.APP_RECEIVE;
1002 String targetProcess = info.activityInfo.processName;
1003 r.curComponent = component;
1004 final int receiverUid = info.activityInfo.applicationInfo.uid;
1005 // If it's a singleton, it needs to be the same app or a special app
1006 if (r.callingUid != Process.SYSTEM_UID && isSingleton
1007 && mService.isValidSingletonCall(r.callingUid, receiverUid)) {
1008 info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
1009 }
1010 r.curReceiver = info.activityInfo;
1011 if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
1012 Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
1013 + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
1014 + info.activityInfo.applicationInfo.uid);
1015 }
1016
1017 if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
1018 scheduleTempWhitelistLocked(receiverUid,
1019 brOptions.getTemporaryAppWhitelistDuration(), r);
1020 }
1021
1022 // Broadcast is being executed, its package can't be stopped.
1023 try {
1024 AppGlobals.getPackageManager().setPackageStoppedState(
1025 r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
1026 } catch (RemoteException e) {
1027 } catch (IllegalArgumentException e) {
1028 Slog.w(TAG, "Failed trying to unstop package "
1029 + r.curComponent.getPackageName() + ": " + e);
1030 }
这里后面调用核心逻辑processCurBroadcastLocked。
1032 // Is this receiver's application already running?
1033 ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
1034 info.activityInfo.applicationInfo.uid, false);
1035 if (app != null && app.thread != null) {
1036 try {
1037 app.addPackage(info.activityInfo.packageName,
1038 info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
1039 processCurBroadcastLocked(r, app);
1040 return;
1041 } catch (RemoteException e) {
1042 Slog.w(TAG, "Exception when sending broadcast to "
1043 + r.curComponent, e);
1044 } catch (RuntimeException e) {
1045 Slog.wtf(TAG, "Failed sending broadcast to "
1046 + r.curComponent + " with " + r.intent, e);
1047 // If some unexpected exception happened, just skip
1048 // this broadcast. At this point we are not in the call
1049 // from a client, so throwing an exception out from here
1050 // will crash the entire system instead of just whoever
1051 // sent the broadcast.
1052 logBroadcastReceiverDiscardLocked(r);
1053 finishReceiverLocked(r, r.resultCode, r.resultData,
1054 r.resultExtras, r.resultAbort, false);
1055 scheduleBroadcastsLocked();
1056 // We need to reset the state if we failed to start the receiver.
1057 r.state = BroadcastRecord.IDLE;
1058 return;
1059 }
1060
1061 // If a dead object exception was thrown -- fall through to
1062 // restart the application.
1063 }
下面开始重头戏,如果进程没启动,调用startProcessLocked去启动进程。
1065 // Not running -- get it started, to be executed when the app comes up.
1066 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
1067 "Need to start app ["
1068 + mQueueName + "] " + targetProcess + " for broadcast " + r);
1069 if ((r.curApp=mService.startProcessLocked(targetProcess,
1070 info.activityInfo.applicationInfo, true,
1071 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
1072 "broadcast", r.curComponent,
1073 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
1074 == null) {
1075 // Ah, this recipient is unavailable. Finish it if necessary,
1076 // and mark the broadcast record as ready for the next.
1077 Slog.w(TAG, "Unable to launch app "
1078 + info.activityInfo.applicationInfo.packageName + "/"
1079 + info.activityInfo.applicationInfo.uid + " for broadcast "
1080 + r.intent + ": process is bad");
1081 logBroadcastReceiverDiscardLocked(r);
1082 finishReceiverLocked(r, r.resultCode, r.resultData,
1083 r.resultExtras, r.resultAbort, false);
1084 scheduleBroadcastsLocked();
1085 r.state = BroadcastRecord.IDLE;
1086 return;
1087 }
1088
1089 mPendingBroadcast = r;
1090 mPendingBroadcastRecvIndex = recIdx;
1091 }
1092 }