Merge "Revert ""Rollback" mimetype cache""
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index 32928ba..f451b2c 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -18,6 +18,7 @@
import com.android.common.content.SyncStateContentProviderHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.util.NeededForTesting;
import com.google.android.collect.Sets;
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 6de16df..7473718 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -48,6 +48,7 @@
import com.android.providers.contacts.SearchIndexManager.FtsQueryBuilder;
import com.android.providers.contacts.aggregation.ContactAggregator;
import com.android.providers.contacts.aggregation.ContactAggregator.AggregationSuggestionParameter;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.aggregation.ProfileAggregator;
import com.android.providers.contacts.util.DbQueryUtils;
import com.android.providers.contacts.util.NeededForTesting;
@@ -57,6 +58,7 @@
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -5253,9 +5255,8 @@
}
case STREAM_ITEMS_LIMIT: {
- MatrixCursor cursor = new MatrixCursor(new String[]{StreamItems.MAX_ITEMS}, 1);
- cursor.addRow(new Object[]{MAX_STREAM_ITEMS_PER_RAW_CONTACT});
- return cursor;
+ return buildSingleRowResult(projection, new String[] {StreamItems.MAX_ITEMS},
+ new Object[] {MAX_STREAM_ITEMS_PER_RAW_CONTACT});
}
case STREAM_ITEMS_PHOTOS: {
@@ -5283,11 +5284,9 @@
}
case PHOTO_DIMENSIONS: {
- MatrixCursor cursor = new MatrixCursor(
- new String[]{DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM},
- 1);
- cursor.addRow(new Object[]{mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim});
- return cursor;
+ return buildSingleRowResult(projection,
+ new String[] {DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM},
+ new Object[] {mMaxDisplayPhotoDim, mMaxThumbnailPhotoDim});
}
case PHONES:
@@ -5848,7 +5847,9 @@
}
case PROVIDER_STATUS: {
- return queryProviderStatus(uri, projection);
+ return buildSingleRowResult(projection,
+ new String[] {ProviderStatus.STATUS, ProviderStatus.DATA1},
+ new Object[] {mProviderStatus, mEstimatedStorageRequirement});
}
case DIRECTORIES : {
@@ -5908,21 +5909,6 @@
return c;
}
- /**
- * Creates a single-row cursor containing the current status of the provider.
- */
- private Cursor queryProviderStatus(Uri uri, String[] projection) {
- MatrixCursor cursor = new MatrixCursor(projection);
- RowBuilder row = cursor.newRow();
- for (int i = 0; i < projection.length; i++) {
- if (ProviderStatus.STATUS.equals(projection[i])) {
- row.add(mProviderStatus);
- } else if (ProviderStatus.DATA1.equals(projection[i])) {
- row.add(mEstimatedStorageRequirement);
- }
- }
- return cursor;
- }
/**
* Runs the query with the supplied contact ID and lookup ID. If the query succeeds,
@@ -8131,6 +8117,39 @@
}
/**
+ * Create a single row cursor for a simple, informational queries, such as
+ * {@link ProviderStatus#CONTENT_URI}.
+ */
+ @VisibleForTesting
+ static Cursor buildSingleRowResult(String[] projection, String[] availableColumns,
+ Object[] data) {
+ Preconditions.checkArgument(availableColumns.length == data.length);
+ if (projection == null) {
+ projection = availableColumns;
+ }
+ final MatrixCursor c = new MatrixCursor(projection, 1);
+ final RowBuilder row = c.newRow();
+
+ // It's O(n^2), but it's okay because we only have a few columns.
+ for (int i = 0; i < c.getColumnCount(); i++) {
+ final String column = c.getColumnName(i);
+
+ boolean found = false;
+ for (int j = 0; j < availableColumns.length; j++) {
+ if (availableColumns[j].equals(column)) {
+ row.add(data[j]);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ throw new IllegalArgumentException("Invalid column " + projection[i]);
+ }
+ }
+ return c;
+ }
+
+ /**
* @return the currently active {@link ContactsDatabaseHelper} for the current thread.
*/
@NeededForTesting
diff --git a/src/com/android/providers/contacts/NameNormalizer.java b/src/com/android/providers/contacts/NameNormalizer.java
index 2ac3865..d91bd7c 100644
--- a/src/com/android/providers/contacts/NameNormalizer.java
+++ b/src/com/android/providers/contacts/NameNormalizer.java
@@ -15,6 +15,8 @@
*/
package com.android.providers.contacts;
+import com.android.providers.contacts.util.Hex;
+
import java.util.Locale;
import java.text.Collator;
import java.text.CollationKey;
diff --git a/src/com/android/providers/contacts/PhotoProcessor.java b/src/com/android/providers/contacts/PhotoProcessor.java
index de6e93a..d2a33d2 100644
--- a/src/com/android/providers/contacts/PhotoProcessor.java
+++ b/src/com/android/providers/contacts/PhotoProcessor.java
@@ -134,10 +134,10 @@
}
}
float scaleFactor = ((float) maxDim) / Math.max(width, height);
- if (scaleFactor < 1.0 || cropLeft != 0 || cropTop != 0) {
+ if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0) {
// Need to scale or crop the photo.
Matrix matrix = new Matrix();
- matrix.setScale(scaleFactor, scaleFactor);
+ if (scaleFactor < 1.0f) matrix.setScale(scaleFactor, scaleFactor);
scaledBitmap = Bitmap.createBitmap(
mOriginal, cropLeft, cropTop, width, height, matrix, false);
}
diff --git a/src/com/android/providers/contacts/aggregation/ContactAggregator.java b/src/com/android/providers/contacts/aggregation/ContactAggregator.java
index a235ce2..60eba95 100644
--- a/src/com/android/providers/contacts/aggregation/ContactAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ContactAggregator.java
@@ -16,10 +16,7 @@
package com.android.providers.contacts.aggregation;
-import com.android.providers.contacts.CommonNicknameCache;
import com.android.providers.contacts.ContactLookupKey;
-import com.android.providers.contacts.ContactMatcher;
-import com.android.providers.contacts.ContactMatcher.MatchScore;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns;
@@ -33,6 +30,9 @@
import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.ContactsDatabaseHelper.Views;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
+import com.android.providers.contacts.aggregation.util.ContactMatcher;
+import com.android.providers.contacts.aggregation.util.ContactMatcher.MatchScore;
import com.android.providers.contacts.ContactsProvider2;
import com.android.providers.contacts.NameLookupBuilder;
import com.android.providers.contacts.NameNormalizer;
diff --git a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
index 6126184..fedf5fe 100644
--- a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
@@ -20,10 +20,10 @@
import android.database.sqlite.SQLiteStatement;
import android.provider.ContactsContract.Contacts;
-import com.android.providers.contacts.CommonNicknameCache;
import com.android.providers.contacts.ContactLookupKey;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.ContactsProvider2;
import com.android.providers.contacts.NameSplitter;
import com.android.providers.contacts.PhotoPriorityResolver;
diff --git a/src/com/android/providers/contacts/CommonNicknameCache.java b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
similarity index 98%
rename from src/com/android/providers/contacts/CommonNicknameCache.java
rename to src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
index e1dfae3..d6b799f 100644
--- a/src/com/android/providers/contacts/CommonNicknameCache.java
+++ b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package com.android.providers.contacts;
+package com.android.providers.contacts.aggregation.util;
import com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
diff --git a/src/com/android/providers/contacts/ContactMatcher.java b/src/com/android/providers/contacts/aggregation/util/ContactMatcher.java
similarity index 99%
rename from src/com/android/providers/contacts/ContactMatcher.java
rename to src/com/android/providers/contacts/aggregation/util/ContactMatcher.java
index e8f4aa5..60e41ab 100644
--- a/src/com/android/providers/contacts/ContactMatcher.java
+++ b/src/com/android/providers/contacts/aggregation/util/ContactMatcher.java
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License
*/
-package com.android.providers.contacts;
+package com.android.providers.contacts.aggregation.util;
import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
+import com.android.providers.contacts.util.Hex;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/providers/contacts/NameDistance.java b/src/com/android/providers/contacts/aggregation/util/NameDistance.java
similarity index 98%
rename from src/com/android/providers/contacts/NameDistance.java
rename to src/com/android/providers/contacts/aggregation/util/NameDistance.java
index d685ba8..e357ec1 100644
--- a/src/com/android/providers/contacts/NameDistance.java
+++ b/src/com/android/providers/contacts/aggregation/util/NameDistance.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License
*/
-package com.android.providers.contacts;
+package com.android.providers.contacts.aggregation.util;
import java.util.Arrays;
diff --git a/src/com/android/providers/contacts/Hex.java b/src/com/android/providers/contacts/util/Hex.java
similarity index 98%
rename from src/com/android/providers/contacts/Hex.java
rename to src/com/android/providers/contacts/util/Hex.java
index 090764a..ad26f4b 100644
--- a/src/com/android/providers/contacts/Hex.java
+++ b/src/com/android/providers/contacts/util/Hex.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License
*/
-package com.android.providers.contacts;
+package com.android.providers.contacts.util;
/**
* Basic hex operations: from byte array to string and vice versa.
diff --git a/tests/res/drawable/earth_300x200.jpg b/tests/res/drawable/earth_300x200.jpg
new file mode 100644
index 0000000..d8446de
--- /dev/null
+++ b/tests/res/drawable/earth_300x200.jpg
Binary files differ
diff --git a/tests/res/drawable/earth_600x400.jpg b/tests/res/drawable/earth_600x400.jpg
new file mode 100644
index 0000000..b5f42fd
--- /dev/null
+++ b/tests/res/drawable/earth_600x400.jpg
Binary files differ
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index b3b3c28..45c360e 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -18,6 +18,7 @@
import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
+import com.android.providers.contacts.util.Hex;
import com.google.android.collect.Sets;
import android.accounts.Account;
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index bef077c..c7f7dcb 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -6393,6 +6393,53 @@
cursor.close();
}
+ public void testBuildSingleRowResult() {
+ checkBuildSingleRowResult(
+ new String[] {"b"},
+ new String[] {"a", "b"},
+ new Integer[] {1, 2},
+ new Integer[] {2}
+ );
+
+ checkBuildSingleRowResult(
+ new String[] {"b", "a", "b"},
+ new String[] {"a", "b"},
+ new Integer[] {1, 2},
+ new Integer[] {2, 1, 2}
+ );
+
+ checkBuildSingleRowResult(
+ null, // all columns
+ new String[] {"a", "b"},
+ new Integer[] {1, 2},
+ new Integer[] {1, 2}
+ );
+
+ try {
+ // Access non-existent column
+ ContactsProvider2.buildSingleRowResult(new String[] {"a"}, new String[] {"b"},
+ new Object[] {1});
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ private void checkBuildSingleRowResult(String[] projection, String[] availableColumns,
+ Object[] data, Integer[] expectedValues) {
+ final Cursor c = ContactsProvider2.buildSingleRowResult(projection, availableColumns, data);
+ try {
+ assertTrue(c.moveToFirst());
+ assertEquals(1, c.getCount());
+ assertEquals(expectedValues.length, c.getColumnCount());
+
+ for (int i = 0; i < expectedValues.length; i++) {
+ assertEquals("column " + i, expectedValues[i], (Integer) c.getInt(i));
+ }
+ } finally {
+ c.close();
+ }
+ }
+
private Cursor queryGroupMemberships(Account account) {
Cursor c = mResolver.query(maybeAddAccountQueryParameters(Data.CONTENT_URI, account),
new String[]{GroupMembership.GROUP_ROW_ID, GroupMembership.RAW_CONTACT_ID},
diff --git a/tests/src/com/android/providers/contacts/PhotoStoreTest.java b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
index 5f9809b..02b3568 100644
--- a/tests/src/com/android/providers/contacts/PhotoStoreTest.java
+++ b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
@@ -18,6 +18,7 @@
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.tests.R;
+import com.android.providers.contacts.util.Hex;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -74,19 +75,36 @@
public void testStore200Photo() throws IOException {
// As 200 is below the full photo size, we don't want to see it upscaled
- runStorageTestForResource(R.drawable.earth_200, 200);
+ runStorageTestForResource(R.drawable.earth_200, 200, 200);
+ }
+
+ public void testStoreNonSquare300x200Photo() throws IOException {
+ // The longer side should be downscaled to the target size
+ runStorageTestForResource(R.drawable.earth_300x200, 256, 171);
+ }
+
+ public void testStoreNonSquare300x200PhotoWithCrop() throws IOException {
+ // As 300x200 is below the full photo size, we don't want to see it upscaled
+ // This one is not square, so we expect the longer side to be cropped
+ runStorageTestForResourceWithCrop(R.drawable.earth_300x200, 200, 200);
+ }
+
+ public void testStoreNonSquare600x400PhotoWithCrop() throws IOException {
+ // As 600x400 is above the full photo size, we expect the picture to be cropped and then
+ // scaled
+ runStorageTestForResourceWithCrop(R.drawable.earth_600x400, 256, 256);
}
public void testStoreMediumPhoto() throws IOException {
- runStorageTestForResource(R.drawable.earth_normal, 256);
+ runStorageTestForResource(R.drawable.earth_normal, 256, 256);
}
public void testStoreLargePhoto() throws IOException {
- runStorageTestForResource(R.drawable.earth_large, 256);
+ runStorageTestForResource(R.drawable.earth_large, 256, 256);
}
public void testStoreHugePhoto() throws IOException {
- runStorageTestForResource(R.drawable.earth_huge, 256);
+ runStorageTestForResource(R.drawable.earth_huge, 256, 256);
}
/**
@@ -104,7 +122,8 @@
* the size of the photo.
* @param resourceId The resource ID of the photo file to test.
*/
- public void runStorageTestForResource(int resourceId, int expectedSize) throws IOException {
+ public void runStorageTestForResource(int resourceId, int expectedWidth,
+ int expectedHeight) throws IOException {
byte[] photo = loadPhotoFromResource(resourceId, PhotoSize.ORIGINAL);
long photoFileId = mPhotoStore.insert(new PhotoProcessor(photo, 256, 96));
assertTrue(photoFileId != 0);
@@ -117,13 +136,12 @@
Hex.encodeHex(storedVersion, false));
Cursor c = mDb.query(Tables.PHOTO_FILES,
- new String[]{PhotoFiles.HEIGHT, PhotoFiles.WIDTH, PhotoFiles.FILESIZE},
+ new String[]{PhotoFiles.WIDTH, PhotoFiles.HEIGHT, PhotoFiles.FILESIZE},
PhotoFiles._ID + "=?", new String[]{String.valueOf(photoFileId)}, null, null, null);
try {
assertEquals(1, c.getCount());
c.moveToFirst();
- assertEquals(expectedSize, c.getInt(0));
- assertEquals(expectedSize, c.getInt(1));
+ assertEquals(expectedWidth + "/" + expectedHeight, c.getInt(0) + "/" + c.getInt(1));
assertEquals(expectedStoredVersion.length, c.getInt(2));
} finally {
c.close();
@@ -132,6 +150,24 @@
assertEquals(expectedStoredVersion.length, mPhotoStore.getTotalSize());
}
+ public void runStorageTestForResourceWithCrop(int resourceId, int expectedWidth,
+ int expectedHeight) throws IOException {
+ byte[] photo = loadPhotoFromResource(resourceId, PhotoSize.ORIGINAL);
+ long photoFileId = mPhotoStore.insert(new PhotoProcessor(photo, 256, 96, true));
+ assertTrue(photoFileId != 0);
+
+ Cursor c = mDb.query(Tables.PHOTO_FILES,
+ new String[]{PhotoFiles.HEIGHT, PhotoFiles.WIDTH, PhotoFiles.FILESIZE},
+ PhotoFiles._ID + "=?", new String[]{String.valueOf(photoFileId)}, null, null, null);
+ try {
+ assertEquals(1, c.getCount());
+ c.moveToFirst();
+ assertEquals(expectedWidth + "/" + expectedHeight, c.getInt(0) + "/" + c.getInt(1));
+ } finally {
+ c.close();
+ }
+ }
+
public void testRemoveEntry() throws IOException {
byte[] photo = loadPhotoFromResource(R.drawable.earth_normal, PhotoSize.ORIGINAL);
long photoFileId = mPhotoStore.insert(new PhotoProcessor(photo, 256, 96));
diff --git a/tests/src/com/android/providers/contacts/NameDistanceTest.java b/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
similarity index 90%
rename from tests/src/com/android/providers/contacts/NameDistanceTest.java
rename to tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
index 45d5eda..7f9f053 100644
--- a/tests/src/com/android/providers/contacts/NameDistanceTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
@@ -14,7 +14,11 @@
* limitations under the License
*/
-package com.android.providers.contacts;
+package com.android.providers.contacts.aggregation.util;
+
+import com.android.providers.contacts.NameNormalizer;
+import com.android.providers.contacts.aggregation.util.NameDistance;
+import com.android.providers.contacts.util.Hex;
import android.test.suitebuilder.annotation.SmallTest;