欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android AOSP 6.0.1 registerReceiver广播注册流程分析

程序员文章站 2022-05-14 17:36:09
...

广播作为 Android 开发的四大组间之一,当我们发送广播以后,发生了什么?广播接收者最终如何收到了广播。

一、复盘广播的使用

在 Android 开发中使用广播分为三个步骤:

1.新建广播接收者 BroadcastReceiver;

2.注册广播接收者,分为静态和动态注册两种方式;

3.其他组间通过 sendBroadcast 向 BroadcastReceiver 发送广播,然后接收者处理。

我在分析流程中使用了动态注册的方式。在 Activity onResume 中注册,onPause 中取消注册。以下是创建 BroadcastReceiver 的代码。

class MainActivity : AppCompatActivity() {
    ......
    inner class MainActivityBroadcastReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (null != intent && intent.action == ACTION) {
                val str = intent.getStringExtra(VALUE_KEY)
                Log.d(TAG, "MainActivityBroadcastReceiver onReceive str=$str")
            }
        }

    }
    ......
}

接着在 Service 中调用 sendBroadcast。

二、广播接收者注册

广播接收者注册调用了 registerReceiver 方法。

class MainActivity : AppCompatActivity() {
    
    companion object {
        const val TAG = "MainActivity"
        const val ACTION = "com.demo.framework.ACTION"
        const val VALUE_KEY = "value_key"
    }

    private var mMainActivityBroadcastReceiver: MainActivityBroadcastReceiver = MainActivityBroadcastReceiver()
    ......
    override fun onResume() {
        super.onResume()
        val intentFilter = IntentFilter(ACTION)
        registerReceiver(mMainActivityBroadcastReceiver, intentFilter)
    }

    override fun onPause() {
        super.onPause()
        unregisterReceiver(mMainActivityBroadcastReceiver)
    }
    ......
}

registerReceiver 方法来自 ContextWrapper 类,回顾 Android AOSP 6.0.1 startService启动流程分析 一节可知,最终调用了 ContextImpl 类中的 registerReceiver 方法。registerReceiver 方法最后调用了 registerReceiverInternal 方法。

frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {
    ......
    @Override
    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }
    ......
}

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

class ContextImpl extends Context {
    ......
    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }

    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext());
    }
    ......
    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context) {
        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 {
            return ActivityManagerNative.getDefault().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName,
                    rd, filter, broadcastPermission, userId);
        } catch (RemoteException e) {
            return null;
        }
    }    
}

熟悉的流程,在 registerReceiverInternal 方法中先获取 ActivityManagerProxy,然后调用它的 registerReceiver 方法。在 registerReceiverInternal 函数中主要用来构建 rd 局部变量,它是 IIntentReceiver 类型。rd 对象是经过 mPackageInfo 调用它的 getReceiverDispatcher 方法获取的。mPackageInfo 是一个 LoadedApk 类型。

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

public final class LoadedApk {
    ......
    public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
            Context context, Handler handler,
            Instrumentation instrumentation, boolean registered) {
        synchronized (mReceivers) {
            LoadedApk.ReceiverDispatcher rd = null;
            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
            if (registered) {
                map = mReceivers.get(context);
                if (map != null) {
                    rd = map.get(r);
                }
            }
            if (rd == null) {
                rd = new ReceiverDispatcher(r, context, handler,
                        instrumentation, registered);
                if (registered) {
                    if (map == null) {
                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                        mReceivers.put(context, map);
                    }
                    map.put(r, rd);
                }
            } else {
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            return rd.getIIntentReceiver();
        }
    }
    ......
}

以上一段代码并不难理解,mReceivers 是 ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> 类型的对象,它是以 Context 作为 key, ArrayMap<BroadcastReceiver, ReceiverDispatcher> 作为值的。这个 Context 其实就是对应的 Activity,而值是 BroadcastReceiver-ReceiverDispatcher 组成的键值对。同一个 Activity 里可以创建很多个 BroadcastReceiver,每个 BroadcastReceiver 都会对应一个 ReceiverDispatcher。没有注册过的 BroadcastReceiver,rd == null 分支会为 true,然后 new 一个 ReceiverDispatcher 对象。最后把键值对添加到 mReceivers 中。

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

public final class LoadedApk {
    ......
    static final class ReceiverDispatcher {

        final static class InnerReceiver extends IIntentReceiver.Stub {
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }
            ......
        }
        ......
        final IIntentReceiver.Stub mIIntentReceiver;
        final BroadcastReceiver mReceiver;
        final Context mContext;
        final Handler mActivityThread;
        final Instrumentation mInstrumentation;
        final boolean mRegistered;
        final IntentReceiverLeaked mLocation;
        RuntimeException mUnregisterLocation;
        boolean mForgotten;
        ......
        ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                Handler activityThread, Instrumentation instrumentation,
                boolean registered) {
            if (activityThread == null) {
                throw new NullPointerException("Handler must not be null");
            }

            mIIntentReceiver = new InnerReceiver(this, !registered);
            mReceiver = receiver;
            mContext = context;
            mActivityThread = activityThread;
            mInstrumentation = instrumentation;
            mRegistered = registered;
            mLocation = new IntentReceiverLeaked(null);
            mLocation.fillInStackTrace();
        }
        ......
        IIntentReceiver getIIntentReceiver() {
            return mIIntentReceiver;
        }
        ......
    }
    ......
}

最终要返回的 ReceiverDispatcher 对象,其中 mIIntentReceiver Field 是一个 InnerReceiver 类型,它的构造函数只是简单的为其 Field 赋值, mDispatcher 是一个弱引用对象。这里 mStrongRef 为 null。现在继续前面的思路,拿到 ActivityManagerProxy 对象,调用其 registerReceiver 方法。

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

class ActivityManagerProxy implements IActivityManager
{
    ......
    public Intent registerReceiver(IApplicationThread caller, String packageName,
            IIntentReceiver receiver,
            IntentFilter filter, String perm, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(packageName);
        data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
        filter.writeToParcel(data, 0);
        data.writeString(perm);
        data.writeInt(userId);
        mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
        reply.readException();
        Intent intent = null;
        int haveIntent = reply.readInt();
        if (haveIntent != 0) {
            intent = Intent.CREATOR.createFromParcel(reply);
        }
        reply.recycle();
        data.recycle();
        return intent;
    }
    ......
}

通过 Binder 机制实际远程调用了 ActivityManagerService 中的同名 registerReceiver 方法。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    // 跟踪已注册用于广播的所有 IIntentReceiver。 哈希键是接收者 IBinder,哈希值是 ReceiverList。
    final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();    
    ......
    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
        enforceNotIsolatedCaller("registerReceiver");
        ArrayList<Intent> stickyIntents = null;
        ProcessRecord callerApp = null;
        int callingUid;
        int callingPid;
        synchronized(this) {
            if (caller != null) {
                callerApp = getRecordForAppLocked(caller);
                ......
                // 给调用者 uid 和 pid 赋值
                callingUid = callerApp.info.uid;
                callingPid = callerApp.pid;
            } else {
                ......
            }

            userId = handleIncomingUser(callingPid, callingUid, userId,
                    true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
            // 获取 IntentFilter 中 action 迭代器
            Iterator<String> actions = filter.actionsIterator();
            if (actions == null) {
                ArrayList<String> noAction = new ArrayList<String>(1);
                noAction.add(null);
                actions = noAction.iterator();
            }

            ......
        }

       ......

        synchronized (this) {
            if (callerApp != null && (callerApp.thread == null
                    || callerApp.thread.asBinder() != caller.asBinder())) {
                // Original caller already died
                return null;
            }
            // 1.获取 ReceiverList 对象
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    // 2.添加 ReceiverList 对象到 ProcessRecord 对象的 receivers field
                    rl.app.receivers.add(rl);
                } else {
                    try {
                        receiver.asBinder().linkToDeath(rl, 0);
                    } catch (RemoteException e) {
                        return sticky;
                    }
                    rl.linkedToDeath = true;
                }
                // 3.添加 ReceiverList 对象到 mRegisteredReceivers
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            } else if (rl.uid != callingUid) {
                throw new IllegalArgumentException(
                        "Receiver requested to register for uid " + callingUid
                        + " was previously registered for uid " + rl.uid);
            } else if (rl.pid != callingPid) {
                throw new IllegalArgumentException(
                        "Receiver requested to register for pid " + callingPid
                        + " was previously registered for pid " + rl.pid);
            } else if (rl.userId != userId) {
                throw new IllegalArgumentException(
                        "Receiver requested to register for user " + userId
                        + " was previously registered for user " + rl.userId);
            }
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId);
            // 4.ReceiverList 添加对应的 BroadcastFilter 
            rl.add(bf);
            if (!bf.debugCheck()) {
                Slog.w(TAG, "==> For Dynamic broadcast");
            }
            // 5.添加 BroadcastFilter 对象到 mReceiverResolver
            mReceiverResolver.addFilter(bf);

            ......
        }
    }
    ......
}

1.获取 ReceiverList 对象

mRegisteredReceivers 是一个 HashMap<IBinder, ReceiverList>,现从这个 HashMap 中查找对应的 ReceiverList 是否存在,如果不存在就 new 一个 ReceiverList 对象。

frameworks/base/services/core/java/com/android/server/am/ReceiverList.java

/**
* 已注册一个或多个广播的接收器对象。 ArrayList 包含 BroadcastFilter 对象。
*/
final class ReceiverList extends ArrayList<BroadcastFilter>
        implements IBinder.DeathRecipient {
    final ActivityManagerService owner;
    public final IIntentReceiver receiver;
    public final ProcessRecord app;
    public final int pid;
    public final int uid;
    public final int userId;
    BroadcastRecord curBroadcast = null;
    boolean linkedToDeath = false;

    String stringName;
    
    ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
            int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
        owner = _owner;
        receiver = _receiver;
        app = _app;
        pid = _pid;
        uid = _uid;
        userId = _userId;
    }
    ......
}

2.添加 ReceiverList 对象到 ProcessRecord 对象的 receivers,实际上是一个 ArraySet 对象。

frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java

final class ProcessRecord {
    ......
    // 该进程注册的所有 IIntentReceivers。
    final ArraySet<ReceiverList> receivers = new ArraySet<>();
    ......
}

3.添加新创建的 ReceiverList 对象到 mRegisteredReceivers。

4.ReceiverList 添加对应的 BroadcastFilter。

frameworks/base/services/core/java/com/android/server/am/BroadcastFilter.java

final class BroadcastFilter extends IntentFilter {
    // 该过滤器所在列表的后向指针。
    final ReceiverList receiverList;
    final String packageName;
    final String requiredPermission;
    final int owningUid;
    final int owningUserId;

    BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
            String _packageName, String _requiredPermission, int _owningUid, int _userId) {
        super(_filter);
        receiverList = _receiverList;
        packageName = _packageName;
        requiredPermission = _requiredPermission;
        owningUid = _owningUid;
        owningUserId = _userId;
    }
    ......
}

5.添加 BroadcastFilter 对象到 mReceiverResolver,mReceiverResolver 是 IntentResolver<BroadcastFilter, BroadcastFilter> 类型,它实现了 IntentResolver 抽象类。 其 addFilter 方法调用 mFilters 的 add 方法将 BroadcastFilter 添加到 ArraySet,这个 Set 代表所有已注册的过滤器。然后调用 register_intent_filter 和 register_mime_types 方法将 BroadcastFilter “分解”添加到各个容器中。

frameworks/base/services/core/java/com/android/server/IntentResolver.java

public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
    final private static String TAG = "IntentResolver";
    final private static boolean DEBUG = false;
    final private static boolean localLOGV = DEBUG || false;
    final private static boolean localVerificationLOGV = DEBUG || false;

    public void addFilter(F f) {
        if (localLOGV) {
            Slog.v(TAG, "Adding filter: " + f);
            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
            Slog.v(TAG, "    Building Lookup Maps:");
        }

        mFilters.add(f);
        int numS = register_intent_filter(f, f.schemesIterator(),
                mSchemeToFilter, "      Scheme: ");
        int numT = register_mime_types(f, "      Type: ");
        if (numS == 0 && numT == 0) {
            register_intent_filter(f, f.actionsIterator(),
                    mActionToFilter, "      Action: ");
        }
        if (numT != 0) {
            register_intent_filter(f, f.actionsIterator(),
                    mTypedActionToFilter, "      TypedAction: ");
        }
    }
    ......
    /**
     * 所有已注册的过滤器
     */
    private final ArraySet<F> mFilters = new ArraySet<F>();

    /**
     * 所有已注册的 MIME 类型,例如“ image/jpeg”,“ image/*”
     */
    private final ArrayMap<String, F[]> mTypeToFilter = new ArrayMap<String, F[]>();

    /**
     * 已注册的所有标准 MIME 类型的基本名称,例如“image”或“*”。 通配符 MIME 类型(例如“image/*”)将不在此处。
     */
    private final ArrayMap<String, F[]> mBaseTypeToFilter = new ArrayMap<String, F[]>();

    /**
     * 已注册的带有子类型通配符的所有 MIME 类型的基本名称,带有“image/*”的过滤器将作为“image”包括在此处,但不包括带有“image/jpeg”的过滤器。
     */
    private final ArrayMap<String, F[]> mWildTypeToFilter = new ArrayMap<String, F[]>();

    /**
     * 已注册的所有 URI schemes(例如 http)
     */
    private final ArrayMap<String, F[]> mSchemeToFilter = new ArrayMap<String, F[]>();

    /**
     * 已注册的所有 Action,但只有未指定数据的
     */
    private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();

    /**
     * 已注册并指定 MIME 类型的所有 Action
     */
    private final ArrayMap<String, F[]> mTypedActionToFilter = new ArrayMap<String, F[]>();
}

打印一下 Log 查看调用过程。

07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ContextImpl registerReceiver receiveaaa@qq.com8b54cc8,aaa@qq.com
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ContextImpl registerReceiverInternal receiveaaa@qq.com8b54cc8,userId=0,aaa@qq.com,broadcastPermission=null,aaa@qq.com
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ContextImpl registerReceiverInternal aaa@qq.com,scheduler=Handler (android.app.ActivityThread$H) {db89733}
07-10 01:58:24.078 2481-2481/com.demo.framework V/lhw: ActivityManagerProxy registerReceiver aaa@qq.com,packageName=com.demo.framework,aaa@qq.comcf8e486,aaa@qq.com,perm=null,userId=0
07-10 01:58:24.079 774-1388/system_process V/lhw: ActivityManagerService registerReceiver aaa@qq.com,callerPackage=com.demo.framework,aaa@qq.com,aaa@qq.com,permission=null,userId=0

最后画时序图作为总结。
Android AOSP 6.0.1 registerReceiver广播注册流程分析

相关标签: Android源码