The contacts aggregation is handled by the ContactAggregator2.java
What is does is match every raw contact with other raw contacts, the aggregations is done based on a score generated by RawContactMatcher
The file contains a little explanation, but you can check the score assigned for different parameters and also the matching scores (EXACT, CONSERVATIVE and APPROXIMATE).
Example for Name-
/**
* Name matching scores: a matrix by name type vs. candidate lookup type.
* For example, if the name type is "full name" while we are looking for a
* "full name", the score may be 99. If we are looking for a "nickname" but
* find "first name", the score may be 50 (see specific scores defined
* below.)
*
* For approximate matching, we have a range of scores, let's say 40-70. Depending one how
* similar the two strings are, the score will be somewhere between 40 and 70, with the exact
* match producing the score of 70. The score may also be 0 if the similarity (distance)
* between the strings is below the threshold.
*
* We use a string matching algorithm, which is particularly suited for
* name matching. See {@link NameDistance}.
*/
If you want two contacts to be aggregated(Joined) just add an entry in http://developer.android.com/reference/android/provider/ContactsContract.AggregationExceptions.html with type as TYPE_KEEP_TOGETHER