ANR源码分析之Broadcast Timeout

 在上篇文章中,介绍了InputDispatcher Timeout的流程。本篇文章将介绍Broadcast Timeout的流程。 我们知道广播根据注册的方式的可以分为静态注册广播和动态注册广播,根据发送方式可以分为普通广播、有序广播、Sticky广播以及APP内广播。广播执行的方式有两种,一种是串行执行,另外一种是并发执行。并发执行的广播是不存在超时的情况,例如动态注册的非有序的广播。而串行执行的广播是有超时时间的,前台广播是10s,后台广播是60s。可以通过设置Intent.FLAG_RECEIVER_FOREGROUND标志位,将广播设置为前台广播,默认情况下,广播都是后台广播。静态注册的和有序的广播都是串行执行的。

 Broadcast Timeout的整体流程如下图所示:



1.sendBroadcast方法(ContextImpl.java)
 广播的发送是通过context.sendBroadcast()方法来实现的,Context类是一个抽象的类,具体的由ContextImpl类来实现。
 framework/core/java/android/app/ContextImpl.java

 /*
    * 发送广播
    */
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManagerNative.getDefault().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();
        }
    }
2.broadcastIntent方法(ActivityManagerService.java)
   frameworks/base/core/java/com/android/server/am/ActivityManagerService.java
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是否有效
            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;
        }
    }

 在broadcastIntent方法中有两个布尔值参数serialized和sticky来共同决定是普通广播,有序广播还是sticky广播,参数如下:

类型 serialized sticky
sendBroadcast false false
sendOrderedBroadcast true false
sendStickyBroadcast false true


3.broadcastIntentLocked方法(ActivityManagerService.java)
 final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
        intent = new Intent(intent);
       // 增加该标志,则广播不会发送到已停止的package
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);


        // 当没有启动完成,不允许启动新的进程
        if (!mProcesse
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值