This article describes how to use intent to find the corresponding receiver. We still focus only on the sorting of receivers.
This article mainly targets the first two articles
Android security question (4) preemptive startup-Result
Android security question (5) preemptive interception of text messages-Result
The second step is analyzed.
Let's take a look at the broadcast sending process.
The sendbroadcast function in context is implemented in contextimpl. The following six functions are related to sending broadcasts:
Void Android. App. contextimpl. sendbroadcast (intent)
Void Android. App. contextimpl. sendbroadcast (intent, string receiverpermission)
Void Android. App. contextimpl. sendorderedbroadcast (intent, string receiverpermission)
Void Android. App. contextimpl. sendorderedbroadcast (intent, string receiverpermission, broadcastreceiver resultreceiver, Handler schedsion, int initialcode, string initialdata, bundle initialextras)
Void Android. App. contextimpl. sendstickybroadcast (intent)
Void Android. App. contextimpl. sendstickyorderedbroadcast (intent, broadcastreceiver resultreceiver, Handler scheduler, int initialcode, string initialdata, bundle initialextras)
It can be divided into three groups: 1 normal broadcast, 2ordered broadcast, and 3sticky broadcast.
Either of them will be processed by activitymanagerservice.
private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid)
Take the first case as an example. The flowchart looks like this.
Ordered and sticky are used to distinguish the preceding three groups of broadcasts.
Next, let's take a closer look at what this method has done.
Some code is deleted.
Private Final int partition (processrecord callerapp, string callerpackage, intent, string resolvedtype, iintentreceiver resulcode, int resultcode, string resultdata, bundle map, string struct, Boolean ordered, Boolean sticky, int callingpid, int callinguid ){... // process special intent // Add to the sticky list if requested .... // process sticky broadcast // figure out who all will receive this Broadcast. List receivers = NULL; List <broadcastfilter> registeredreceivers = NULL; try {If (intent. getcomponent ()! = NULL) {// broadcast is going to one specific receiver class... activityinfo AI = appglobals. getpackagemanager (). getreceiverinfo (intent. getcomponent (), stock_pm_flags); If (Ai! = NULL) {receivers = new arraylist (); resolveinfo rI = new resolveinfo (); ri. activityinfo = AI; receivers. add (RI) ;}} else {// need to resolve the intent to interested receivers... if (intent. getflags () & intent. flag_receiver_registered_only) = 0) {receivers = appglobals. getpackagemanager (). queryintentreceivers (intent, resolvedtype, stock_pm_flags);} registeredreceivers = mreceiverresolver. qu Eryintent (intent, resolvedtype, false) ;}} catch (RemoteException ex) {// PM is in same process, this will never happen .} final Boolean replacepending = (intent. getflags () & intent. flag_receiver_replace_pending )! = 0;... int Nr = registeredreceivers! = NULL? Registeredreceivers. Size (): 0;... // If the broadcast is not ordered, process the dynamically registered receiver 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. broadcastrecord r = new broadcastrecord (intent, callerapp, callerpackage, callingpid, callinguid, requiredpermission, callback, resulcode code, resultdata, MAP, ordered, sticky, false );... // mparallelbroadcasts only includes Receiver Boolean replaced = false with dynamic registration; if (replacepending) {for (INT I = mparallelbroadcasts. size ()-1; I> = 0; I --) {If (intent. filterequals (mparallelbroadcasts. get (I ). intent) {If (debug_broadcast) slog. V (TAG, "***** dropping parallel:" + intent); mparallelbroadcasts. set (I, R); replaced = true; break ;}}} if (! Replaced) {mparallelbroadcasts. add (r); schedulebroadcastslocked ();} registeredreceivers = NULL; Nr = 0 ;}// merge into one list. // If the broadcast is ordered, merge static and dynamic receivers // otherwise, the dynamic receiver is processed before. Here, registeredreceivers is null int IR = 0; If (receivers! = NULL) {... // merging process. Pay attention to the order int Nt = receivers! = NULL? Receivers. size (): 0; int it = 0; resolveinfo Curt = NULL; broadcastfilter curr = NULL; while (it <NT & IR <nr) {If (Curt = NULL) {Curt = (resolveinfo) receivers. get (IT) ;}if (curr = NULL) {curr = registeredreceivers. get (IR);} // If the dynamic receiver has a high priority, insert it to the front. // otherwise, enter else and perform the next round of comparison, take a static receiver and compare it with the previous dynamic receiver, and insert it into the list until you find your position. // adjust the sequence of the receiver with the same priority, obviously, dynamic needs to be in front of static if (curr. getpriority ()> = Curt. priority) {// I Nsert this broadcast record into the final list. receivers. add (it, curr); IR ++; curr = NULL; it ++; nt ++;} else {// skip to the next resolveinfo in the final list. it ++; Curt = NULL ;}}while (IR <nr) {If (receivers = NULL) {receivers = new arraylist ();} receivers. add (registeredreceivers. get (IR); IR ++;} If (receivers! = NULL & receivers. Size ()> 0) | resultasks! = NULL) {broadcastrecord r = new broadcastrecord (intent, callerapp, callerpackage, callingpid, callinguid, requiredpermission, receivers, resulguid code, resultdata, MAP, ordered, sticky, false );... if (! Replaced) {morderedbroadcasts. Add (r); schedulebroadcastslocked () ;}} return broadcast_success ;}
Note the two member variables mentioned in the above function.
/** * List of all active broadcasts that are to be executed immediately * (without waiting for another broadcast to finish). Currently this only * contains broadcasts to registered receivers, to avoid spinning up * a bunch of processes to execute IntentReceiver components. */final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();/** * List of all active broadcasts that are to be executed one at a time. * The object at the top of the list is the currently activity broadcasts; * those after it are waiting for the top to finish.. */final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();
If it is not an ordered broadcast, mparallelbroadcasts will store all the dynamic receivers. When merged, mparallelbroadcasts is set to null, so it will not be merged into receivers.
For ordered broadcast, mparallelbroadcasts will be merged into receivers.
Then, no matter which broadcast, schedulebroadcastslocked is called to continue processing.
Finally, go to the processnextbroadcast function.
Before reading the processnextbroadcast function, there is still a problem to be solved.
receivers = AppGlobals.getPackageManager().queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS);registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
That is, the order of the list to be queried, which has been seen in the subsequent processing process, but we have not seen the order.
Let's take a look at the situation of dynamically registered referers.
Public list <r> queryintent (intent, string resolvedtype, Boolean defaultonly) {string scheme = intent. getscheme (); arraylist <r> finallist = new arraylist <r> ();... arraylist <F> firsttypecut = NULL; arraylist <F> secondtypecut = NULL; arraylist <F> thirdtypecut = NULL; arraylist <F> schemecut = NULL; // below are some matching details. We will not pay attention to it first // if the intent except des a MIME type, then we want to collect all of // Filters that match that mime type. // mime is not involved here, So resolvedtype = NULL if (resolvedtype! = NULL ){...} // if the intent provided des a data Uri, then we want to collect all of // The filters that match its scheme (We will further refine matches // on the authority and path by directly matching each resulting filter ). if (scheme! = NULL) {schemecut = mschemetofilter. get (scheme); If (Debug) slog. V (TAG, "Scheme list:" + schemecut );} // if the intent does not specify any data -- either a MIME type or // a URI -- then we will only be looking for matches against empty // data. if (resolvedtype = NULL & scheme = NULL & intent. getaction ()! = NULL) {firsttypecut = mactiontofilter. get (intent. getaction (); // Add it to addfilter. For details, see the previous blog if (Debug) slog. V (TAG, "Action List:" + firsttypecut);} fastimmutablearrayset <string> categories = getfastintentcategories (intent); // finallist is our result set if (firsttypecut! = NULL) {// buildresolvelist loop list, check whether the conditions are met, and then copy to finallist buildresolvelist (intent, categories, debug, defaultonly, resolvedtype, scheme, firsttypecut, finallist );} if (secondtypecut! = NULL) {buildresolvelist (intent, categories, debug, defaultonly, resolvedtype, scheme, secondtypecut, finallist);} If (thirdtypecut! = NULL) {buildresolvelist (intent, categories, debug, defaultonly, resolvedtype, scheme, thirdtypecut, finallist);} If (schemecut! = NULL) {buildresolvelist (intent, categories, debug, defaultonly, resolvedtype, scheme, schemecut, finallist);} sortresults (finallist);... return finallist ;}
Here we also see the specific Sorting Code as follows, which is very simple.
@SuppressWarnings("unchecked")protected void sortResults(List<R> results) { Collections.sort(results, mResolvePrioritySorter);}// Sorts a List of IntentFilter objects into descending priority order.@SuppressWarnings("rawtypes")private static final Comparator mResolvePrioritySorter = new Comparator() { public int compare(Object o1, Object o2) { final int q1 = ((IntentFilter) o1).getPriority(); final int q2 = ((IntentFilter) o2).getPriority(); return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); }};
The above is simply sorted by priority, and the big one is placed in front, otherwise the location will not move
Next let's take a look at the situation of static registered referers. In the end, they will call the same function like the dynamically registered referers.
Public list <resolveinfo> queryintentreceivers (intent, string resolvedtype, int flags) {// It should be null after componentname. We will not discuss the situation where only specific components are sent, this does not involve priority and order issues. componentname comp = intent. getcomponent (); If (Comp = NULL) {If (intent. getselector ()! = NULL) {intent = intent. getselector (); comp = intent. getcomponent () ;}} if (Comp! = NULL) {list <resolveinfo> List = new arraylist <resolveinfo> (1); activityinfo AI = getreceiverinfo (COMP, flags); If (Ai! = NULL) {resolveinfo rI = new resolveinfo (); ri. activityinfo = AI; List. add (RI) ;}return list ;}// reader // componentname = NULL, so the following code is executed: synchronized (mpackages) {string pkgname = intent. getpackage (); // only pkgname = NULL is considered. In the same package, which receiver receives the broadcast first does not care about if (pkgname = NULL) {return mreceivers. queryintent (intent, resolvedtype, flags); // intentresolver is called. queryintent, analyzed above} final packagepa Rser. Package PKG = mpackages. Get (pkgname); If (PKG! = NULL) {return mreceivers. queryintentforpackage (intent, resolvedtype, flags, PKG. Receivers);} return NULL ;}}
The preceding two queries are sorted by priority from high to low. If the priority is the same, the order remains unchanged.
Schedulebroadcastslocked is called to broadcast to every worker.
As for how to deal with the broadcast in the future, we will not go further into it.
Now we can see the order of receipt in the application.
Summary:
There are two scenarios: schedulebroadcastslocked, ordered broadcast, and non-ordered broadcast.
Non-ordered Broadcast
First process the animation receiver, and then process the static Receiver
Ordered Broadcast
Processing both dynamic and static Receivers
First, the dynamic and static receivers are merged to maintain the same order of priority. The priority is higher than the previous one. Otherwise, the order remains unchanged. If the static receiver has the same priority as the dynamic receiver
Repost the following link
My blog address
Http://su1216.iteye.com/
Http://blog.csdn.net/su1216/