MediaBrowserService: Make SubscriptionCallback.onError be called

Bug: 26733259
Change-Id: I8324e1c56e87071e781550ac0701e632a4122e73
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 9e67c15..ada0e2c 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -633,7 +633,6 @@
                     return;
                 }
 
-                List<MediaItem> data = list == null ? null : list.getList();
                 if (DBG) {
                     Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId);
                 }
@@ -644,10 +643,19 @@
                     // Tell the app.
                     SubscriptionCallback subscriptionCallback = subscription.getCallback(options);
                     if (subscriptionCallback != null) {
+                        List<MediaItem> data = list == null ? null : list.getList();
                         if (options == null) {
-                            subscriptionCallback.onChildrenLoaded(parentId, data);
+                            if (data == null) {
+                                subscriptionCallback.onError(parentId);
+                            } else {
+                                subscriptionCallback.onChildrenLoaded(parentId, data);
+                            }
                         } else {
-                            subscriptionCallback.onChildrenLoaded(parentId, data, options);
+                            if (data == null) {
+                                subscriptionCallback.onError(parentId, options);
+                            } else {
+                                subscriptionCallback.onChildrenLoaded(parentId, data, options);
+                            }
                         }
                         return;
                     }
@@ -848,21 +856,21 @@
          * Called when the list of children is loaded or updated.
          *
          * @param parentId The media id of the parent media item.
-         * @param children The children which were loaded, or null if the id is invalid.
+         * @param children The children which were loaded.
          */
-        public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) {
+        public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children) {
         }
 
         /**
          * Called when the list of children is loaded or updated.
          *
          * @param parentId The media id of the parent media item.
-         * @param children The children which were loaded, or null if the id is invalid.
+         * @param children The children which were loaded.
          * @param options A bundle of service-specific arguments sent to the media
          *            browse service. The contents of this bundle may affect the
          *            information returned when browsing.
          */
-        public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children,
+        public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
                 @NonNull Bundle options) {
         }
 
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 480acd9..b5ea2a0 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -45,6 +45,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 
@@ -120,8 +121,8 @@
      * they are done. If more than one of those methods is called, an exception will
      * be thrown.
      *
-     * @see MediaBrowserService#onLoadChildren
-     * @see MediaBrowserService#onLoadItem
+     * @see #onLoadChildren
+     * @see #onLoadItem
      */
     public class Result<T> {
         private Object mDebug;
@@ -367,10 +368,16 @@
      * {@link Result#detach result.detach} may be called before returning from
      * this function, and then {@link Result#sendResult result.sendResult}
      * called when the loading is complete.
+     * </p><p>
+     * In case the media item does not have any children, call {@link Result#sendResult}
+     * with an empty list which is not {@code null}. If {@code null} is sent that means
+     * the given {@code parentId} is invalid and {@link MediaBrowser.SubscriptionCallback#onError}
+     * will be called.
+     * </p>
      *
      * @param parentId The id of the parent media item whose children are to be
      *            queried.
-     * @param result The Result to send the list of children to, or null if the
+     * @param result The Result to send the list of children to. Send null if the
      *            id is invalid.
      */
     public abstract void onLoadChildren(@NonNull String parentId,
@@ -385,10 +392,16 @@
      * {@link Result#detach result.detach} may be called before returning from
      * this function, and then {@link Result#sendResult result.sendResult}
      * called when the loading is complete.
+     * </p><p>
+     * In case the media item does not have any children, call {@link Result#sendResult}
+     * with an empty list which is not {@code null}. If {@code null} is sent that means
+     * the given {@code parentId} is invalid and {@link MediaBrowser.SubscriptionCallback#onError}
+     * will be called.
+     * </p>
      *
      * @param parentId The id of the parent media item whose children are to be
      *            queried.
-     * @param result The Result to send the list of children to, or null if the
+     * @param result The Result to send the list of children to. Send null if the
      *            id is invalid.
      * @param options A bundle of service-specific arguments sent from the media
      *            browse. The information returned through the result should be
@@ -416,7 +429,7 @@
      *
      * @param itemId The id for the specific
      *            {@link android.media.browse.MediaBrowser.MediaItem}.
-     * @param result The Result to send the item to, or null if the id is
+     * @param result The Result to send the item to. Send null if the id is
      *            invalid.
      */
     public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
@@ -630,6 +643,9 @@
 
     private List<MediaBrowser.MediaItem> applyOptions(List<MediaBrowser.MediaItem> list,
             final Bundle options) {
+        if (list == null) {
+            return null;
+        }
         int page = options.getInt(MediaBrowser.EXTRA_PAGE, -1);
         int pageSize = options.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
         if (page == -1 && pageSize == -1) {
@@ -638,7 +654,7 @@
         int fromIndex = pageSize * (page - 1);
         int toIndex = fromIndex + pageSize;
         if (page < 1 || pageSize < 1 || fromIndex >= list.size()) {
-            return null;
+            return Collections.EMPTY_LIST;
         }
         if (toIndex > list.size()) {
             toIndex = list.size();