From 517d590dc73e5efcf7c94e2431faec2473924ca2 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Thu, 6 Jul 2017 15:52:01 -0700 Subject: Make CP2 low-ram friendly - Switch to ArrayMap|Set - No common nickname DB on lowram devices - Don't use WAL for profile DB, ever - Don't use WAL for contacts2.db on lowram devices Bug 63340057 Test: adb shell am instrument -w -e package android.provider.cts.contacts \ android.provider.cts/android.support.test.runner.AndroidJUnitRunner Test: bit ContactsProviderTests Change-Id: I16a6b41762874590c487ac82020bd1da7d7c0a0a --- .../providers/contacts/CallLogProvider.java | 6 +-- .../providers/contacts/ContactLocaleUtils.java | 8 +-- .../providers/contacts/ContactsDatabaseHelper.java | 4 ++ .../providers/contacts/ContactsProvider2.java | 27 +++++----- .../contacts/DataRowHandlerForGroupMembership.java | 7 +-- .../contacts/DbModifierWithNotification.java | 6 +-- .../providers/contacts/LegacyApiSupport.java | 36 ++++++------- .../android/providers/contacts/NameSplitter.java | 14 ++--- .../providers/contacts/PhotoPriorityResolver.java | 7 +-- src/com/android/providers/contacts/PhotoStore.java | 11 ++-- .../providers/contacts/SearchIndexManager.java | 4 +- .../providers/contacts/TransactionContext.java | 63 +++++++++++----------- .../aggregation/AbstractContactAggregator.java | 14 ++--- .../contacts/aggregation/ContactAggregator.java | 14 ++--- .../contacts/aggregation/ContactAggregator2.java | 14 ++--- .../aggregation/util/CommonNicknameCache.java | 10 ++-- .../aggregation/util/ContactAggregatorHelper.java | 19 +++---- .../contacts/aggregation/util/ContactMatcher.java | 4 +- .../aggregation/util/RawContactMatcher.java | 4 +- .../util/RawContactMatchingCandidates.java | 11 ++-- .../providers/contacts/util/DbQueryUtils.java | 6 +-- .../aggregation/ContactAggregator2Test.java | 15 +++++- .../aggregation/ContactAggregatorTest.java | 16 +++++- 23 files changed, 176 insertions(+), 144 deletions(-) diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java index 9b53c0ef..59e9b147 100644 --- a/src/com/android/providers/contacts/CallLogProvider.java +++ b/src/com/android/providers/contacts/CallLogProvider.java @@ -41,6 +41,7 @@ import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -50,7 +51,6 @@ import com.android.providers.contacts.util.SelectionBuilder; import com.android.providers.contacts.util.UserUtils; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -114,11 +114,11 @@ public class CallLogProvider extends ContentProvider { sURIMatcher.addURI(CallLog.SHADOW_AUTHORITY, "calls", CALLS); } - private static final HashMap sCallsProjectionMap; + private static final ArrayMap sCallsProjectionMap; static { // Calls projection map - sCallsProjectionMap = new HashMap(); + sCallsProjectionMap = new ArrayMap<>(); sCallsProjectionMap.put(Calls._ID, Calls._ID); sCallsProjectionMap.put(Calls.NUMBER, Calls.NUMBER); sCallsProjectionMap.put(Calls.POST_DIAL_DIGITS, Calls.POST_DIAL_DIGITS); diff --git a/src/com/android/providers/contacts/ContactLocaleUtils.java b/src/com/android/providers/contacts/ContactLocaleUtils.java index 2b7f1ff4..a3e97779 100644 --- a/src/com/android/providers/contacts/ContactLocaleUtils.java +++ b/src/com/android/providers/contacts/ContactLocaleUtils.java @@ -23,6 +23,7 @@ import android.os.LocaleList; import android.provider.ContactsContract.FullNameStyle; import android.provider.ContactsContract.PhoneticNameStyle; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; import com.android.providers.contacts.HanziToPinyin.Token; @@ -32,7 +33,6 @@ import com.google.common.annotations.VisibleForTesting; import java.lang.Character.UnicodeBlock; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -313,7 +313,7 @@ public class ContactLocaleUtils { // blocks are included but Korean Hangul and jamo are not). private static final Set CJ_BLOCKS; static { - Set set = new HashSet(); + Set set = new ArraySet<>(); set.add(UnicodeBlock.HIRAGANA); set.add(UnicodeBlock.KATAKANA); set.add(UnicodeBlock.KATAKANA_PHONETIC_EXTENSIONS); @@ -421,7 +421,7 @@ public class ContactLocaleUtils { TextUtils.equals(name, romajiName)) { return null; } - final HashSet keys = new HashSet(); + final ArraySet keys = new ArraySet<>(); keys.add(romajiName); return keys.iterator(); } @@ -468,7 +468,7 @@ public class ContactLocaleUtils { public static Iterator getPinyinNameLookupKeys(String name) { // TODO : Reduce the object allocation. - HashSet keys = new HashSet(); + ArraySet keys = new ArraySet<>(); ArrayList tokens = HanziToPinyin.getInstance().getTokens(name); final int tokenCount = tokens.size(); final StringBuilder keyPinyin = new StringBuilder(); diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java index 89cc3964..c45c63e3 100644 --- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java +++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java @@ -21,6 +21,7 @@ import com.android.providers.contacts.sqlite.SqlChecker; import com.android.providers.contacts.sqlite.SqlChecker.InvalidSqlException; import com.android.providers.contacts.util.PropertyUtils; +import android.app.ActivityManager; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -1059,6 +1060,9 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper { super(context, databaseName, null, DATABASE_VERSION, MINIMUM_SUPPORTED_VERSION, null); boolean enableWal = android.provider.Settings.Global.getInt(context.getContentResolver(), android.provider.Settings.Global.CONTACTS_DATABASE_WAL_ENABLED, 1) == 1; + if (dbForProfile() != 0 || ActivityManager.isLowRamDeviceStatic()) { + enableWal = false; + } setWriteAheadLoggingEnabled(enableWal); mDatabaseOptimizationEnabled = optimizationEnabled; mIsTestInstance = isTestInstance; diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java index 4feb71e6..a5af51fe 100644 --- a/src/com/android/providers/contacts/ContactsProvider2.java +++ b/src/com/android/providers/contacts/ContactsProvider2.java @@ -110,6 +110,7 @@ import android.provider.SyncStateContract; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -198,8 +199,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -1459,7 +1458,7 @@ public class ContactsProvider2 extends AbstractContactsProvider // Random number generator. private final SecureRandom mRandom = new SecureRandom(); - private final HashMap mAccountWritability = Maps.newHashMap(); + private final ArrayMap mAccountWritability = new ArrayMap<>(); private PhotoStore mContactsPhotoStore; private PhotoStore mProfilePhotoStore; @@ -1468,13 +1467,13 @@ public class ContactsProvider2 extends AbstractContactsProvider private ProfileDatabaseHelper mProfileHelper; // Separate data row handler instances for contact data and profile data. - private HashMap mDataRowHandlers; - private HashMap mProfileDataRowHandlers; + private ArrayMap mDataRowHandlers; + private ArrayMap mProfileDataRowHandlers; /** * Cached information about contact directories. */ - private HashMap mDirectoryCache = new HashMap(); + private ArrayMap mDirectoryCache = new ArrayMap<>(); private boolean mDirectoryCacheValid = false; /** @@ -1484,7 +1483,7 @@ public class ContactsProvider2 extends AbstractContactsProvider * be a small number of contact groups. The cache is keyed off source ID. The value * is a list of groups with this group ID. */ - private HashMap> mGroupIdCache = Maps.newHashMap(); + private ArrayMap> mGroupIdCache = new ArrayMap<>(); /** * Sub-provider for handling profile requests against the profile database. @@ -1684,10 +1683,10 @@ public class ContactsProvider2 extends AbstractContactsProvider mProfilePhotoStore = new PhotoStore(new File(getContext().getFilesDir(), "profile"), mProfileHelper); - mDataRowHandlers = new HashMap(); + mDataRowHandlers = new ArrayMap<>(); initDataRowHandlers(mDataRowHandlers, mContactsHelper, mContactAggregator, mContactsPhotoStore); - mProfileDataRowHandlers = new HashMap(); + mProfileDataRowHandlers = new ArrayMap<>(); initDataRowHandlers(mProfileDataRowHandlers, mProfileHelper, mProfileAggregator, mProfilePhotoStore); @@ -5050,7 +5049,7 @@ public class ContactsProvider2 extends AbstractContactsProvider private Set queryAggregationRawContactIds(SQLiteDatabase db, long rawContactId) { mSelectionArgs2[0] = String.valueOf(rawContactId); mSelectionArgs2[1] = String.valueOf(rawContactId); - Set aggregationRawContactIds = new HashSet<>(); + Set aggregationRawContactIds = new ArraySet<>(); final Cursor c = db.query(AggregationExceptionQuery.TABLE, AggregationExceptionQuery.COLUMNS, AggregationExceptionQuery.SELECTION, mSelectionArgs2, null, null, null); @@ -5122,7 +5121,7 @@ public class ContactsProvider2 extends AbstractContactsProvider } // Update AggregationException table. - final Set aggregationRawContactIdsInServer = new HashSet<>(); + final Set aggregationRawContactIdsInServer = new ArraySet<>(); for (int i = 0; i < metadataEntry.mAggregationDatas.size(); i++) { final AggregationData aggregationData = metadataEntry.mAggregationDatas.get(i); final int typeInt = getAggregationType(aggregationData.mType, null); @@ -5385,7 +5384,7 @@ public class ContactsProvider2 extends AbstractContactsProvider // Find all aggregated contacts that used to contain the raw contacts // we have just deleted and see if they are still referencing the deleted // names or photos. If so, fix up those contacts. - HashSet orphanContactIds = Sets.newHashSet(); + ArraySet orphanContactIds = new ArraySet<>(); Cursor cursor = db.rawQuery("SELECT " + Contacts._ID + " FROM " + Tables.CONTACTS + " WHERE (" + Contacts.NAME_RAW_CONTACT_ID + " NOT NULL AND " + @@ -7715,7 +7714,7 @@ public class ContactsProvider2 extends AbstractContactsProvider return null; } - HashMap projectionMap = Maps.newHashMap(); + ArrayMap projectionMap = new ArrayMap<>(); projectionMap.put(AddressBookIndexQuery.NAME, sortKey + " AS " + AddressBookIndexQuery.NAME); projectionMap.put(AddressBookIndexQuery.BUCKET, @@ -9866,7 +9865,7 @@ public class ContactsProvider2 extends AbstractContactsProvider final SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); - final Set rawContactIds = new HashSet<>(); + final Set rawContactIds = new ArraySet<>(); final Cursor cursor = db.rawQuery(rawContactIdSelect.toString(), null); try { cursor.moveToPosition(-1); diff --git a/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java b/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java index 4e9d5d4a..b1c40497 100644 --- a/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java +++ b/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java @@ -23,6 +23,7 @@ import android.database.sqlite.SQLiteDatabase; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; import android.provider.ContactsContract.Groups; import android.provider.ContactsContract.RawContacts; + import com.android.providers.contacts.ContactsDatabaseHelper.Clauses; import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns; @@ -33,7 +34,7 @@ import com.android.providers.contacts.ContactsProvider2.GroupIdCacheEntry; import com.android.providers.contacts.aggregation.AbstractContactAggregator; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Map; /** * Handler for group membership data rows. @@ -62,11 +63,11 @@ public class DataRowHandlerForGroupMembership extends DataRowHandler { + " AND " + Tables.DATA + "." + GroupMembership.RAW_CONTACT_ID + "=?" + " AND " + Groups.FAVORITES + "!=0"; - private final HashMap> mGroupIdCache; + private final Map> mGroupIdCache; public DataRowHandlerForGroupMembership(Context context, ContactsDatabaseHelper dbHelper, AbstractContactAggregator aggregator, - HashMap> groupIdCache) { + Map> groupIdCache) { super(context, dbHelper, aggregator, GroupMembership.CONTENT_ITEM_TYPE); mGroupIdCache = groupIdCache; } diff --git a/src/com/android/providers/contacts/DbModifierWithNotification.java b/src/com/android/providers/contacts/DbModifierWithNotification.java index cb5460ce..7e7b3e17 100644 --- a/src/com/android/providers/contacts/DbModifierWithNotification.java +++ b/src/com/android/providers/contacts/DbModifierWithNotification.java @@ -36,6 +36,7 @@ import android.provider.CallLog.Calls; import android.provider.VoicemailContract; import android.provider.VoicemailContract.Status; import android.provider.VoicemailContract.Voicemails; +import android.util.ArraySet; import android.util.Log; import com.android.common.io.MoreCloseables; @@ -46,7 +47,6 @@ import com.google.android.collect.Lists; import com.google.common.collect.Iterables; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -262,7 +262,7 @@ public class DbModifierWithNotification implements DatabaseModifier { * always expected to have the source package field set. */ private Set getModifiedPackages(String whereClause, String[] whereArgs) { - Set modifiedPackages = new HashSet(); + Set modifiedPackages = new ArraySet<>(); Cursor cursor = mDb.query(mTableName, PROJECTION, DbQueryUtils.concatenateClauses(NON_NULL_SOURCE_PACKAGE_SELECTION, whereClause), whereArgs, null, null, null); @@ -280,7 +280,7 @@ public class DbModifierWithNotification implements DatabaseModifier { * package field set. */ private Set getModifiedPackages(ContentValues values) { - Set impactedPackages = new HashSet(); + Set impactedPackages = new ArraySet<>(); if(values.containsKey(VoicemailContract.SOURCE_PACKAGE_FIELD)) { impactedPackages.add(values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD)); } diff --git a/src/com/android/providers/contacts/LegacyApiSupport.java b/src/com/android/providers/contacts/LegacyApiSupport.java index 741639a2..c111cf39 100644 --- a/src/com/android/providers/contacts/LegacyApiSupport.java +++ b/src/com/android/providers/contacts/LegacyApiSupport.java @@ -50,6 +50,7 @@ import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.Settings; import android.provider.ContactsContract.StatusUpdates; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns; @@ -65,7 +66,6 @@ import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns; import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns; import com.android.providers.contacts.ContactsDatabaseHelper.Tables; -import java.util.HashMap; import java.util.Locale; @SuppressWarnings("deprecation") @@ -250,14 +250,14 @@ public class LegacyApiSupport { + " AND " + DataColumns.CONCRETE_ID + " = legacy_photo." + LegacyPhotoData.PHOTO_DATA_ID + ")"; - private static final HashMap sPeopleProjectionMap; - private static final HashMap sOrganizationProjectionMap; - private static final HashMap sContactMethodProjectionMap; - private static final HashMap sPhoneProjectionMap; - private static final HashMap sExtensionProjectionMap; - private static final HashMap sGroupProjectionMap; - private static final HashMap sGroupMembershipProjectionMap; - private static final HashMap sPhotoProjectionMap; + private static final ArrayMap sPeopleProjectionMap; + private static final ArrayMap sOrganizationProjectionMap; + private static final ArrayMap sContactMethodProjectionMap; + private static final ArrayMap sPhoneProjectionMap; + private static final ArrayMap sExtensionProjectionMap; + private static final ArrayMap sGroupProjectionMap; + private static final ArrayMap sGroupMembershipProjectionMap; + private static final ArrayMap sPhotoProjectionMap; static { @@ -335,7 +335,7 @@ public class LegacyApiSupport { SEARCH_SHORTCUT); matcher.addURI(authority, "settings", SETTINGS); - HashMap peopleProjectionMap = new HashMap(); + ArrayMap peopleProjectionMap = new ArrayMap<>(); peopleProjectionMap.put(People.NAME, People.NAME); peopleProjectionMap.put(People.DISPLAY_NAME, People.DISPLAY_NAME); peopleProjectionMap.put(People.PHONETIC_NAME, People.PHONETIC_NAME); @@ -349,7 +349,7 @@ public class LegacyApiSupport { peopleProjectionMap.put(People.PRIMARY_EMAIL_ID, People.PRIMARY_EMAIL_ID); peopleProjectionMap.put(People.PRIMARY_PHONE_ID, People.PRIMARY_PHONE_ID); - sPeopleProjectionMap = new HashMap(peopleProjectionMap); + sPeopleProjectionMap = new ArrayMap<>(peopleProjectionMap); sPeopleProjectionMap.put(People._ID, People._ID); sPeopleProjectionMap.put(People.NUMBER, People.NUMBER); sPeopleProjectionMap.put(People.TYPE, People.TYPE); @@ -369,7 +369,7 @@ public class LegacyApiSupport { " LIMIT 1" + ") AS " + People.PRESENCE_CUSTOM_STATUS); - sOrganizationProjectionMap = new HashMap(); + sOrganizationProjectionMap = new ArrayMap<>(); sOrganizationProjectionMap.put(android.provider.Contacts.Organizations._ID, android.provider.Contacts.Organizations._ID); sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.PERSON_ID, @@ -385,7 +385,7 @@ public class LegacyApiSupport { sOrganizationProjectionMap.put(android.provider.Contacts.Organizations.TITLE, android.provider.Contacts.Organizations.TITLE); - sContactMethodProjectionMap = new HashMap(peopleProjectionMap); + sContactMethodProjectionMap = new ArrayMap<>(peopleProjectionMap); sContactMethodProjectionMap.put(ContactMethods._ID, ContactMethods._ID); sContactMethodProjectionMap.put(ContactMethods.PERSON_ID, ContactMethods.PERSON_ID); sContactMethodProjectionMap.put(ContactMethods.KIND, ContactMethods.KIND); @@ -395,7 +395,7 @@ public class LegacyApiSupport { sContactMethodProjectionMap.put(ContactMethods.LABEL, ContactMethods.LABEL); sContactMethodProjectionMap.put(ContactMethods.AUX_DATA, ContactMethods.AUX_DATA); - sPhoneProjectionMap = new HashMap(peopleProjectionMap); + sPhoneProjectionMap = new ArrayMap<>(peopleProjectionMap); sPhoneProjectionMap.put(android.provider.Contacts.Phones._ID, android.provider.Contacts.Phones._ID); sPhoneProjectionMap.put(android.provider.Contacts.Phones.PERSON_ID, @@ -411,7 +411,7 @@ public class LegacyApiSupport { sPhoneProjectionMap.put(android.provider.Contacts.Phones.NUMBER_KEY, android.provider.Contacts.Phones.NUMBER_KEY); - sExtensionProjectionMap = new HashMap(); + sExtensionProjectionMap = new ArrayMap<>(); sExtensionProjectionMap.put(android.provider.Contacts.Extensions._ID, android.provider.Contacts.Extensions._ID); sExtensionProjectionMap.put(android.provider.Contacts.Extensions.PERSON_ID, @@ -421,7 +421,7 @@ public class LegacyApiSupport { sExtensionProjectionMap.put(android.provider.Contacts.Extensions.VALUE, android.provider.Contacts.Extensions.VALUE); - sGroupProjectionMap = new HashMap(); + sGroupProjectionMap = new ArrayMap<>(); sGroupProjectionMap.put(android.provider.Contacts.Groups._ID, android.provider.Contacts.Groups._ID); sGroupProjectionMap.put(android.provider.Contacts.Groups.NAME, @@ -431,7 +431,7 @@ public class LegacyApiSupport { sGroupProjectionMap.put(android.provider.Contacts.Groups.SYSTEM_ID, android.provider.Contacts.Groups.SYSTEM_ID); - sGroupMembershipProjectionMap = new HashMap(sGroupProjectionMap); + sGroupMembershipProjectionMap = new ArrayMap<>(sGroupProjectionMap); sGroupMembershipProjectionMap.put(android.provider.Contacts.GroupMembership._ID, android.provider.Contacts.GroupMembership._ID); sGroupMembershipProjectionMap.put(android.provider.Contacts.GroupMembership.PERSON_ID, @@ -448,7 +448,7 @@ public class LegacyApiSupport { android.provider.Contacts.GroupMembership.GROUP_SYNC_ACCOUNT_TYPE, android.provider.Contacts.GroupMembership.GROUP_SYNC_ACCOUNT_TYPE); - sPhotoProjectionMap = new HashMap(); + sPhotoProjectionMap = new ArrayMap<>(); sPhotoProjectionMap.put(android.provider.Contacts.Photos._ID, android.provider.Contacts.Photos._ID); sPhotoProjectionMap.put(android.provider.Contacts.Photos.PERSON_ID, diff --git a/src/com/android/providers/contacts/NameSplitter.java b/src/com/android/providers/contacts/NameSplitter.java index ebf6136d..50b50fbb 100644 --- a/src/com/android/providers/contacts/NameSplitter.java +++ b/src/com/android/providers/contacts/NameSplitter.java @@ -20,11 +20,11 @@ import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.FullNameStyle; import android.provider.ContactsContract.PhoneticNameStyle; import android.text.TextUtils; +import android.util.ArraySet; import com.android.providers.contacts.util.NeededForTesting; import java.lang.Character.UnicodeBlock; -import java.util.HashSet; import java.util.Locale; import java.util.StringTokenizer; @@ -53,11 +53,11 @@ public class NameSplitter { // This includes simplified and traditional Chinese private static final String CHINESE_LANGUAGE = Locale.CHINESE.getLanguage().toLowerCase(); - private final HashSet mPrefixesSet; - private final HashSet mSuffixesSet; + private final ArraySet mPrefixesSet; + private final ArraySet mSuffixesSet; private final int mMaxSuffixLength; - private final HashSet mLastNamePrefixesSet; - private final HashSet mConjuctions; + private final ArraySet mLastNamePrefixesSet; + private final ArraySet mConjuctions; private final Locale mLocale; private final String mLanguage; @@ -304,8 +304,8 @@ public class NameSplitter { * Converts a comma-separated list of Strings to a set of Strings. Trims strings * and converts them to upper case. */ - private static HashSet convertToSet(String strings) { - HashSet set = new HashSet(); + private static ArraySet convertToSet(String strings) { + ArraySet set = new ArraySet<>(); if (strings != null) { String[] split = strings.split(","); for (int i = 0; i < split.length; i++) { diff --git a/src/com/android/providers/contacts/PhotoPriorityResolver.java b/src/com/android/providers/contacts/PhotoPriorityResolver.java index bbf83c5c..e9b94649 100644 --- a/src/com/android/providers/contacts/PhotoPriorityResolver.java +++ b/src/com/android/providers/contacts/PhotoPriorityResolver.java @@ -21,20 +21,17 @@ import android.accounts.AuthenticatorDescription; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.XmlResourceParser; -import android.util.Log; +import android.util.ArrayMap; import com.android.internal.util.XmlUtils; -import com.google.android.collect.Maps; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; -import java.util.HashMap; import java.util.List; /** @@ -76,7 +73,7 @@ public class PhotoPriorityResolver { private static final String PRIORITY_ATTR = "priority"; private Context mContext; - private HashMap mPhotoPriorities = Maps.newHashMap(); + private ArrayMap mPhotoPriorities = new ArrayMap<>(); public PhotoPriorityResolver(Context context) { mContext = context; diff --git a/src/com/android/providers/contacts/PhotoStore.java b/src/com/android/providers/contacts/PhotoStore.java index 79042c40..f2b95b6b 100644 --- a/src/com/android/providers/contacts/PhotoStore.java +++ b/src/com/android/providers/contacts/PhotoStore.java @@ -19,17 +19,18 @@ import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; import android.provider.ContactsContract.PhotoFiles; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns; import com.android.providers.contacts.ContactsDatabaseHelper.Tables; + import com.google.common.annotations.VisibleForTesting; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -77,7 +78,7 @@ public class PhotoStore { } } mDatabaseHelper = databaseHelper; - mEntries = new HashMap(); + mEntries = new ArrayMap(); initialize(); } @@ -146,7 +147,7 @@ public class PhotoStore { * @return The set of the keys in use that refer to non-existent entries. */ public Set cleanup(Set keysInUse) { - Set keysToRemove = new HashSet(); + Set keysToRemove = new ArraySet<>(); keysToRemove.addAll(mEntries.keySet()); keysToRemove.removeAll(keysInUse); if (!keysToRemove.isEmpty()) { @@ -156,7 +157,7 @@ public class PhotoStore { } } - Set missingKeys = new HashSet(); + Set missingKeys = new ArraySet<>(); missingKeys.addAll(keysInUse); missingKeys.removeAll(mEntries.keySet()); return missingKeys; diff --git a/src/com/android/providers/contacts/SearchIndexManager.java b/src/com/android/providers/contacts/SearchIndexManager.java index 768fb978..14c78a77 100644 --- a/src/com/android/providers/contacts/SearchIndexManager.java +++ b/src/com/android/providers/contacts/SearchIndexManager.java @@ -27,6 +27,7 @@ import android.provider.ContactsContract.Data; import android.provider.ContactsContract.ProviderStatus; import android.provider.ContactsContract.RawContacts; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; @@ -38,7 +39,6 @@ import com.google.android.collect.Lists; import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; @@ -76,7 +76,7 @@ public class SearchIndexManager { private StringBuilder mSbName = new StringBuilder(); private StringBuilder mSbTokens = new StringBuilder(); private StringBuilder mSbElementContent = new StringBuilder(); - private HashSet mUniqueElements = new HashSet(); + private ArraySet mUniqueElements = new ArraySet<>(); private Cursor mCursor; void setCursor(Cursor cursor) { diff --git a/src/com/android/providers/contacts/TransactionContext.java b/src/com/android/providers/contacts/TransactionContext.java index 5cc91026..dfb6d696 100644 --- a/src/com/android/providers/contacts/TransactionContext.java +++ b/src/com/android/providers/contacts/TransactionContext.java @@ -16,11 +16,12 @@ package com.android.providers.contacts; +import android.util.ArrayMap; +import android.util.ArraySet; + import com.google.android.collect.Maps; import com.google.android.collect.Sets; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map.Entry; import java.util.Set; @@ -32,19 +33,19 @@ public class TransactionContext { private final boolean mForProfile; /** Map from raw contact id to account Id */ - private HashMap mInsertedRawContactsAccounts; - private HashSet mUpdatedRawContacts; - private HashSet mMetadataDirtyRawContacts; - private HashSet mBackupIdChangedRawContacts; - private HashSet mDirtyRawContacts; + private ArrayMap mInsertedRawContactsAccounts; + private ArraySet mUpdatedRawContacts; + private ArraySet mMetadataDirtyRawContacts; + private ArraySet mBackupIdChangedRawContacts; + private ArraySet mDirtyRawContacts; // Set used to track what has been changed and deleted. This is needed so we can update the // contact last touch timestamp. Dirty set above is only set when sync adapter is false. // {@see android.provider.ContactsContract#CALLER_IS_SYNCADAPTER}. While the set below will // contain all changed contacts. - private HashSet mChangedRawContacts; - private HashSet mStaleSearchIndexRawContacts; - private HashSet mStaleSearchIndexContacts; - private HashMap mUpdatedSyncStates; + private ArraySet mChangedRawContacts; + private ArraySet mStaleSearchIndexRawContacts; + private ArraySet mStaleSearchIndexContacts; + private ArrayMap mUpdatedSyncStates; public TransactionContext(boolean forProfile) { mForProfile = forProfile; @@ -55,21 +56,21 @@ public class TransactionContext { } public void rawContactInserted(long rawContactId, long accountId) { - if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = Maps.newHashMap(); + if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = new ArrayMap<>(); mInsertedRawContactsAccounts.put(rawContactId, accountId); markRawContactChangedOrDeletedOrInserted(rawContactId); } public void rawContactUpdated(long rawContactId) { - if (mUpdatedRawContacts == null) mUpdatedRawContacts = Sets.newHashSet(); + if (mUpdatedRawContacts == null) mUpdatedRawContacts = new ArraySet<>(); mUpdatedRawContacts.add(rawContactId); } public void markRawContactDirtyAndChanged(long rawContactId, boolean isSyncAdapter) { if (!isSyncAdapter) { if (mDirtyRawContacts == null) { - mDirtyRawContacts = Sets.newHashSet(); + mDirtyRawContacts = new ArraySet<>(); } mDirtyRawContacts.add(rawContactId); } @@ -80,7 +81,7 @@ public class TransactionContext { public void markRawContactMetadataDirty(long rawContactId, boolean isMetadataSyncAdapter) { if (!isMetadataSyncAdapter) { if (mMetadataDirtyRawContacts == null) { - mMetadataDirtyRawContacts = Sets.newHashSet(); + mMetadataDirtyRawContacts = new ArraySet<>(); } mMetadataDirtyRawContacts.add(rawContactId); } @@ -88,85 +89,85 @@ public class TransactionContext { public void markBackupIdChangedRawContact(long rawContactId) { if (mBackupIdChangedRawContacts == null) { - mBackupIdChangedRawContacts = Sets.newHashSet(); + mBackupIdChangedRawContacts = new ArraySet<>(); } mBackupIdChangedRawContacts.add(rawContactId); } public void markRawContactChangedOrDeletedOrInserted(long rawContactId) { if (mChangedRawContacts == null) { - mChangedRawContacts = Sets.newHashSet(); + mChangedRawContacts = new ArraySet<>(); } mChangedRawContacts.add(rawContactId); } public void syncStateUpdated(long rowId, Object data) { - if (mUpdatedSyncStates == null) mUpdatedSyncStates = Maps.newHashMap(); + if (mUpdatedSyncStates == null) mUpdatedSyncStates = new ArrayMap<>(); mUpdatedSyncStates.put(rowId, data); } public void invalidateSearchIndexForRawContact(long rawContactId) { - if (mStaleSearchIndexRawContacts == null) mStaleSearchIndexRawContacts = Sets.newHashSet(); + if (mStaleSearchIndexRawContacts == null) mStaleSearchIndexRawContacts = new ArraySet<>(); mStaleSearchIndexRawContacts.add(rawContactId); } public void invalidateSearchIndexForContact(long contactId) { - if (mStaleSearchIndexContacts == null) mStaleSearchIndexContacts = Sets.newHashSet(); + if (mStaleSearchIndexContacts == null) mStaleSearchIndexContacts = new ArraySet<>(); mStaleSearchIndexContacts.add(contactId); } public Set getInsertedRawContactIds() { - if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = Maps.newHashMap(); + if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = new ArrayMap<>(); return mInsertedRawContactsAccounts.keySet(); } public Set getUpdatedRawContactIds() { - if (mUpdatedRawContacts == null) mUpdatedRawContacts = Sets.newHashSet(); + if (mUpdatedRawContacts == null) mUpdatedRawContacts = new ArraySet<>(); return mUpdatedRawContacts; } public Set getDirtyRawContactIds() { - if (mDirtyRawContacts == null) mDirtyRawContacts = Sets.newHashSet(); + if (mDirtyRawContacts == null) mDirtyRawContacts = new ArraySet<>(); return mDirtyRawContacts; } public Set getMetadataDirtyRawContactIds() { - if (mMetadataDirtyRawContacts == null) mMetadataDirtyRawContacts = Sets.newHashSet(); + if (mMetadataDirtyRawContacts == null) mMetadataDirtyRawContacts = new ArraySet<>(); return mMetadataDirtyRawContacts; } public Set getBackupIdChangedRawContacts() { - if (mBackupIdChangedRawContacts == null) mBackupIdChangedRawContacts = Sets.newHashSet(); + if (mBackupIdChangedRawContacts == null) mBackupIdChangedRawContacts = new ArraySet<>(); return mBackupIdChangedRawContacts; } public Set getChangedRawContactIds() { - if (mChangedRawContacts == null) mChangedRawContacts = Sets.newHashSet(); + if (mChangedRawContacts == null) mChangedRawContacts = new ArraySet<>(); return mChangedRawContacts; } public Set getStaleSearchIndexRawContactIds() { - if (mStaleSearchIndexRawContacts == null) mStaleSearchIndexRawContacts = Sets.newHashSet(); + if (mStaleSearchIndexRawContacts == null) mStaleSearchIndexRawContacts = new ArraySet<>(); return mStaleSearchIndexRawContacts; } public Set getStaleSearchIndexContactIds() { - if (mStaleSearchIndexContacts == null) mStaleSearchIndexContacts = Sets.newHashSet(); + if (mStaleSearchIndexContacts == null) mStaleSearchIndexContacts = new ArraySet<>(); return mStaleSearchIndexContacts; } public Set> getUpdatedSyncStates() { - if (mUpdatedSyncStates == null) mUpdatedSyncStates = Maps.newHashMap(); + if (mUpdatedSyncStates == null) mUpdatedSyncStates = new ArrayMap<>(); return mUpdatedSyncStates.entrySet(); } public Long getAccountIdOrNullForRawContact(long rawContactId) { - if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = Maps.newHashMap(); + if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = new ArrayMap<>(); return mInsertedRawContactsAccounts.get(rawContactId); } public boolean isNewRawContact(long rawContactId) { - if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = Maps.newHashMap(); + if (mInsertedRawContactsAccounts == null) mInsertedRawContactsAccounts = new ArrayMap<>(); return mInsertedRawContactsAccounts.containsKey(rawContactId); } diff --git a/src/com/android/providers/contacts/aggregation/AbstractContactAggregator.java b/src/com/android/providers/contacts/aggregation/AbstractContactAggregator.java index 20e3bbec..965780ea 100644 --- a/src/com/android/providers/contacts/aggregation/AbstractContactAggregator.java +++ b/src/com/android/providers/contacts/aggregation/AbstractContactAggregator.java @@ -67,14 +67,14 @@ import android.provider.ContactsContract.PinnedPositions; import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.StatusUpdates; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Slog; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -170,7 +170,7 @@ public abstract class AbstractContactAggregator { protected SQLiteStatement mContactInsert; protected SQLiteStatement mResetPinnedForRawContact; - protected HashMap mRawContactsMarkedForAggregation = Maps.newHashMap(); + protected ArrayMap mRawContactsMarkedForAggregation = new ArrayMap<>(); protected String[] mSelectionArgs1 = new String[1]; protected String[] mSelectionArgs2 = new String[2]; @@ -532,7 +532,7 @@ public abstract class AbstractContactAggregator { public final void clearPendingAggregations() { // HashMap woulnd't shrink the internal table once expands it, so let's just re-create // a new one instead of clear()ing it. - mRawContactsMarkedForAggregation = Maps.newHashMap(); + mRawContactsMarkedForAggregation = new ArrayMap<>(); } public final void markNewForAggregation(long rawContactId, int aggregationMode) { @@ -951,7 +951,7 @@ public abstract class AbstractContactAggregator { } // A set of raw contact IDs for which there are aggregation exceptions - protected final HashSet mAggregationExceptionIds = new HashSet(); + protected final ArraySet mAggregationExceptionIds = new ArraySet<>(); protected boolean mAggregationExceptionIdsValid; public final void invalidateAggregationExceptionCache() { @@ -1958,7 +1958,7 @@ public abstract class AbstractContactAggregator { try { List bestMatches = findMatchingContacts(db, contactId, parameters); List bestMatchesWithoutDuplicateContactIds = new ArrayList<>(); - Set contactIds = new HashSet<>(); + Set contactIds = new ArraySet<>(); for (MatchScore bestMatch : bestMatches) { long cid = bestMatch.getContactId(); if (!contactIds.contains(cid) && cid != contactId) { @@ -2005,7 +2005,7 @@ public abstract class AbstractContactAggregator { } // Run a query and find ids of best matching contacts satisfying the filter (if any) - HashSet foundIds = new HashSet(); + ArraySet foundIds = new ArraySet(); Cursor cursor = db.query(qb.getTables(), ContactIdQuery.COLUMNS, sb.toString(), null, null, null, null); try { diff --git a/src/com/android/providers/contacts/aggregation/ContactAggregator.java b/src/com/android/providers/contacts/aggregation/ContactAggregator.java index e7fd910f..e5bd2eaf 100644 --- a/src/com/android/providers/contacts/aggregation/ContactAggregator.java +++ b/src/com/android/providers/contacts/aggregation/ContactAggregator.java @@ -25,6 +25,7 @@ import android.provider.ContactsContract.Contacts.AggregationSuggestions; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.RawContacts; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; import com.android.providers.contacts.ContactsDatabaseHelper; import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; @@ -43,7 +44,6 @@ import com.android.providers.contacts.database.ContactsTableUtil; import com.google.android.collect.Sets; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -95,8 +95,8 @@ public class ContactAggregator extends AbstractContactAggregator { boolean needReaggregate = false; final ContactMatcher matcher = new ContactMatcher(); - final Set rawContactIdsInSameAccount = new HashSet(); - final Set rawContactIdsInOtherAccount = new HashSet(); + final Set rawContactIdsInSameAccount = new ArraySet<>(); + final Set rawContactIdsInOtherAccount = new ArraySet<>(); if (aggregationMode == RawContacts.AGGREGATION_MODE_DEFAULT) { candidates.clear(); matcher.clear(); @@ -202,7 +202,7 @@ public class ContactAggregator extends AbstractContactAggregator { } } else if (needReaggregate) { // re-aggregate - final Set allRawContactIdSet = new HashSet(); + final Set allRawContactIdSet = new ArraySet<>(); allRawContactIdSet.addAll(rawContactIdsInSameAccount); allRawContactIdSet.addAll(rawContactIdsInOtherAccount); // If there is no other raw contacts aggregated with the given raw contact currently, @@ -345,7 +345,7 @@ public class ContactAggregator extends AbstractContactAggregator { } - final Set rawContactIdSet = new HashSet(); + final Set rawContactIdSet = new ArraySet<>(); rawContactIdSet.add(rawContactId); if (rawContactIdsInSameAccount.size() > 0 && isDataMaching(db, rawContactIdSet, rawContactIdsInSameAccount)) { @@ -419,7 +419,7 @@ public class ContactAggregator extends AbstractContactAggregator { // Find the connected component based on the aggregation exceptions or // identity/email/phone matching for all the raw contacts of [contactId] and the give // raw contact. - final Set allIds = new HashSet(); + final Set allIds = new ArraySet<>(); allIds.add(rawContactId); allIds.addAll(existingRawContactIds); final Set> connectedRawContactSets = findConnectedRawContacts(db, allIds); @@ -821,7 +821,7 @@ public class ContactAggregator extends AbstractContactAggregator { */ private void lookupApproximateNameMatches(SQLiteDatabase db, MatchCandidateList candidates, ContactMatcher matcher) { - HashSet firstLetters = new HashSet(); + ArraySet firstLetters = new ArraySet<>(); for (int i = 0; i < candidates.mCount; i++) { final NameMatchCandidate candidate = candidates.mList.get(i); if (candidate.mName.length() >= 2) { diff --git a/src/com/android/providers/contacts/aggregation/ContactAggregator2.java b/src/com/android/providers/contacts/aggregation/ContactAggregator2.java index 5e1821b2..e0bc3bb4 100644 --- a/src/com/android/providers/contacts/aggregation/ContactAggregator2.java +++ b/src/com/android/providers/contacts/aggregation/ContactAggregator2.java @@ -31,6 +31,7 @@ import android.provider.ContactsContract.FullNameStyle; import android.provider.ContactsContract.PhotoFiles; import android.provider.ContactsContract.RawContacts; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; import com.android.providers.contacts.ContactsDatabaseHelper; import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns; @@ -54,7 +55,6 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -212,14 +212,14 @@ public class ContactAggregator2 extends AbstractContactAggregator { updateMatchScores(db, rawContactId, candidates, matcher); final RawContactMatchingCandidates matchingCandidates = new RawContactMatchingCandidates( matcher.pickBestMatches()); - Set newIds = new HashSet<>(); + Set newIds = new ArraySet<>(); newIds.addAll(matchingCandidates.getRawContactIdSet()); // Keep doing the following until no new raw contact candidate is found. while (!newIds.isEmpty()) { if (matchingCandidates.getCount() >= AGGREGATION_CONTACT_SIZE_LIMIT) { return matchingCandidates; } - final Set tmpIdSet = new HashSet<>(); + final Set tmpIdSet = new ArraySet<>(); for (long rId : newIds) { final RawContactMatcher rMatcher = new RawContactMatcher(); updateMatchScores(db, rId, new MatchCandidateList(), @@ -315,7 +315,7 @@ public class ContactAggregator2 extends AbstractContactAggregator { // Find the connected component based on the aggregation exceptions or // identity/email/phone matching for all the raw contacts of [contactId] and the give // raw contact. - final Set allIds = new HashSet<>(); + final Set allIds = new ArraySet<>(); allIds.add(rawContactId); allIds.addAll(matchingCandidates.getRawContactIdSet()); final Set> connectedRawContactSets = findConnectedRawContacts(db, allIds); @@ -331,7 +331,7 @@ public class ContactAggregator2 extends AbstractContactAggregator { // Update aggregate data for all the contactIds touched by this connected component, for (Set connectedRawContactIds : connectedRawContactSets) { Long contactId = null; - Set cidsNeedToBeUpdated = new HashSet<>(); + Set cidsNeedToBeUpdated = new ArraySet<>(); if (connectedRawContactIds.contains(rawContactId)) { // If there is no other raw contacts aggregated with the given raw contact currently // or all the raw contacts in [currentCidForRawContact] are still in the same @@ -422,7 +422,7 @@ public class ContactAggregator2 extends AbstractContactAggregator { */ private void breakComponentsByExceptions(SQLiteDatabase db, Set> connectedRawContacts) { - final Set> tmpSets = new HashSet<>(connectedRawContacts); + final Set> tmpSets = new ArraySet<>(connectedRawContacts); for (Set component : tmpSets) { final String rawContacts = TextUtils.join(",", component); // If "SEPARATE" exception is found inside an connected component [component], @@ -691,7 +691,7 @@ public class ContactAggregator2 extends AbstractContactAggregator { */ private void lookupApproximateNameMatches(SQLiteDatabase db, MatchCandidateList candidates, RawContactMatcher matcher) { - HashSet firstLetters = new HashSet<>(); + ArraySet firstLetters = new ArraySet<>(); for (int i = 0; i < candidates.mCount; i++) { final NameMatchCandidate candidate = candidates.mList.get(i); if (candidate.mName.length() >= 2) { diff --git a/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java index 9643d815..5e8126a3 100644 --- a/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java +++ b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java @@ -16,16 +16,16 @@ package com.android.providers.contacts.aggregation.util; +import android.app.ActivityManager; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.util.ArrayMap; import com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns; import com.android.providers.contacts.ContactsDatabaseHelper.Tables; -import com.google.android.collect.Maps; import java.lang.ref.SoftReference; import java.util.BitSet; -import java.util.HashMap; /** * Cache for common nicknames. @@ -36,7 +36,8 @@ public class CommonNicknameCache { private static final int NICKNAME_BLOOM_FILTER_SIZE = 0x1FFF; // =long[128] private BitSet mNicknameBloomFilter; - private HashMap> mNicknameClusterCache = Maps.newHashMap(); + private final ArrayMap> mNicknameClusterCache + = new ArrayMap<>(); private final SQLiteDatabase mDb; @@ -88,6 +89,9 @@ public class CommonNicknameCache { * Returns nickname cluster IDs or null. Maintains cache. */ public String[] getCommonNicknameClusters(String normalizedName) { + if (ActivityManager.isLowRamDeviceStatic()) { + return null; // Do not use common nickname cache on lowram devices. + } if (mNicknameBloomFilter == null) { preloadNicknameBloomFilter(); } diff --git a/src/com/android/providers/contacts/aggregation/util/ContactAggregatorHelper.java b/src/com/android/providers/contacts/aggregation/util/ContactAggregatorHelper.java index 9c19dcec..4311fe32 100644 --- a/src/com/android/providers/contacts/aggregation/util/ContactAggregatorHelper.java +++ b/src/com/android/providers/contacts/aggregation/util/ContactAggregatorHelper.java @@ -16,12 +16,13 @@ package com.android.providers.contacts.aggregation.util; +import android.util.ArrayMap; +import android.util.ArraySet; + import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -40,9 +41,9 @@ public class ContactAggregatorHelper { public static void mergeComponentsWithDisjointAccounts(Set> connectedRawContactSets, Map rawContactsToAccounts) { // Index to rawContactIds mapping - final Map> rawContactIds = new HashMap<>(); + final Map> rawContactIds = new ArrayMap<>(); // AccountId to indices mapping - final Map> accounts = new HashMap<>(); + final Map> accounts = new ArrayMap<>(); int index = 0; for (Set rIds : connectedRawContactSets) { @@ -51,7 +52,7 @@ public class ContactAggregatorHelper { long acctId = rawContactsToAccounts.get(rId); Set s = accounts.get(acctId); if (s == null) { - s = new HashSet(); + s = new ArraySet(); } s.add(index); accounts.put(acctId, s); @@ -73,7 +74,7 @@ public class ContactAggregatorHelper { } } - final Set mergedSet = new HashSet<>(); + final Set mergedSet = new ArraySet<>(); for (Long accountId : accounts.keySet()) { final Set s = accounts.get(accountId); if (s.size() == 1) { @@ -93,11 +94,11 @@ public class ContactAggregatorHelper { @VisibleForTesting public static Set> findConnectedComponents(Set rawContactIdSet, Multimap matchingRawIdPairs) { - Set> connectedRawContactSets = new HashSet<>(); - Set visited = new HashSet<>(); + Set> connectedRawContactSets = new ArraySet<>(); + Set visited = new ArraySet<>(); for (Long id : rawContactIdSet) { if (!visited.contains(id)) { - Set set = new HashSet<>(); + Set set = new ArraySet<>(); findConnectedComponentForRawContact(matchingRawIdPairs, visited, id, set); connectedRawContactSets.add(set); } diff --git a/src/com/android/providers/contacts/aggregation/util/ContactMatcher.java b/src/com/android/providers/contacts/aggregation/util/ContactMatcher.java index 9b71651b..c5837edd 100644 --- a/src/com/android/providers/contacts/aggregation/util/ContactMatcher.java +++ b/src/com/android/providers/contacts/aggregation/util/ContactMatcher.java @@ -18,11 +18,11 @@ package com.android.providers.contacts.aggregation.util; import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; import com.android.providers.contacts.util.Hex; +import android.util.ArrayMap; import android.util.Log; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; /** @@ -153,7 +153,7 @@ public class ContactMatcher { return sMaxScore[index]; } - private final HashMap mScores = new HashMap(); + private final ArrayMap mScores = new ArrayMap<>(); private final ArrayList mScoreList = new ArrayList(); private int mScoreCount = 0; diff --git a/src/com/android/providers/contacts/aggregation/util/RawContactMatcher.java b/src/com/android/providers/contacts/aggregation/util/RawContactMatcher.java index f39ae96c..b483ba83 100644 --- a/src/com/android/providers/contacts/aggregation/util/RawContactMatcher.java +++ b/src/com/android/providers/contacts/aggregation/util/RawContactMatcher.java @@ -15,13 +15,13 @@ */ package com.android.providers.contacts.aggregation.util; +import android.util.ArrayMap; import android.util.Log; import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType; import com.android.providers.contacts.util.Hex; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; /** @@ -158,7 +158,7 @@ public class RawContactMatcher { return sMaxScore[index]; } - private final HashMap mScores = new HashMap(); + private final ArrayMap mScores = new ArrayMap<>(); private final ArrayList mScoreList = new ArrayList(); private int mScoreCount = 0; diff --git a/src/com/android/providers/contacts/aggregation/util/RawContactMatchingCandidates.java b/src/com/android/providers/contacts/aggregation/util/RawContactMatchingCandidates.java index 917c810c..408e7258 100644 --- a/src/com/android/providers/contacts/aggregation/util/RawContactMatchingCandidates.java +++ b/src/com/android/providers/contacts/aggregation/util/RawContactMatchingCandidates.java @@ -17,14 +17,15 @@ package com.android.providers.contacts.aggregation.util; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static com.android.internal.util.Preconditions.checkNotNull; +import android.util.ArrayMap; +import android.util.ArraySet; + /** * Matching candidates for a raw contact, used in the contact aggregator. */ @@ -89,7 +90,7 @@ public class RawContactMatchingCandidates { } private void createRawContactToContactMap() { - mRawContactToContact = new HashMap(); + mRawContactToContact = new ArrayMap<>(); for (int i = 0; i < mBestMatches.size(); i++) { mRawContactToContact.put(mBestMatches.get(i).getRawContactId(), mBestMatches.get(i).getContactId()); @@ -97,7 +98,7 @@ public class RawContactMatchingCandidates { } private void createRawContactToAccountMap() { - mRawContactToAccount = new HashMap(); + mRawContactToAccount = new ArrayMap<>(); for (int i = 0; i < mBestMatches.size(); i++) { mRawContactToAccount.put(mBestMatches.get(i).getRawContactId(), mBestMatches.get(i).getAccountId()); @@ -105,7 +106,7 @@ public class RawContactMatchingCandidates { } private void createRawContactIdSet() { - mRawContactIds = new HashSet(); + mRawContactIds = new ArraySet<>(); for (int i = 0; i < mBestMatches.size(); i++) { mRawContactIds.add(mBestMatches.get(i).getRawContactId()); } diff --git a/src/com/android/providers/contacts/util/DbQueryUtils.java b/src/com/android/providers/contacts/util/DbQueryUtils.java index 23c144ac..458db61c 100644 --- a/src/com/android/providers/contacts/util/DbQueryUtils.java +++ b/src/com/android/providers/contacts/util/DbQueryUtils.java @@ -19,7 +19,7 @@ import android.content.ContentValues; import android.database.DatabaseUtils; import android.text.TextUtils; -import java.util.HashMap; +import java.util.Map; import java.util.Set; /** @@ -88,13 +88,13 @@ public class DbQueryUtils { * @throws IllegalArgumentException if any value in values is not found in * the projection map. */ - public static void checkForSupportedColumns(HashMap projectionMap, + public static void checkForSupportedColumns(Map projectionMap, ContentValues values) { checkForSupportedColumns(projectionMap.keySet(), values, "Is invalid."); } /** - * @see #checkForSupportedColumns(HashMap, ContentValues) + * @see #checkForSupportedColumns(Map, ContentValues) */ public static void checkForSupportedColumns(Set allowedColumns, ContentValues values, String msgSuffix) { diff --git a/tests/src/com/android/providers/contacts/aggregation/ContactAggregator2Test.java b/tests/src/com/android/providers/contacts/aggregation/ContactAggregator2Test.java index 9839f8e7..927b215c 100644 --- a/tests/src/com/android/providers/contacts/aggregation/ContactAggregator2Test.java +++ b/tests/src/com/android/providers/contacts/aggregation/ContactAggregator2Test.java @@ -17,6 +17,7 @@ package com.android.providers.contacts.aggregation; import android.accounts.Account; +import android.app.ActivityManager; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentUris; @@ -412,7 +413,12 @@ public class ContactAggregator2Test extends BaseContactsProvider2Test { long rawContactId2 = RawContactUtil.createRawContact(mResolver, ACCOUNT_2); DataUtil.insertStructuredName(mResolver, rawContactId2, "William", "Gore"); - assertAggregated(rawContactId1, rawContactId2, "William Gore"); + if (ActivityManager.isLowRamDeviceStatic()) { + // No common nickname DB on lowram devices. + assertNotAggregated(rawContactId1, rawContactId2); + } else { + assertAggregated(rawContactId1, rawContactId2, "William Gore"); + } } public void testAggregationByCommonNicknameOnly() { @@ -422,7 +428,12 @@ public class ContactAggregator2Test extends BaseContactsProvider2Test { long rawContactId2 = RawContactUtil.createRawContact(mResolver, ACCOUNT_2); DataUtil.insertStructuredName(mResolver, rawContactId2, "Larry", null); - assertAggregated(rawContactId1, rawContactId2, "Lawrence"); + if (ActivityManager.isLowRamDeviceStatic()) { + // No common nickname DB on lowram devices. + assertNotAggregated(rawContactId1, rawContactId2); + } else { + assertAggregated(rawContactId1, rawContactId2, "Lawrence"); + } } public void testAggregationByNicknameNoStructuredNameWithinSameAccount() { diff --git a/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java b/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java index 3b59cdb8..fb4f930a 100644 --- a/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java +++ b/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java @@ -17,6 +17,7 @@ package com.android.providers.contacts.aggregation; import android.accounts.Account; +import android.app.ActivityManager; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentUris; @@ -396,7 +397,13 @@ public class ContactAggregatorTest extends BaseContactsProvider2Test { long rawContactId2 = RawContactUtil.createRawContact(mResolver, ACCOUNT_2); DataUtil.insertStructuredName(mResolver, rawContactId2, "William", "Gore"); - assertAggregated(rawContactId1, rawContactId2, "William Gore"); + + if (ActivityManager.isLowRamDeviceStatic()) { + // No common nickname DB on lowram devices. + assertNotAggregated(rawContactId1, rawContactId2); + } else { + assertAggregated(rawContactId1, rawContactId2, "William Gore"); + } } public void testAggregationByCommonNicknameOnly() { @@ -406,7 +413,12 @@ public class ContactAggregatorTest extends BaseContactsProvider2Test { long rawContactId2 = RawContactUtil.createRawContact(mResolver, ACCOUNT_2); DataUtil.insertStructuredName(mResolver, rawContactId2, "Larry", null); - assertAggregated(rawContactId1, rawContactId2, "Lawrence"); + if (ActivityManager.isLowRamDeviceStatic()) { + // No common nickname DB on lowram devices. + assertNotAggregated(rawContactId1, rawContactId2); + } else { + assertAggregated(rawContactId1, rawContactId2, "Lawrence"); + } } public void testAggregationByNicknameNoStructuredName() { -- cgit v1.2.3 From bbd7b2f2fe43fb8562670cd70d99a069f9c8eb07 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Fri, 7 Jul 2017 01:16:46 -0700 Subject: Import translations. DO NOT MERGE Change-Id: Ibc8680bc418d5d6baa32a0c2f091f7945e052dde Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- res/values-bs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index c23e9ef4..04a0b74d 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -28,7 +28,7 @@ "Kopiraj bazu podataka kontakata" "Upravo ćete 1) napraviti kopiju svoje baze podataka koja sadrži sve informacije o kontaktima i sve popise poziva u unutrašnjoj pohrani i 2) poslati tu kopiju e-poštom. Ne zaboravite izbrisati kopiju čim je uspješno kopirate s uređaja ili čim primite poruku e-pošte." "Izbriši sada" - "Počni" + "Započni" "Izaberite program za slanje fajla" "Baza podataka kontakata je u prilogu" "U prilogu je moja baza podataka kontakata sa svim informacijama o kontaktima. Rukujte oprezno." -- cgit v1.2.3