Android_动态广播源码分析

追一追动态广播的源码
          恩恩。今天我们追一追动态广播的源码,看看我们平时使用的动态广播是怎样实现的:(现在网上资料一大堆,其他内容就不多赘述,主要从源码层面来分析);

动态广播的注册:

【注册广播的一方为接受广播的一方】

registerReceiver( receiver,filter);

一般情况下动态广播需要在代码里面注册,而注册的代码就是上面的一行,这段代码执行完后,我们就认为动态广播就注册好了。那么它具体是怎么完成注册功能的呢?我们接下来继续看,现在转到ContextImpl类中:

frameworks/base/core/java/android/app/ContextImpl.java

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

         registerReceiver并没有做什么事,调用了registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
        String broadcastPermission, Handler scheduler, int flags)方法 ,增加了两参数,接下来:

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
        String broadcastPermission, Handler scheduler, int flags) {
    return registerReceiverInternal(receiver, getUserId(),
            filter, broadcastPermission, scheduler, getOuterContext(), flags);

如上代码所示:registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags)方法调用了registerReceiverInternal()方法,看看registerReceicerInternal()方法里面主要做了什么:

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    IIntentReceiver rd = null;
    if (receiver != null) {
            ...
            rd = mPackageInfo.getReceiverDispatcher(
                receiver, context, scheduler,
                mMainThread.getInstrumentation(), true);
        } else {
            ...
            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();
    }
}

registerReceicerInternal()方法主要是做了两件事:

  1.  rd = mPackageInfo.getReceiverDispatcher(  receiver, context, ...);

我们先看看这个rd,rd也是binder的对象,可以跨进程传递的,那看看getReceiverDispatcher具体是怎么样的获取rd的,


public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,...) {
    synchronized (mReceivers) {
        LoadedApk.ReceiverDispatcher rd = null;
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
        if (registered) {
            map = mReceivers.get(context);
            ...
        }
        ...
        rd = new ReceiverDispatcher(r, context, handler,...);
        ...
        if (map == null) {
        ...
        map.put(r, rd);
        ...
        return rd.getIIntentReceiver();
    }
}

这个mReceivers是在这定义的

private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<>();

mReceivers是一个map,这个map的key为context.value为另一个map,这个map的key为BroadCaseReceiver,value 为ReceiverDispather;这样我们看getReceiverDispatcher()一开始就是为BroadCastReceiver new 了一个ReceiverDispatcher对象rd.然后将rd push到mReceiver中.返回IIntentReceiver.那接下来我们看看getIIntentReceiver()是从哪里取得的IIntentReceiver

ReceiverDispatcher(BroadcastReceiver receiver, Context context,...) {
    ...
    mIIntentReceiver = new InnerReceiver(this, !registered);
    mReceiver = receiver;
    ...
}

在ReceiverDispatcher中生成InnerReceiverd对象mIntentReceiver,而InnerReceiver继承IIntentReceiver.Stub,就是个binder对象.

final static class InnerReceiver extends IIntentReceiver.Stub {
    final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
    ...
    InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
        mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
        ...
    }

在InnerReceiver中持有ReceiverDispatcher的弱引用.

   2 . final Intent intent = ActivityManager.getService().registerReceiver(  ..., rd, ....);

这里先获得AMS的代理对象,然后调用其registerReceiver()方法进行注册;接下来就跳转到AMS中,来看看AMS中广播是怎么注册的:

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver...) {
    ...
    ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
    if (rl == null) {
        rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                userId, receiver);
        ...
        rl.app.receivers.add(rl);
        ...
        mRegisteredReceivers.put(receiver.asBinder(), rl);
    }
    ...
    BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
        permission, callingUid, userId, instantApp, visibleToInstantApps); 
    ...
    mReceiverResolver.addFilter(bf);
    ...
}

我们来看这个AMS里面的执行情况, 从mRegisteredReceivers中取得ReceiverList,这个mRegidsteredReceivers是一个Map,其key是Ibinder(就是我们传过来的IIntentReceiver),value是一个ReceiverList(相当于一个FilterList,就是List<BroadcastFilter>,BroadcastFilter继承IntentFilter).

下面的mReceiverResolver是用于向注册接收器广播意图的解析器。持有BroadcastFilter(intentFilter的子类),用来解析intent.

广播的发送(一般广播)

@Override
public void sendBroadcast(Intent intent) {
    ...
    try {
        ...
        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();
    }
}

一般广播的发送如上代码所示,在sendBroadcast()方法中首先获取AMS的代理对象,然后调用其broadcastIntent()方法。接下来就转到AMS中看看broadcastIntent()主要干了些什么:

public final int broadcastIntent(...) {
        ....
    int res = broadcastIntentLocked(...);
    ...
    return res;

}
...
final int broadcastIntentLocked(...) {
    intent = new Intent(intent;
    ...
    // 通过intent找到匹配的Receiver列表
    registeredReceivers = mReceiverResolver.queryIntent(intent,...);
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    if (!ordered && NR > 0) {
    // 如果我们不是有序广播,则分别发送已注册的接收器,这样它们就不会等待组件启动。
    final BroadcastQueue queue = broadcastQueueForIntent(intent);
    // BroadcastRecord 里面包含receiver列表,
    BroadcastRecord r = new BroadcastRecord(queue, intent, );
    ...
    // 接着将BroadcastRecord添加到BroadcastQueue中
    queue.enqueueParallelBroadcastLocked(r); //并行分发列表 
    queue.scheduleBroadcastsLocked(); // 准备分发广播
    ...
}

然后进入具体的分发过程:

final void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            processNextBroadcastLocked(fromMsg, false);
    }
}

final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
    BroadcastRecord r;
    // First, deliver any non-serialized broadcasts right away.
    while (mParallelBroadcasts.size() > 0) {
        r = mParallelBroadcasts.remove(0);
        ...
        final int N = r.receivers.size();
        for (int i=0; i<N; i++) {
            Object target = r.receivers.get(i);
            deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
        }
        ...
    }
}

普通共同广播是并行分发的,首先遍历mParallelBroadcasts列表,依次拿把BroadcastRecord拿出,然后再遍历receiver列表。依次取出receiver列表里面的Receiver。然后通过deliverToRegisteredReceiverLocked()将广播发给Receiver。

广播的接收

void performReceiveLocked(ProcessRecord app...) throws RemoteException {
    if (app != null) {
        ...
        app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
    } else {
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}

广播的接收首先判断ProcessRecord是不是空,如果是不为空,则调用app.thread.schedulRegisteredReceiver();这里的thread就是应用向AMS注册的代理对象,所以这里会调用应用的schedulRegisteredReceiver()方法:

// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver...) throws RemoteException {
    receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
            sticky, sendingUser);
}

看注释可以看到:此函数存在以确保所有接收方调度正确地排序,因为这些是单向调用,并且绑定器驱动程序为每个调用应用每个对象的事务排序。所以从AMS发送的广播都将串行排序分发。

接下来看看:


public void performReceive(Intent intent, int resultCode...) {
    final LoadedApk.ReceiverDispatcher rd;
    ...
    rd = mDispatcher.get();
    rd.performReceive(intent, resultCode, data, extras,
                ordered, sticky, sendingUser);
    ...
}
...
public void performReceive(Intent intent, int resultCode,...) {
    final Args args = new Args(intent, resultCode,..);
    ....
    // post到主线程去处理
    if (intent == null || !mActivityThread.post(args.getRunnable())) {
        ...
        }
    }
}

performReceiver()方法中先获取到ReceiverDispatcher对象,然后调用它的performReceiver()方法。接下来先new一个Args对象,然后post到ActivityThread中交给主线程去处理, 我们在使用onReceiver时也是在主线程能调用的,

接着我们看看Args 的getRunnable()方法:


public final Runnable getRunnable() {
    return () -> {
        final BroadcastReceiver receiver = mReceiver;
        final boolean ordered = mOrdered;
        ...
        receiver.setPendingResult(this);
        receiver.onReceive(mContext, intent);
        ...
        if (receiver.getPendingResult() != null) {
            finish();
        }
        ...
    }
}

上述代码的主要操做就是先获取BroadcastReceiver对象 receiver,然后调用它的onReceiver()方法,接着调用finish()方法;finish()方法主要作用就是通知AMS当前广播分发完了[对于一些串行分发的广播,就需要上一个广播执行完才能进行下一个广播执行]

/**
 * BROADCASTS
 *
 * We keep two broadcast queues and associated bookkeeping, one for those at
 * foreground priority, and one for normal (background-priority) broadcasts.
 */

我们保留两个广播队列和相关的记录,一个用于前台优先级广播,另一个用于正常(后台优先级)广播

普通广播动态广播在系统端是并行分发,应用端是串行分发

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值