Program: 152526
Project: 152526
Buggy source:
/** 
 * Takes a batch of contacts and aggregates them. Returns the number of successfully processed raw contacts.
 */
private int aggregateBatch(SQLiteDatabase db,MatchCandidateList candidates,ContactMatcher matcher,ContentValues values,long[] rawContactIds,long[] contactIds){
  long elapsedTime=0;
  int aggregatedCount=0;
  while (!mCancel && aggregatedCount < MAX_TRANSACTION_SIZE) {
    db.beginTransaction();
    try {
      long start=System.currentTimeMillis();
      int count=findContactsToAggregate(db,rawContactIds,contactIds,MAX_TRANSACTION_SIZE - aggregatedCount);
      if (mCancel || count == 0) {
        break;
      }
      Log.i(TAG,"String_Node_Str" + count);
      EventLog.writeEvent(LOG_SYNC_CONTACTS_AGGREGATION,System.currentTimeMillis() - start,-count);
      for (int i=0; i < count; i++) {
        start=System.currentTimeMillis();
        aggregateContact(db,rawContactIds[i],contactIds[i],candidates,matcher,values);
        long end=System.currentTimeMillis();
        elapsedTime+=(end - start);
        aggregatedCount++;
        if (db.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) {
          break;
        }
      }
      db.setTransactionSuccessful();
    }
  finally {
      db.endTransaction();
    }
  }
  EventLog.writeEvent(LOG_SYNC_CONTACTS_AGGREGATION,elapsedTime,aggregatedCount);
  String performance=aggregatedCount == 0 ? "String_Node_Str" : "String_Node_Str" + (elapsedTime / aggregatedCount) + "String_Node_Str";
  if (aggregatedCount != 0) {
    Log.i(TAG,"String_Node_Str" + aggregatedCount + performance);
  }
  if (aggregatedCount > 0) {
    mContactsProvider.notifyChange();
  }
  return aggregatedCount;
}

Fixed version (ground truth):
/** 
 * Takes a batch of contacts and aggregates them. Returns the number of successfully processed raw contacts.
 * @return true if there are possibly more contacts to aggregate
 */
private boolean aggregateBatch(SQLiteDatabase db,MatchCandidateList candidates,ContactMatcher matcher,ContentValues values,long[] rawContactIds,long[] contactIds){
  boolean lastBatch=false;
  long elapsedTime=0;
  int aggregatedCount=0;
  while (!mCancel && aggregatedCount < MAX_TRANSACTION_SIZE) {
    db.beginTransaction();
    try {
      long start=System.currentTimeMillis();
      int count=findContactsToAggregate(db,rawContactIds,contactIds,MAX_TRANSACTION_SIZE - aggregatedCount);
      if (mCancel || count == 0) {
        lastBatch=true;
        break;
      }
      Log.i(TAG,"String_Node_Str" + count);
      EventLog.writeEvent(LOG_SYNC_CONTACTS_AGGREGATION,System.currentTimeMillis() - start,-count);
      for (int i=0; i < count; i++) {
        start=System.currentTimeMillis();
        aggregateContact(db,rawContactIds[i],contactIds[i],candidates,matcher,values);
        long end=System.currentTimeMillis();
        elapsedTime+=(end - start);
        aggregatedCount++;
        if (db.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) {
          break;
        }
      }
      db.setTransactionSuccessful();
    }
  finally {
      db.endTransaction();
    }
  }
  EventLog.writeEvent(LOG_SYNC_CONTACTS_AGGREGATION,elapsedTime,aggregatedCount);
  String performance=aggregatedCount == 0 ? "String_Node_Str" : "String_Node_Str" + (elapsedTime / aggregatedCount) + "String_Node_Str";
  if (aggregatedCount != 0) {
    Log.i(TAG,"String_Node_Str" + aggregatedCount + performance);
  }
  if (aggregatedCount > 0) {
    mContactsProvider.notifyChange();
  }
  return !lastBatch;
}