Merge "MediaController2: Ensure NonNull for parameters of public methods"
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
index 6a03989..9ee4928 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
@@ -42,7 +42,7 @@
 
     void onCustomLayoutChanged(in List<Bundle> commandButtonlist);
 
-    void sendCustomCommand(in Bundle command, in Bundle args, in ResultReceiver receiver);
+    void onCustomCommand(in Bundle command, in Bundle args, in ResultReceiver receiver);
 
     //////////////////////////////////////////////////////////////////////////////////////////////
     // Browser sepcific
diff --git a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
index 24293ab..122ebe7 100644
--- a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
@@ -68,6 +68,10 @@
 
     @Override
     public void subscribe_impl(String parentId, Bundle extras) {
+        if (parentId == null) {
+            throw new IllegalArgumentException("parentId shouldn't be null");
+        }
+
         final IMediaSession2 binder = getSessionBinder();
         if (binder != null) {
             try {
@@ -85,6 +89,10 @@
 
     @Override
     public void unsubscribe_impl(String parentId) {
+        if (parentId == null) {
+            throw new IllegalArgumentException("parentId shouldn't be null");
+        }
+
         final IMediaSession2 binder = getSessionBinder();
         if (binder != null) {
             try {
@@ -170,6 +178,9 @@
         if (TextUtils.isEmpty(query)) {
             throw new IllegalArgumentException("query shouldn't be empty");
         }
+        if (page < 1 || pageSize < 1) {
+            throw new IllegalArgumentException("Neither page nor pageSize should be less than 1");
+        }
         final IMediaSession2 binder = getSessionBinder();
         if (binder != null) {
             try {
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 2c28e10..4a4f250 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -46,6 +46,7 @@
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.support.annotation.GuardedBy;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -380,6 +381,9 @@
     @Override
     public void prepareFromUri_impl(Uri uri, Bundle extras) {
         final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PREPARE_FROM_URI);
+        if (uri == null) {
+            throw new IllegalArgumentException("uri shouldn't be null");
+        }
         if (binder != null) {
             try {
                 binder.prepareFromUri(mSessionCallbackStub, uri, extras);
@@ -394,6 +398,9 @@
     @Override
     public void prepareFromSearch_impl(String query, Bundle extras) {
         final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PREPARE_FROM_SEARCH);
+        if (TextUtils.isEmpty(query)) {
+            throw new IllegalArgumentException("query shouldn't be empty");
+        }
         if (binder != null) {
             try {
                 binder.prepareFromSearch(mSessionCallbackStub, query, extras);
@@ -406,8 +413,11 @@
     }
 
     @Override
-    public void prepareMediaId_impl(String mediaId, Bundle extras) {
+    public void prepareFromMediaId_impl(String mediaId, Bundle extras) {
         final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PREPARE_FROM_MEDIA_ID);
+        if (mediaId == null) {
+            throw new IllegalArgumentException("mediaId shouldn't be null");
+        }
         if (binder != null) {
             try {
                 binder.prepareFromMediaId(mSessionCallbackStub, mediaId, extras);
@@ -422,6 +432,9 @@
     @Override
     public void playFromUri_impl(Uri uri, Bundle extras) {
         final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAY_FROM_URI);
+        if (uri == null) {
+            throw new IllegalArgumentException("uri shouldn't be null");
+        }
         if (binder != null) {
             try {
                 binder.playFromUri(mSessionCallbackStub, uri, extras);
@@ -436,6 +449,9 @@
     @Override
     public void playFromSearch_impl(String query, Bundle extras) {
         final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAY_FROM_SEARCH);
+        if (TextUtils.isEmpty(query)) {
+            throw new IllegalArgumentException("query shouldn't be empty");
+        }
         if (binder != null) {
             try {
                 binder.playFromSearch(mSessionCallbackStub, query, extras);
@@ -450,6 +466,9 @@
     @Override
     public void playFromMediaId_impl(String mediaId, Bundle extras) {
         final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAY_FROM_MEDIA_ID);
+        if (mediaId == null) {
+            throw new IllegalArgumentException("mediaId shouldn't be null");
+        }
         if (binder != null) {
             try {
                 binder.playFromMediaId(mSessionCallbackStub, mediaId, extras);
@@ -523,6 +542,9 @@
 
     @Override
     public void seekTo_impl(long pos) {
+        if (pos < 0) {
+            throw new IllegalArgumentException("position shouldn't be negative");
+        }
         Bundle args = new Bundle();
         args.putLong(MediaSession2Stub.ARGUMENT_KEY_POSITION, pos);
         sendTransportControlCommand(MediaSession2.COMMAND_CODE_PLAYBACK_SEEK_TO, args);
@@ -530,6 +552,10 @@
 
     @Override
     public void skipToPlaylistItem_impl(MediaItem2 item) {
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
+
         // TODO(jaewan): Implement this
         /*
         Bundle args = new Bundle();
@@ -549,16 +575,31 @@
     @Override
     public void addPlaylistItem_impl(int index, MediaItem2 item) {
         // TODO(jaewan): Implement (b/73149584)
+        if (index < 0) {
+            throw new IllegalArgumentException("index shouldn't be negative");
+        }
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
     }
 
     @Override
     public void removePlaylistItem_impl(MediaItem2 item) {
         // TODO(jaewan): Implement (b/73149584)
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
     }
 
     @Override
     public void replacePlaylistItem_impl(int index, MediaItem2 item) {
         // TODO: Implement this (b/73149407)
+        if (index < 0) {
+            throw new IllegalArgumentException("index shouldn't be negative");
+        }
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
     }
 
     @Override
@@ -578,7 +619,7 @@
     @Override
     public void setPlaylistParams_impl(PlaylistParams params) {
         if (params == null) {
-            throw new IllegalArgumentException("PlaylistParams should not be null!");
+            throw new IllegalArgumentException("params shouldn't be null");
         }
         Bundle args = new Bundle();
         args.putBundle(MediaSession2Stub.ARGUMENT_KEY_PLAYLIST_PARAMS, params.toBundle());
@@ -651,15 +692,7 @@
         });
     }
 
-    void pushPlaylistChanges(final List<Bundle> list) {
-        final List<MediaItem2> playlist = new ArrayList<>();
-        for (int i = 0; i < list.size(); i++) {
-            MediaItem2 item = MediaItem2.fromBundle(mContext, list.get(i));
-            if (item != null) {
-                playlist.add(item);
-            }
-        }
-
+    void pushPlaylistChanges(final List<MediaItem2> playlist) {
         synchronized (mLock) {
             mPlaylist = playlist;
             mCallbackExecutor.execute(() -> {
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java b/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java
index 7ebf716..b8e651e 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.content.Context;
+import android.media.MediaController2;
 import android.media.MediaItem2;
 import android.media.MediaSession2.Command;
 import android.media.MediaSession2.CommandButton;
@@ -26,6 +27,7 @@
 import android.media.PlaybackState2;
 import android.os.Bundle;
 import android.os.ResultReceiver;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.media.MediaController2Impl.PlaybackInfoImpl;
@@ -79,7 +81,7 @@
     }
 
     @Override
-    public void onPlaylistChanged(List<Bundle> playlist) throws RuntimeException {
+    public void onPlaylistChanged(List<Bundle> playlistBundle) throws RuntimeException {
         final MediaController2Impl controller;
         try {
             controller = getController();
@@ -87,14 +89,24 @@
             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
             return;
         }
-        if (playlist == null) {
+        if (playlistBundle == null) {
+            Log.w(TAG, "onPlaylistChanged(): Ignoring null playlist");
             return;
         }
+        List<MediaItem2> playlist = new ArrayList<>();
+        for (Bundle bundle : playlistBundle) {
+            MediaItem2 item = MediaItem2.fromBundle(controller.getContext(), bundle);
+            if (item == null) {
+                Log.w(TAG, "onPlaylistChanged(): Ignoring null item in playlist");
+            } else {
+                playlist.add(item);
+            }
+        }
         controller.pushPlaylistChanges(playlist);
     }
 
     @Override
-    public void onPlaylistParamsChanged(Bundle params) throws RuntimeException {
+    public void onPlaylistParamsChanged(Bundle paramsBundle) throws RuntimeException {
         final MediaController2Impl controller;
         try {
             controller = getController();
@@ -102,8 +114,12 @@
             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
             return;
         }
-        controller.pushPlaylistParamsChanges(
-                PlaylistParams.fromBundle(controller.getContext(), params));
+        PlaylistParams params = PlaylistParams.fromBundle(controller.getContext(), paramsBundle);
+        if (params == null) {
+            Log.w(TAG, "onPlaylistParamsChanged(): Ignoring null playlistParams");
+            return;
+        }
+        controller.pushPlaylistParamsChanges(params);
     }
 
     @Override
@@ -118,6 +134,12 @@
             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
             return;
         }
+        MediaController2.PlaybackInfo info =
+                PlaybackInfoImpl.fromBundle(controller.getContext(), playbackInfo);
+        if (info == null) {
+            Log.w(TAG, "onPlaybackInfoChanged(): Ignoring null playbackInfo");
+            return;
+        }
         controller.pushPlaybackInfoChanges(
                 PlaybackInfoImpl.fromBundle(controller.getContext(), playbackInfo));
     }
@@ -167,7 +189,7 @@
     @Override
     public void onCustomLayoutChanged(List<Bundle> commandButtonlist) {
         if (commandButtonlist == null) {
-            // Illegal call. Ignore
+            Log.w(TAG, "onCustomLayoutChanged(): Ignoring null commandButtonlist");
             return;
         }
         final MediaController2Impl controller;
@@ -193,7 +215,7 @@
     }
 
     @Override
-    public void sendCustomCommand(Bundle commandBundle, Bundle args, ResultReceiver receiver) {
+    public void onCustomCommand(Bundle commandBundle, Bundle args, ResultReceiver receiver) {
         final MediaController2Impl controller;
         try {
             controller = getController();
@@ -203,6 +225,7 @@
         }
         Command command = Command.fromBundle(controller.getContext(), commandBundle);
         if (command == null) {
+            Log.w(TAG, "onCustomCommand(): Ignoring null command");
             return;
         }
         controller.onCustomCommand(command, args, receiver);
@@ -231,6 +254,10 @@
 
     @Override
     public void onGetItemDone(String mediaId, Bundle itemBundle) throws RuntimeException {
+        if (mediaId == null) {
+            Log.w(TAG, "onGetItemDone(): Ignoring null mediaId");
+            return;
+        }
         final MediaBrowser2Impl browser;
         try {
             browser = getBrowser();
@@ -249,6 +276,10 @@
     @Override
     public void onGetChildrenDone(String parentId, int page, int pageSize,
             List<Bundle> itemBundleList, Bundle extras) throws RuntimeException {
+        if (parentId == null) {
+            Log.w(TAG, "onGetChildrenDone(): Ignoring null parentId");
+            return;
+        }
         final MediaBrowser2Impl browser;
         try {
             browser = getBrowser();
@@ -274,6 +305,10 @@
     @Override
     public void onSearchResultChanged(String query, int itemCount, Bundle extras)
             throws RuntimeException {
+        if (TextUtils.isEmpty(query)) {
+            Log.w(TAG, "onSearchResultChanged(): Ignoring empty query");
+            return;
+        }
         final MediaBrowser2Impl browser;
         try {
             browser = getBrowser();
@@ -291,6 +326,10 @@
     @Override
     public void onGetSearchResultDone(String query, int page, int pageSize,
             List<Bundle> itemBundleList, Bundle extras) throws RuntimeException {
+        if (TextUtils.isEmpty(query)) {
+            Log.w(TAG, "onGetSearchResultDone(): Ignoring empty query");
+            return;
+        }
         final MediaBrowser2Impl browser;
         try {
             browser = getBrowser();
@@ -315,6 +354,10 @@
 
     @Override
     public void onChildrenChanged(String parentId, int itemCount, Bundle extras) {
+        if (parentId == null) {
+            Log.w(TAG, "onChildrenChanged(): Ignoring null parentId");
+            return;
+        }
         final MediaBrowser2Impl browser;
         try {
             browser = getBrowser();
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 15cfd8d..785248c 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -985,7 +985,7 @@
         }
         try {
             Bundle commandBundle = command.toBundle();
-            controllerBinder.sendCustomCommand(commandBundle, args, receiver);
+            controllerBinder.onCustomCommand(commandBundle, args, receiver);
         } catch (RemoteException e) {
             Log.w(TAG, "Controller is gone", e);
             // TODO(jaewan): What to do when the controller is gone?