1. 程式人生 > >Android source code(7.1) 廣播機制解析(一)

Android source code(7.1) 廣播機制解析(一)

  1. 廣播註冊的全部大致過程
  2. 無序廣播發送的全部大致過程

一、廣播註冊
關於廣播的註冊,從程式碼的角度進行跟蹤註冊的流程,主要用到ContextImp.java、ActivityManagerNative.java、ActivityManagerService.java、ApplicationThreadNative.java、ActivityThread.java、LoadedApk.java

註冊廣播:registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

ContextImp.java
public Intent registerReceiver
(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); }

下面的code呼叫registerReceiverInternal方法

ContextImp.java
 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {
        return
registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext()); }
ContextImp.java
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 { final Intent intent = ActivityManagerNative. getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); intent.prepareToEnterProcess(); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); }

上面主要是呼叫getDefault().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId);

AcitivityManagerProxy.java
 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;
    }

ok,看到這裡,app-client的註冊工作已經完成了,剩下的工作就通過binder方式來交給ActivityManagerNative.java來完成了,這裡需要知道ActivityManagerService是ActivityManagerNative.java的實現類

下面,我們來看一下System_server是如何完成app-client請求註冊的廣播的

ActivityManagerService.java
 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
        ....................

        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
          if (rl == null) {
              rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                      userId, receiver);
              if (rl.app != null) {
                  rl.app.receivers.add(rl);
              } else {
                  try {
                      receiver.asBinder().linkToDeath(rl, 0);
                  } catch (RemoteException e) {
                      return sticky;
                  }
                  rl.linkedToDeath = true;
              }
              mRegisteredReceivers.put(receiver.asBinder(), rl);
          } else if................
          BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                  permission, callingUid, userId);
          rl.add(bf);
          mReceiverResolver.addFilter(bf);
         ..................................................

           return sticky;
        }
    }

ActivityManagerService.registerReceiver方法的code比較多,我只貼出了最主要部分,裡面的mRegisteredReceivers最終來儲存註冊的廣播資訊。

有了廣播的註冊,再來看一下廣播的傳送

ContextImp.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();
        }
    }

上面的方法最終還是歸結到ActivyManagerNative,我們來看一下

public int broadcastIntent(IApplicationThread caller,Intent intent, 
    String resolvedType, IIntentReceiver resultTo,int resultCode, String resultData, Bundle map,String[] requiredPermissions, int appOp, Bundle options, boolean serialized,boolean sticky, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
        data.writeInt(resultCode);
        data.writeString(resultData);
        data.writeBundle(map);
        data.writeStringArray(requiredPermissions);
        data.writeInt(appOp);
        data.writeBundle(options);
        data.writeInt(serialized ? 1 : 0);
        data.writeInt(sticky ? 1 : 0);
        data.writeInt(userId);
        mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        reply.recycle();
        data.recycle();
        return res;
    }

app-client傳送廣播的work在這裡已經完成,剩下的交給system-server來繼續,我們繼續往下跟蹤:

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 = 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;
        }
    }

上面的code其實就是呼叫了broadcastIntentLocked方法

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) {
            ............................
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
               // Query one target user at a time, excluding shell-restricted users
               for (int i = 0; i < users.length; i++) {
                   if (mUserController.hasUserRestriction(
                           UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                       continue;
                   }
                   List<BroadcastFilter> registeredReceiversForUser =
                           mReceiverResolver.queryIntent(intent,
                                   resolvedType, false, users[i]);
                   if (registeredReceivers == null) {
                       registeredReceivers = registeredReceiversForUser;
                   } else if (registeredReceiversForUser != null) {
                       registeredReceivers.addAll(registeredReceiversForUser);
                   }
               }
           } else {
               registeredReceivers = mReceiverResolver.queryIntent(intent,
                       resolvedType, false, userId);
           }
       }

       final boolean replacePending =
               (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;

       if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueing broadcast: " + intent.getAction()
                + " replacePending=" + replacePending);

        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        if (!ordered && NR > 0) {
            // If we are not serializing this broadcast, then send the
            // registered receivers separately so they don't wait for the
            // components to be launched.
            if (isCallerSystem) {
                checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                        isProtectedBroadcast, registeredReceivers);
            }
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,resultExtras, ordered, sticky, false, userId);

            final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
            if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }

這裡省略了很多code,我們著重看一下
queue.enqueueParallelBroadcastLocked(r) 使用一個BroadcastQueue佇列來儲存要傳送的廣播
queue.scheduleBroadcastsLocked();來進行傳送廣播,後面的傳送work由BroadcastQueue來承擔

public void scheduleBroadcastsLocked() {
       if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

我們來看一下mHandler的具體code

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;
                case SCHEDULE_TEMP_WHITELIST_MSG: {
                    DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
                    if (dic != null) {
                        dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
                                msg.arg2, true, (String)msg.obj);
                    }
                } break;
            }
        }
    }

ok,mHandler裡面呼叫了processNextBroadcast方法,此方法裡code比較多,這裡就不直接貼code了,我簡單描述下此方法的功能:
1、處理無序廣播
2、處理有序廣播
3、處理pending的廣播
4、設定廣播超時時間
最終,呼叫
BroadcastQueue.deliverToRegisteredReceiverLocked ->BroadcastQueue.performReceiveLocked

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {

        if (app != null) {
            if (app.thread != null) {
             try {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState);

                } catch (RemoteException ex) {
                    synchronized (mService) {                       
                        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);
        }
    }

上面的方法,我們只關注app.thread.scheduleRegisteredReceiver(receiver,intent,resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState);這一行
app.thread是ApplicationThreadProxy物件的引用

ApplicationThreadNative.ApplicationThreadProxy
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
            int resultCode, String dataStr, Bundle extras, boolean ordered,
            boolean sticky, int sendingUser, int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(receiver.asBinder());
        intent.writeToParcel(data, 0);
        data.writeInt(resultCode);
        data.writeString(dataStr);
        data.writeBundle(extras);
        data.writeInt(ordered ? 1 : 0);
        data.writeInt(sticky ? 1 : 0);
        data.writeInt(sendingUser);
        data.writeInt(processState);
        mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

接下來,將呼叫到ActivityThread.java裡面的scheduleRegisteredReceiver方法
Note:ActivityThread是ApplicationThreadNative.java的實現類

ActivityThread.java
 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

receiver的物件型別是LoadedApk.ReceiverDispatcher.InnerReceiver的物件例項,執行InnerReceiver裡面的performReceive方法,然後再ReceiverDispatcher.performReceive方法

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;
    }

    @Override
    public void performReceive(Intent intent, int resultCode, String data,
            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
        final LoadedApk.ReceiverDispatcher rd;
        if (intent == null) {
            Log.wtf(TAG, "Null intent received");
            rd = null;
        } else {
            rd = mDispatcher.get();
        }
        if (ActivityThread.DEBUG_BROADCAST) {
            int seq = intent.getIntExtra("seq", -1);
            Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
                    + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
        }
        if (rd != null) {
            rd.performReceive(intent, resultCode, data, extras,
                    ordered, sticky, sendingUser);
        } else {
            // The activity manager dispatched a broadcast to a registered
            // receiver in this process, but before it could be delivered the
            // receiver was unregistered.  Acknowledge the broadcast on its
            // behalf so that the system's broadcast sequence can continue.
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing broadcast to unregistered receiver");
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                if (extras != null) {
                    extras.setAllowFds(false);
                }
                mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
}
................
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();
}
...........................
public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final Args args = new Args(intent, resultCode, data, extras, ordered,
            sticky, sendingUser);
    if (intent == null) {
        Log.wtf(TAG, "Null intent received");
    } else {
        if (ActivityThread.DEBUG_BROADCAST) {
            int seq = intent.getIntExtra("seq", -1);
            Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                    + " seq=" + seq + " to " + mReceiver);
        }
    }
    if (intent == null || !mActivityThread.post(args)) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManagerNative.getDefault();
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing sync broadcast to " + mReceiver);
            args.sendFinished(mgr);
        }
    }
}

if (intent == null || !mActivityThread.post(args))這一行code會最終執行BroadcastReceiver.onReceive操作,args 的code如下:

final class Args extends BroadcastReceiver.PendingResult implements Runnable {
    private Intent mCurIntent;
    private final boolean mOrdered;
    private boolean mDispatched;

    public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
            boolean ordered, boolean sticky, int sendingUser) {
        super(resultCode, resultData, resultExtras,
                mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
                sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
        mCurIntent = intent;
        mOrdered = ordered;
    }

    public void run() {
        final BroadcastReceiver receiver = mReceiver;
        final boolean ordered = mOrdered;

        if (ActivityThread.DEBUG_BROADCAST) {
            int seq = mCurIntent.getIntExtra("seq", -1);
            Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
                    + " seq=" + seq + " to " + mReceiver);
            Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
                    + " mOrderedHint=" + ordered);
        }

        final IActivityManager mgr = ActivityManagerNative.getDefault();
        final Intent intent = mCurIntent;
        if (intent == null) {
            Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
        }

        mCurIntent = null;
        mDispatched = true;
        if (receiver == null || intent == null || mForgotten) {
            if (mRegistered && ordered) {
                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing null broadcast to " + mReceiver);
                sendFinished(mgr);
            }
            return;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
        try {
            ClassLoader cl =  mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
            receiver.onReceive(mContext, intent);
        } catch (Exception e) {
            if (mRegistered && ordered) {
                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing failed broadcast to " + mReceiver);
                sendFinished(mgr);
            }
            if (mInstrumentation == null ||
                    !mInstrumentation.onException(mReceiver, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Error receiving broadcast " + intent
                    + " in " + mReceiver, e);
            }
        }

        if (receiver.getPendingResult() != null) {
            finish();
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

在Args的run()方法裡,可以看見 receiver.onReceive(mContext, intent); 這樣一行code,這樣,之前所註冊的BroadcastReceiver的onReceive方法將被執行