Add cloud provider APIs to MediaStore
1. MediaStore#getCloudProvider
2. MediaStore#notifyCloudEvent
Test: m
Bug: 195008799
CTS-Coverage-Bug: 193668830
Change-Id: I5f44d2dee87335cea773bcd88222c626a109f9d0
diff --git a/apex/framework/api/current.txt b/apex/framework/api/current.txt
index 9d1fd44..6ac4dc1 100644
--- a/apex/framework/api/current.txt
+++ b/apex/framework/api/current.txt
@@ -68,6 +68,7 @@
method @NonNull public static android.app.PendingIntent createFavoriteRequest(@NonNull android.content.ContentResolver, @NonNull java.util.Collection<android.net.Uri>, boolean);
method @NonNull public static android.app.PendingIntent createTrashRequest(@NonNull android.content.ContentResolver, @NonNull java.util.Collection<android.net.Uri>, boolean);
method @NonNull public static android.app.PendingIntent createWriteRequest(@NonNull android.content.ContentResolver, @NonNull java.util.Collection<android.net.Uri>);
+ method @Nullable public static String getCloudProvider(@NonNull android.content.ContentResolver);
method @Nullable public static android.net.Uri getDocumentUri(@NonNull android.content.Context, @NonNull android.net.Uri);
method @NonNull public static java.util.Set<java.lang.String> getExternalVolumeNames(@NonNull android.content.Context);
method public static long getGeneration(@NonNull android.content.Context, @NonNull String);
@@ -83,6 +84,7 @@
method @NonNull public static String getVersion(@NonNull android.content.Context, @NonNull String);
method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
method public static boolean isCurrentSystemGallery(@NonNull android.content.ContentResolver, int, @NonNull String);
+ method public static boolean notifyCloudEvent(@NonNull android.content.ContentResolver);
method @Deprecated @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
field public static final String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
diff --git a/apex/framework/java/android/provider/MediaStore.java b/apex/framework/java/android/provider/MediaStore.java
index 00589e8..848ddbf 100644
--- a/apex/framework/java/android/provider/MediaStore.java
+++ b/apex/framework/java/android/provider/MediaStore.java
@@ -243,11 +243,17 @@
public static final String EXTRA_IS_SYSTEM_GALLERY_RESPONSE = "is_system_gallery_response";
/** {@hide} */
+ public static final String GET_CLOUD_PROVIDER_CALL = "get_cloud_provider";
+ /** {@hide} */
+ public static final String NOTIFY_CLOUD_EVENT_CALL = "notify_cloud_event";
+ /** {@hide} */
public static final String SYNC_PROVIDERS_CALL = "sync_providers";
/** {@hide} */
public static final String SET_CLOUD_PROVIDER_CALL = "set_cloud_provider";
/** {@hide} */
public static final String EXTRA_CLOUD_PROVIDER = "cloud_provider";
+ /** {@hide} */
+ public static final String EXTRA_NOTIFY_CLOUD_EVENT_RESULT = "notify_cloud_event_result";
/** {@hide} */
public static final String QUERY_ARG_LIMIT = ContentResolver.QUERY_ARG_LIMIT;
@@ -4561,4 +4567,38 @@
return false;
}
}
+
+ /**
+ * Returns the authority of the currently enabled cloud provider or {@code null} if there's none
+ * enabled.
+ *
+ * See android.provider.CloudMediaProvider
+ */
+ // TODO(b/202733511): Convert See to @see tag after CloudMediaProvider API is unhidden
+ @Nullable
+ public static String getCloudProvider(@NonNull ContentResolver resolver) {
+ Objects.requireNonNull(resolver);
+
+ final Bundle out = resolver.call(AUTHORITY, GET_CLOUD_PROVIDER_CALL, null, null);
+ return out.getString(EXTRA_CLOUD_PROVIDER);
+ }
+
+ /**
+ * Notifies the OS about a cloud event requiring a full or incremental media collection sync
+ * for the currently enabled cloud provider.
+ *
+ * The OS will schedule the sync in the background and will attempt to batch frequent
+ * notifications into a single sync event.
+ *
+ * If the caller is not the currently enabled cloud provider as returned by
+ * {@link #getCloudProvider(ContentResolver)}, the request will be unsuccessful.
+ *
+ * @return {@code true} if the notification was successful, {@code false} otherwise
+ */
+ public static boolean notifyCloudEvent(@NonNull ContentResolver resolver) {
+ Objects.requireNonNull(resolver);
+
+ final Bundle out = resolver.call(AUTHORITY, NOTIFY_CLOUD_EVENT_CALL, null, null);
+ return out.getBoolean(EXTRA_NOTIFY_CLOUD_EVENT_RESULT);
+ }
}
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 90bfdbc..8fb7007 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -6027,15 +6027,38 @@
} finally {
restoreLocalCallingIdentity(token);
}
- case MediaStore.SET_CLOUD_PROVIDER_CALL:
+ case MediaStore.SET_CLOUD_PROVIDER_CALL: {
// TODO(b/190713331): Remove after initial development
final String cloudProvider = extras.getString(MediaStore.EXTRA_CLOUD_PROVIDER);
Log.i(TAG, "Developer initiated cloud provider switch: " + cloudProvider);
mPickerSyncController.setCloudProvider(cloudProvider);
// fall through
- case MediaStore.SYNC_PROVIDERS_CALL:
+ }
+ case MediaStore.SYNC_PROVIDERS_CALL: {
syncPicker();
return new Bundle();
+ }
+ case MediaStore.GET_CLOUD_PROVIDER_CALL: {
+ final String cloudProvider = mPickerSyncController.getCloudProvider();
+
+ Bundle bundle = new Bundle();
+ bundle.putString(MediaStore.EXTRA_CLOUD_PROVIDER, cloudProvider);
+ return bundle;
+ }
+ case MediaStore.NOTIFY_CLOUD_EVENT_CALL: {
+ final boolean notifyCloudEventResult;
+ if (mPickerSyncController.isProviderEnabled(Binder.getCallingUid())) {
+ mPickerSyncController.notifyMediaEvent();
+ notifyCloudEventResult = true;
+ } else {
+ notifyCloudEventResult = false;
+ }
+
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(MediaStore.EXTRA_NOTIFY_CLOUD_EVENT_RESULT,
+ notifyCloudEventResult);
+ return bundle;
+ }
default:
throw new UnsupportedOperationException("Unsupported call: " + method);
}