diff options
author | 2018-12-07 15:16:08 -0700 | |
---|---|---|
committer | 2018-12-08 11:35:52 -0700 | |
commit | 844989ead3947133ec0854bd16e67b461bb122a0 (patch) | |
tree | 328d26072223f7b8d5f2c23b710273cb4f3c6a39 | |
parent | dc0d44176d23c7ed24e9cb38ce6886bf02a9bd6d (diff) |
Make DocumentsContract methods more general.
Accepting only ContentResolver arguments was quite limiting, so use
the newly created super-interface ContentInterface, which lets
callers use a ContentResolver, and ContentProviderClient, or even a
specific ContentProvider.
This is a safe API change, since we're accepting a more-general
argument, and existing API users can continue passing ContentResolver
to these methods.
Bug: 117635768
Test: atest DocumentsUITests
Test: atest android.appsecurity.cts.DocumentsTest
Change-Id: I109af667d9bdabe4bf78fb35fa61dee6c429ed47
8 files changed, 28 insertions, 66 deletions
diff --git a/src/com/android/documentsui/DocumentsAccess.java b/src/com/android/documentsui/DocumentsAccess.java index ea62d935a..a0f3b2ddd 100644 --- a/src/com/android/documentsui/DocumentsAccess.java +++ b/src/com/android/documentsui/DocumentsAccess.java @@ -47,7 +47,7 @@ public interface DocumentsAccess { @Nullable DocumentInfo getArchiveDocument(Uri uri); boolean isDocumentUri(Uri uri); - @Nullable Path findDocumentPath(Uri uri) throws RemoteException; + @Nullable Path findDocumentPath(Uri uri) throws RemoteException, FileNotFoundException; List<DocumentInfo> getDocuments(String authority, List<String> docIds) throws RemoteException; @@ -120,7 +120,7 @@ public interface DocumentsAccess { } @Override - public Path findDocumentPath(Uri docUri) throws RemoteException { + public Path findDocumentPath(Uri docUri) throws RemoteException, FileNotFoundException { final ContentResolver resolver = mContext.getContentResolver(); try (final ContentProviderClient client = DocumentsApplication .acquireUnstableProviderOrThrow(resolver, docUri.getAuthority())) { diff --git a/src/com/android/documentsui/Metrics.java b/src/com/android/documentsui/Metrics.java index 838ebf8b7..4ce3697a8 100644 --- a/src/com/android/documentsui/Metrics.java +++ b/src/com/android/documentsui/Metrics.java @@ -43,6 +43,7 @@ import com.android.documentsui.services.FileOperationService; import com.android.documentsui.services.FileOperationService.OpType; import com.android.internal.logging.MetricsLogger; +import java.io.FileNotFoundException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; @@ -709,7 +710,7 @@ public final class Metrics { final RootInfo root = providers.getRootOneshot( Providers.AUTHORITY_STORAGE, path.getRootId()); isInternal = !root.supportsEject(); - } catch (RemoteException | RuntimeException e) { + } catch (FileNotFoundException | RemoteException | RuntimeException e) { Log.e(TAG, "Failed to obtain its root info. Log the metrics as internal.", e); // It's not very likely to have an external storage so log it as internal. isInternal = true; diff --git a/src/com/android/documentsui/services/CopyJob.java b/src/com/android/documentsui/services/CopyJob.java index 013a73d70..5761fed83 100644 --- a/src/com/android/documentsui/services/CopyJob.java +++ b/src/com/android/documentsui/services/CopyJob.java @@ -327,7 +327,7 @@ class CopyJob extends ResolvedResourcesJob { appContext, operationType, Metrics.OPMODE_PROVIDER); return; } - } catch (RemoteException | RuntimeException e) { + } catch (FileNotFoundException | RemoteException | RuntimeException e) { Log.e(TAG, "Provider side copy failed for: " + src.derivedUri + " due to an exception.", e); Metrics.logFileOperationFailure( @@ -390,7 +390,7 @@ class CopyJob extends ResolvedResourcesJob { try { dstUri = DocumentsContract.createDocument( getClient(dest), dest.derivedUri, dstMimeType, dstDisplayName); - } catch (RemoteException | RuntimeException e) { + } catch (FileNotFoundException | RemoteException | RuntimeException e) { Metrics.logFileOperationFailure( appContext, Metrics.SUBFILEOP_CREATE_DOCUMENT, dest.derivedUri); throw new ResourceException( @@ -783,7 +783,7 @@ class CopyJob extends ResolvedResourcesJob { if (parent.isDirectory() && doc.authority.equals(parent.authority)) { try { return isChildDocument(getClient(doc), doc.derivedUri, parent.derivedUri); - } catch (RemoteException | RuntimeException e) { + } catch (FileNotFoundException | RemoteException | RuntimeException e) { throw new ResourceException( "Failed to check if %s is a child of %s due to an exception.", doc.derivedUri, parent.derivedUri, e); diff --git a/src/com/android/documentsui/services/Job.java b/src/com/android/documentsui/services/Job.java index e50d50b0a..cc5208ec7 100644 --- a/src/com/android/documentsui/services/Job.java +++ b/src/com/android/documentsui/services/Job.java @@ -53,6 +53,7 @@ import com.android.documentsui.clipping.UrisSupplier; import com.android.documentsui.files.FilesActivity; import com.android.documentsui.services.FileOperationService.OpType; +import java.io.FileNotFoundException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -264,7 +265,7 @@ abstract public class Job implements Runnable { throw new ResourceException("Unable to delete source document. " + "File is not deletable or removable: %s.", doc.derivedUri); } - } catch (RemoteException | RuntimeException e) { + } catch (FileNotFoundException | RemoteException | RuntimeException e) { throw new ResourceException("Failed to delete file %s due to an exception.", doc.derivedUri, e); } diff --git a/src/com/android/documentsui/services/MoveJob.java b/src/com/android/documentsui/services/MoveJob.java index c46f39bc4..10185e23a 100644 --- a/src/com/android/documentsui/services/MoveJob.java +++ b/src/com/android/documentsui/services/MoveJob.java @@ -153,7 +153,7 @@ final class MoveJob extends CopyJob { appContext, operationType, Metrics.OPMODE_PROVIDER); return; } - } catch (RemoteException | RuntimeException e) { + } catch (FileNotFoundException | RemoteException | RuntimeException e) { Metrics.logFileOperationFailure( appContext, Metrics.SUBFILEOP_QUICK_MOVE, src.derivedUri); Log.e(TAG, "Provider side move failed for: " + src.derivedUri diff --git a/tests/common/com/android/documentsui/DocumentsProviderHelper.java b/tests/common/com/android/documentsui/DocumentsProviderHelper.java index 123f4fb15..fdc71888c 100644 --- a/tests/common/com/android/documentsui/DocumentsProviderHelper.java +++ b/tests/common/com/android/documentsui/DocumentsProviderHelper.java @@ -49,6 +49,7 @@ import libcore.io.Streams; import com.google.common.collect.Lists; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -93,7 +94,7 @@ public class DocumentsProviderHelper { try { Uri uri = DocumentsContract.createDocument(mClient, parentUri, mimeType, name); return uri; - } catch (RemoteException e) { + } catch (FileNotFoundException e) { throw new RuntimeException("Couldn't create document: " + name + " with mimetype " + mimeType, e); } diff --git a/tests/common/com/android/documentsui/bots/NotificationsBot.java b/tests/common/com/android/documentsui/bots/NotificationsBot.java index 500b6304e..7a4c5496b 100644 --- a/tests/common/com/android/documentsui/bots/NotificationsBot.java +++ b/tests/common/com/android/documentsui/bots/NotificationsBot.java @@ -17,74 +17,32 @@ package com.android.documentsui.bots; import android.app.Activity; -import android.content.ContentResolver; +import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager.NameNotFoundException; -import android.provider.Settings; -import android.support.test.InstrumentationRegistry; import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiSelector; -import android.text.TextUtils; -import android.view.KeyEvent; + +import com.android.documentsui.services.TestNotificationService; + +import java.io.IOException; /** * A test helper class for controlling notification items. */ public class NotificationsBot extends Bots.BaseBot { - private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; - private static final String allow_res_name = "allow"; - private static final String turn_off_res_name = "notification_listener_disable_warning_confirm"; + private final ComponentName mComponent; public NotificationsBot(UiDevice device, Context context, int timeout) { super(device, context, timeout); + mComponent = new ComponentName(context, TestNotificationService.class); } - public void setNotificationAccess(Activity activity, boolean enabled) - throws UiObjectNotFoundException, NameNotFoundException { - Context testContext = InstrumentationRegistry.getContext(); - - if(isNotificationAccessEnabled( - mContext.getContentResolver(), testContext.getPackageName()) == enabled) { - return; - } - - Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS); - activity.startActivity(intent); - mDevice.waitForIdle(); - - String appName = testContext.getPackageManager().getApplicationLabel( - testContext.getApplicationInfo()).toString(); - clickLabel(appName); - - Context settings_context = mContext.createPackageContext(SETTINGS_PACKAGE_NAME, - Context.CONTEXT_RESTRICTED); - String label_res_name = enabled ? allow_res_name : turn_off_res_name; - int res_id = settings_context.getResources().getIdentifier(label_res_name, - "string", SETTINGS_PACKAGE_NAME); - - clickLabel(settings_context.getResources().getString(res_id)); - mDevice.pressKeyCode(KeyEvent.KEYCODE_BACK); - mDevice.waitForIdle(); - } - - private boolean isNotificationAccessEnabled(ContentResolver resolver, String pkgName) { - String listeners = Settings.Secure.getString(resolver, "enabled_notification_listeners"); - if (!TextUtils.isEmpty(listeners)) { - String[] list = listeners.split(":"); - for(String item : list) { - if(item.startsWith(pkgName)) { - return true; - } - } + public void setNotificationAccess(Activity activity, boolean enabled) throws IOException { + if (enabled) { + mDevice.executeShellCommand( + "cmd notification allow_listener " + mComponent.flattenToString()); + } else { + mDevice.executeShellCommand( + "cmd notification disallow_listener " + mComponent.flattenToString()); } - return false; - } - - private void clickLabel(String label) throws UiObjectNotFoundException { - UiSelector selector = new UiSelector().textMatches("(?i)" + label); - mDevice.findObject(selector).click(); - mDevice.waitForIdle(); } } diff --git a/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java b/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java index cc40e56e8..cd7bda299 100644 --- a/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java +++ b/tests/unit/com/android/documentsui/archives/ArchivesProviderTest.java @@ -44,6 +44,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.io.FileNotFoundException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -266,7 +267,7 @@ public class ArchivesProviderTest { } @Test - public void testGetDocumentMetadata() throws InterruptedException, RemoteException { + public void testGetDocumentMetadata() throws Exception { final Uri sourceUri = DocumentsContract.buildDocumentUri( ResourcesProvider.AUTHORITY, "images.zip"); final Uri archiveUri = ArchivesProvider.buildUriForArchive(sourceUri, |