Loading core/java/com/android/internal/app/ChooserActivity.java +28 −15 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.OpenableColumns; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; Loading Loading @@ -620,28 +621,40 @@ public class ChooserActivity extends ResolverActivity { } } /** * Wrapping the ContentResolver call to expose for easier mocking, * and to avoid mocking Android core classes. */ @VisibleForTesting public Cursor queryResolver(ContentResolver resolver, Uri uri) { return resolver.query(uri, null, null, null, null); } private FileInfo extractFileInfo(Uri uri, ContentResolver resolver) { String fileName = null; boolean hasThumbnail = false; Cursor cursor = null; try { cursor = resolver.query(uri, null, null, null, null); } catch (SecurityException e) { Log.w(TAG, "Error loading file preview", e); } try (Cursor cursor = queryResolver(resolver, uri)) { if (cursor != null && cursor.getCount() > 0) { int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); int titleIndex = cursor.getColumnIndex(Downloads.Impl.COLUMN_TITLE); int flagsIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS); cursor.moveToFirst(); if (nameIndex != -1) { fileName = cursor.getString(nameIndex); } else if (titleIndex != -1) { fileName = cursor.getString(titleIndex); } if (flagsIndex != -1) { hasThumbnail = (cursor.getInt(flagsIndex) & DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL) != 0; } } } catch (SecurityException e) { Log.w(TAG, "Error loading file preview", e); } if (TextUtils.isEmpty(fileName)) { fileName = uri.getPath(); Loading core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +55 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -41,6 +42,7 @@ import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; Loading Loading @@ -651,6 +653,59 @@ public class ChooserActivityTest { onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } @Test public void contentProviderThrowSecurityException() throws InterruptedException { Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf"); ArrayList<Uri> uris = new ArrayList<>(); uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); sOverrides.resolverForceException = true; mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed())); onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf"))); onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } @Test public void contentProviderReturnsNoColumns() throws InterruptedException { Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf"); ArrayList<Uri> uris = new ArrayList<>(); uris.add(uri); uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); Cursor cursor = mock(Cursor.class); when(cursor.getCount()).thenReturn(1); Mockito.doNothing().when(cursor).close(); when(cursor.moveToFirst()).thenReturn(true); when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1); sOverrides.resolverCursor = cursor; mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed())); onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file"))); onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } private Intent createSendTextIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); Loading core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +19 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,10 @@ package com.android.internal.app; import static org.mockito.Mockito.mock; import android.app.usage.UsageStatsManager; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.util.Size; Loading Loading @@ -97,6 +99,19 @@ public class ChooserWrapperActivity extends ChooserActivity { return sOverrides.metricsLogger; } @Override public Cursor queryResolver(ContentResolver resolver, Uri uri) { if (sOverrides.resolverCursor != null) { return sOverrides.resolverCursor; } if (sOverrides.resolverForceException) { throw new SecurityException("Test exception handling"); } return super.queryResolver(resolver, uri); } /** * We cannot directly mock the activity created since instrumentation creates it. * <p> Loading @@ -109,6 +124,8 @@ public class ChooserWrapperActivity extends ChooserActivity { public ResolverListController resolverListController; public Boolean isVoiceInteraction; public boolean isImageType; public Cursor resolverCursor; public boolean resolverForceException; public Bitmap previewThumbnail; public MetricsLogger metricsLogger; Loading @@ -118,6 +135,8 @@ public class ChooserWrapperActivity extends ChooserActivity { createPackageManager = null; previewThumbnail = null; isImageType = false; resolverCursor = null; resolverForceException = false; resolverListController = mock(ResolverListController.class); metricsLogger = mock(MetricsLogger.class); } Loading Loading
core/java/com/android/internal/app/ChooserActivity.java +28 −15 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.OpenableColumns; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; Loading Loading @@ -620,28 +621,40 @@ public class ChooserActivity extends ResolverActivity { } } /** * Wrapping the ContentResolver call to expose for easier mocking, * and to avoid mocking Android core classes. */ @VisibleForTesting public Cursor queryResolver(ContentResolver resolver, Uri uri) { return resolver.query(uri, null, null, null, null); } private FileInfo extractFileInfo(Uri uri, ContentResolver resolver) { String fileName = null; boolean hasThumbnail = false; Cursor cursor = null; try { cursor = resolver.query(uri, null, null, null, null); } catch (SecurityException e) { Log.w(TAG, "Error loading file preview", e); } try (Cursor cursor = queryResolver(resolver, uri)) { if (cursor != null && cursor.getCount() > 0) { int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); int titleIndex = cursor.getColumnIndex(Downloads.Impl.COLUMN_TITLE); int flagsIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS); cursor.moveToFirst(); if (nameIndex != -1) { fileName = cursor.getString(nameIndex); } else if (titleIndex != -1) { fileName = cursor.getString(titleIndex); } if (flagsIndex != -1) { hasThumbnail = (cursor.getInt(flagsIndex) & DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL) != 0; } } } catch (SecurityException e) { Log.w(TAG, "Error loading file preview", e); } if (TextUtils.isEmpty(fileName)) { fileName = uri.getPath(); Loading
core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +55 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -41,6 +42,7 @@ import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; Loading Loading @@ -651,6 +653,59 @@ public class ChooserActivityTest { onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } @Test public void contentProviderThrowSecurityException() throws InterruptedException { Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf"); ArrayList<Uri> uris = new ArrayList<>(); uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); sOverrides.resolverForceException = true; mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed())); onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf"))); onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } @Test public void contentProviderReturnsNoColumns() throws InterruptedException { Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf"); ArrayList<Uri> uris = new ArrayList<>(); uris.add(uri); uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); Cursor cursor = mock(Cursor.class); when(cursor.getCount()).thenReturn(1); Mockito.doNothing().when(cursor).close(); when(cursor.moveToFirst()).thenReturn(true); when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1); sOverrides.resolverCursor = cursor; mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed())); onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file"))); onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } private Intent createSendTextIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); Loading
core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +19 −0 Original line number Diff line number Diff line Loading @@ -19,8 +19,10 @@ package com.android.internal.app; import static org.mockito.Mockito.mock; import android.app.usage.UsageStatsManager; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.util.Size; Loading Loading @@ -97,6 +99,19 @@ public class ChooserWrapperActivity extends ChooserActivity { return sOverrides.metricsLogger; } @Override public Cursor queryResolver(ContentResolver resolver, Uri uri) { if (sOverrides.resolverCursor != null) { return sOverrides.resolverCursor; } if (sOverrides.resolverForceException) { throw new SecurityException("Test exception handling"); } return super.queryResolver(resolver, uri); } /** * We cannot directly mock the activity created since instrumentation creates it. * <p> Loading @@ -109,6 +124,8 @@ public class ChooserWrapperActivity extends ChooserActivity { public ResolverListController resolverListController; public Boolean isVoiceInteraction; public boolean isImageType; public Cursor resolverCursor; public boolean resolverForceException; public Bitmap previewThumbnail; public MetricsLogger metricsLogger; Loading @@ -118,6 +135,8 @@ public class ChooserWrapperActivity extends ChooserActivity { createPackageManager = null; previewThumbnail = null; isImageType = false; resolverCursor = null; resolverForceException = false; resolverListController = mock(ResolverListController.class); metricsLogger = mock(MetricsLogger.class); } Loading