Merge "MediaSession2: Ensure NonNull/Nullable for parameters of public methods" into pi-dev
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
index 34251fb..ef7120d 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
@@ -62,7 +62,7 @@
     //////////////////////////////////////////////////////////////////////////////////////////////
     // library service specific
     //////////////////////////////////////////////////////////////////////////////////////////////
-    void getBrowserRoot(IMediaSession2Callback caller, in Bundle rootHints);
+    void getLibraryRoot(IMediaSession2Callback caller, in Bundle rootHints);
     void getItem(IMediaSession2Callback caller, String mediaId);
     void getChildren(IMediaSession2Callback caller, String parentId, int page, int pageSize,
             in Bundle extras);
diff --git a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
index 122ebe7..c909099 100644
--- a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
@@ -54,7 +54,7 @@
         final IMediaSession2 binder = getSessionBinder();
         if (binder != null) {
             try {
-                binder.getBrowserRoot(getControllerStub(), rootHints);
+                binder.getLibraryRoot(getControllerStub(), rootHints);
             } catch (RemoteException e) {
                 // TODO(jaewan): Handle disconnect.
                 if (DEBUG) {
diff --git a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
index 5351394..b3512cc 100644
--- a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
@@ -72,8 +72,8 @@
                 VolumeProvider2 volumeProvider,
                 PendingIntent sessionActivity, Executor callbackExecutor,
                 MediaLibrarySessionCallback callback) {
-            super(context, player, id, playlistAgent, volumeProvider, sessionActivity, callbackExecutor,
-                    callback);
+            super(context, player, id, playlistAgent, volumeProvider, sessionActivity,
+                    callbackExecutor, callback);
             // Don't put any extra initialization here. Here's the reason.
             // System service will recognize this session inside of the super constructor and would
             // connect to this session assuming that initialization is finished. However, if any
@@ -154,8 +154,7 @@
         public LibraryRootImpl(Context context, LibraryRoot instance, String rootId,
                 Bundle extras) {
             if (rootId == null) {
-                throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " +
-                        "Use null for BrowserRoot instead.");
+                throw new IllegalArgumentException("rootId shouldn't be null.");
             }
             mInstance = instance;
             mRootId = rootId;
diff --git a/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java b/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
index 7b2ee32..333455d 100644
--- a/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
@@ -123,11 +123,17 @@
 
     @Override
     public boolean containsKey_impl(String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         return mBundle.containsKey(key);
     }
 
     @Override
     public CharSequence getText_impl(@TextKey String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         return mBundle.getCharSequence(key);
     }
 
@@ -138,6 +144,9 @@
 
     @Override
     public String getString_impl(@TextKey String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         CharSequence text = mBundle.getCharSequence(key);
         if (text != null) {
             return text.toString();
@@ -147,11 +156,17 @@
 
     @Override
     public long getLong_impl(@LongKey String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         return mBundle.getLong(key, 0);
     }
 
     @Override
     public Rating2 getRating_impl(@RatingKey String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         // TODO(jaewan): Add backward compatibility
         Rating2 rating = null;
         try {
@@ -165,11 +180,17 @@
 
     @Override
     public float getFloat_impl(@FloatKey String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         return mBundle.getFloat(key);
     }
 
     @Override
     public Bitmap getBitmap_impl(@BitmapKey String key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key shouldn't be null");
+        }
         Bitmap bmp = null;
         try {
             bmp = mBundle.getParcelable(key);
@@ -221,7 +242,8 @@
             mBundle = new Bundle();
         }
 
-        public BuilderImpl(Context context, MediaMetadata2.Builder instance, MediaMetadata2 source) {
+        public BuilderImpl(Context context, MediaMetadata2.Builder instance,
+                MediaMetadata2 source) {
             if (source == null) {
                 throw new IllegalArgumentException("source shouldn't be null");
             }
@@ -248,6 +270,9 @@
 
         @Override
         public Builder putText_impl(@TextKey String key, CharSequence value) {
+            if (key == null) {
+                throw new IllegalArgumentException("key shouldn't be null");
+            }
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                     throw new IllegalArgumentException("The " + key
@@ -260,6 +285,9 @@
 
         @Override
         public Builder putString_impl(@TextKey String key, String value) {
+            if (key == null) {
+                throw new IllegalArgumentException("key shouldn't be null");
+            }
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                     throw new IllegalArgumentException("The " + key
@@ -272,6 +300,9 @@
 
         @Override
         public Builder putLong_impl(@LongKey String key, long value) {
+            if (key == null) {
+                throw new IllegalArgumentException("key shouldn't be null");
+            }
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
                     throw new IllegalArgumentException("The " + key
@@ -284,6 +315,9 @@
 
         @Override
         public Builder putRating_impl(@RatingKey String key, Rating2 value) {
+            if (key == null) {
+                throw new IllegalArgumentException("key shouldn't be null");
+            }
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
                     throw new IllegalArgumentException("The " + key
@@ -296,6 +330,9 @@
 
         @Override
         public Builder putBitmap_impl(@BitmapKey String key, Bitmap value) {
+            if (key == null) {
+                throw new IllegalArgumentException("key shouldn't be null");
+            }
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
                     throw new IllegalArgumentException("The " + key
@@ -308,6 +345,9 @@
 
         @Override
         public Builder putFloat_impl(@FloatKey String key, float value) {
+            if (key == null) {
+                throw new IllegalArgumentException("key shouldn't be null");
+            }
             if (METADATA_KEYS_TYPE.containsKey(key)) {
                 if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_FLOAT) {
                     throw new IllegalArgumentException("The " + key
@@ -329,7 +369,8 @@
             return new MediaMetadata2Impl(mContext, mBundle).getInstance();
         }
 
-        private Bitmap scaleBitmap(Bitmap bmp, int maxSize) { float maxSizeF = maxSize;
+        private Bitmap scaleBitmap(Bitmap bmp, int maxSize) {
+            float maxSizeF = maxSize;
             float widthScale = maxSizeF / bmp.getWidth();
             float heightScale = maxSizeF / bmp.getHeight();
             float scale = Math.min(widthScale, heightScale);
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index 7e24bb0..5c18515 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.media.AudioAttributes;
+import android.media.AudioFocusRequest;
 import android.media.AudioManager;
 import android.media.DataSourceDesc;
 import android.media.MediaController2;
@@ -346,7 +347,7 @@
     }
 
     @Override
-    public void setAudioFocusRequest_impl(int focusGain) {
+    public void setAudioFocusRequest_impl(AudioFocusRequest afr) {
         // implement
     }
 
@@ -477,11 +478,20 @@
     @Override
     public void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
             ResultReceiver receiver) {
+        if (controller == null) {
+            throw new IllegalArgumentException("controller shouldn't be null");
+        }
+        if (command == null) {
+            throw new IllegalArgumentException("command shouldn't be null");
+        }
         mSessionStub.sendCustomCommand(controller, command, args, receiver);
     }
 
     @Override
     public void sendCustomCommand_impl(Command command, Bundle args) {
+        if (command == null) {
+            throw new IllegalArgumentException("command shouldn't be null");
+        }
         mSessionStub.sendCustomCommand(command, args);
     }
 
@@ -506,21 +516,39 @@
 
     @Override
     public void addPlaylistItem_impl(int index, MediaItem2 item) {
+        if (index < 0) {
+            throw new IllegalArgumentException("index shouldn't be negative");
+        }
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
         // TODO(jaewan): Implement
     }
 
     @Override
     public void removePlaylistItem_impl(MediaItem2 item) {
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
         // TODO(jaewan): Implement
     }
 
     @Override
     public void editPlaylistItem_impl(MediaItem2 item) {
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
         // TODO(jaewan): Implement
     }
 
     @Override
     public void replacePlaylistItem_impl(int index, MediaItem2 item) {
+        if (index < 0) {
+            throw new IllegalArgumentException("index shouldn't be negative");
+        }
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
         // TODO(jaewan): Implement
     }
 
@@ -603,6 +631,9 @@
     @Override
     public void skipToPlaylistItem_impl(MediaItem2 item) {
         ensureCallingThread();
+        if (item == null) {
+            throw new IllegalArgumentException("item shouldn't be null");
+        }
         // TODO: Uncomment or remove
         /*
         final MediaPlayerBase player = mPlayer;
@@ -887,6 +918,9 @@
          * @return a new Command instance from the Bundle
          */
         public static Command fromBundle_impl(Context context, Bundle command) {
+            if (command == null) {
+                throw new IllegalArgumentException("command shouldn't be null");
+            }
             int code = command.getInt(KEY_COMMAND_CODE);
             if (code != COMMAND_CODE_CUSTOM) {
                 return new Command(context, code);
@@ -939,6 +973,9 @@
 
         @Override
         public void addCommand_impl(Command command) {
+            if (command == null) {
+                throw new IllegalArgumentException("command shouldn't be null");
+            }
             mCommands.add(command);
         }
 
@@ -951,11 +988,17 @@
 
         @Override
         public void removeCommand_impl(Command command) {
+            if (command == null) {
+                throw new IllegalArgumentException("command shouldn't be null");
+            }
             mCommands.remove(command);
         }
 
         @Override
         public boolean hasCommand_impl(Command command) {
+            if (command == null) {
+                throw new IllegalArgumentException("command shouldn't be null");
+            }
             return mCommands.contains(command);
         }
 
@@ -1029,6 +1072,13 @@
 
         public ControllerInfoImpl(Context context, ControllerInfo instance, int uid,
                 int pid, String packageName, IMediaSession2Callback callback) {
+            if (TextUtils.isEmpty(packageName)) {
+                throw new IllegalArgumentException("packageName shouldn't be empty");
+            }
+            if (callback == null) {
+                throw new IllegalArgumentException("callback shouldn't be null");
+            }
+
             mInstance = instance;
             mUid = uid;
             mPackageName = packageName;
@@ -1351,6 +1401,7 @@
             mId = "";
         }
 
+        @Override
         public void setPlayer_impl(MediaPlayerBase player) {
             if (player == null) {
                 throw new IllegalArgumentException("player shouldn't be null");
@@ -1366,17 +1417,17 @@
             mPlaylistAgent = playlistAgent;
         }
 
+        @Override
         public void setVolumeProvider_impl(VolumeProvider2 volumeProvider) {
-            if (volumeProvider == null) {
-                throw new IllegalArgumentException("volumeProvider shouldn't be null");
-            }
             mVolumeProvider = volumeProvider;
         }
 
+        @Override
         public void setSessionActivity_impl(PendingIntent pi) {
             mSessionActivity = pi;
         }
 
+        @Override
         public void setId_impl(String id) {
             if (id == null) {
                 throw new IllegalArgumentException("id shouldn't be null");
@@ -1384,6 +1435,7 @@
             mId = id;
         }
 
+        @Override
         public void setSessionCallback_impl(Executor executor, C callback) {
             if (executor == null) {
                 throw new IllegalArgumentException("executor shouldn't be null");
@@ -1395,6 +1447,7 @@
             mCallback = callback;
         }
 
+        @Override
         public abstract T build_impl();
     }
 
@@ -1411,7 +1464,6 @@
             if (mCallback == null) {
                 mCallback = new SessionCallback(mContext) {};
             }
-
             return new MediaSession2Impl(mContext, mPlayer, mId, mPlaylistAgent,
                     mVolumeProvider, mSessionActivity, mCallbackExecutor, mCallback).getInstance();
         }
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index d4164f6..a9c5224 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -481,6 +481,11 @@
             return;
         }
         final Command command = Command.fromBundle(session.getContext(), commandBundle);
+        if (command == null) {
+            Log.w(TAG, "sendCustomCommand(): Ignoring null command from "
+                    + getControllerIfAble(caller));
+            return;
+        }
         final ControllerInfo controller = getControllerIfAble(caller, command);
         if (controller == null) {
             return;
@@ -503,6 +508,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (uri == null) {
+            Log.w(TAG, "prepareFromUri(): Ignoring null uri from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(
                     caller, MediaSession2.COMMAND_CODE_PREPARE_FROM_URI) == null) {
@@ -522,6 +531,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (TextUtils.isEmpty(query)) {
+            Log.w(TAG, "prepareFromSearch(): Ignoring empty query from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(
                     caller, MediaSession2.COMMAND_CODE_PREPARE_FROM_SEARCH) == null) {
@@ -541,6 +554,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (mediaId == null) {
+            Log.w(TAG, "prepareFromMediaId(): Ignoring null mediaId from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(
                     caller, MediaSession2.COMMAND_CODE_PREPARE_FROM_MEDIA_ID) == null) {
@@ -560,6 +577,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (uri == null) {
+            Log.w(TAG, "playFromUri(): Ignoring null uri from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(
                     caller, MediaSession2.COMMAND_CODE_PLAY_FROM_URI) == null) {
@@ -578,6 +599,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (TextUtils.isEmpty(query)) {
+            Log.w(TAG, "playFromSearch(): Ignoring empty query from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(
                     caller, MediaSession2.COMMAND_CODE_PLAY_FROM_SEARCH) == null) {
@@ -597,6 +622,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (mediaId == null) {
+            Log.w(TAG, "playFromMediaId(): Ignoring null mediaId from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (session == null) {
                 return;
@@ -617,14 +646,17 @@
             }
             return;
         }
+        Rating2 rating = Rating2Impl.fromBundle(sessionImpl.getContext(), ratingBundle);
+        if (rating == null) {
+            Log.w(TAG, "setRating(): Ignore null rating");
+            return;
+        }
         sessionImpl.getCallbackExecutor().execute(() -> {
             final MediaSession2Impl session = mSession.get();
             if (session == null) {
                 return;
             }
-            Rating2 rating = Rating2Impl.fromBundle(session.getContext(), ratingBundle);
-            session.getCallback().onSetRating(session.getInstance(),
-                    controller, mediaId, rating);
+            session.getCallback().onSetRating(session.getInstance(), controller, mediaId, rating);
         });
     }
 
@@ -633,7 +665,7 @@
     //////////////////////////////////////////////////////////////////////////////////////////////
 
     @Override
-    public void getBrowserRoot(final IMediaSession2Callback caller, final Bundle rootHints)
+    public void getLibraryRoot(final IMediaSession2Callback caller, final Bundle rootHints)
             throws RuntimeException {
         final MediaLibrarySessionImpl session = getLibrarySession();
         final ControllerInfo controller = getControllerIfAble(
@@ -744,36 +776,36 @@
         if (session == null || controller == null) {
             return;
         }
+        if (TextUtils.isEmpty(query)) {
+            Log.w(TAG, "search(): Ignoring empty query from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(caller, MediaSession2.COMMAND_CODE_BROWSER) == null) {
                 return;
             }
-            session.getCallback().onSearch(session.getInstance(),
-                    controller, query, extras);
+            session.getCallback().onSearch(session.getInstance(), controller, query, extras);
         });
     }
 
     @Override
     public void getSearchResult(final IMediaSession2Callback caller, final String query,
             final int page, final int pageSize, final Bundle extras) {
-        if (TextUtils.isEmpty(query)) {
-            if (DEBUG) {
-                Log.d(TAG, "query shouldn't be empty");
-            }
-            return;
-        }
-        if (page < 1 || pageSize < 1) {
-            if (DEBUG) {
-                Log.d(TAG, "Neither page nor pageSize should be less than 1");
-            }
-            return;
-        }
         final MediaLibrarySessionImpl session = getLibrarySession();
         final ControllerInfo controller = getControllerIfAble(
                 caller, MediaSession2.COMMAND_CODE_BROWSER);
         if (session == null || controller == null) {
             return;
         }
+        if (TextUtils.isEmpty(query)) {
+            Log.w(TAG, "getSearchResult(): Ignoring empty query from " + controller);
+            return;
+        }
+        if (page < 1 || pageSize < 1) {
+            Log.w(TAG, "getSearchResult(): Ignoring negative page / pageSize."
+                    + " page=" + page + " pageSize=" + pageSize + " from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(caller, MediaSession2.COMMAND_CODE_BROWSER) == null) {
                 return;
@@ -811,6 +843,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (parentId == null) {
+            Log.w(TAG, "subscribe(): Ignoring null parentId from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(caller, MediaSession2.COMMAND_CODE_BROWSER) == null) {
                 return;
@@ -836,6 +872,10 @@
         if (session == null || controller == null) {
             return;
         }
+        if (parentId == null) {
+            Log.w(TAG, "unsubscribe(): Ignoring null parentId from " + controller);
+            return;
+        }
         session.getCallbackExecutor().execute(() -> {
             if (getControllerIfAble(caller, MediaSession2.COMMAND_CODE_BROWSER) == null) {
                 return;
diff --git a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
index 3965ccb..723622e 100644
--- a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
@@ -59,10 +59,10 @@
     public SessionToken2Impl(Context context, SessionToken2 instance,
             String packageName, String serviceName, int uid) {
         if (TextUtils.isEmpty(packageName)) {
-            throw new IllegalArgumentException("package name shouldn't be null");
+            throw new IllegalArgumentException("packageName shouldn't be empty");
         }
         if (TextUtils.isEmpty(serviceName)) {
-            throw new IllegalArgumentException("service name shouldn't be null");
+            throw new IllegalArgumentException("serviceName shouldn't be empty");
         }
         mInstance = instance;
         // Calculate uid if it's not specified.
diff --git a/packages/MediaComponents/src/com/android/media/VolumeProvider2Impl.java b/packages/MediaComponents/src/com/android/media/VolumeProvider2Impl.java
index 5af3ddf..156bcae 100644
--- a/packages/MediaComponents/src/com/android/media/VolumeProvider2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/VolumeProvider2Impl.java
@@ -15,6 +15,10 @@
  */
 package com.android.media;
 
+import static android.media.VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+import static android.media.VolumeProvider2.VOLUME_CONTROL_FIXED;
+import static android.media.VolumeProvider2.VOLUME_CONTROL_RELATIVE;
+
 import android.content.Context;
 import android.media.VolumeProvider2;
 import android.media.update.VolumeProvider2Provider;
@@ -31,6 +35,18 @@
 
     public VolumeProvider2Impl(Context context, VolumeProvider2 instance,
             @VolumeProvider2.ControlType int controlType, int maxVolume, int currentVolume) {
+        if (controlType != VOLUME_CONTROL_FIXED && controlType != VOLUME_CONTROL_RELATIVE
+                && controlType != VOLUME_CONTROL_ABSOLUTE) {
+            throw new IllegalArgumentException("wrong controlType " + controlType);
+        }
+        if (maxVolume < 0 || currentVolume < 0) {
+            throw new IllegalArgumentException("volume shouldn't be negative"
+                    + ", maxVolume=" + maxVolume + ", currentVolume=" + currentVolume);
+        }
+        if (currentVolume > maxVolume) {
+            throw new IllegalArgumentException("currentVolume shouldn't be greater than maxVolume"
+                    + ", maxVolume=" + maxVolume + ", currentVolume=" + currentVolume);
+        }
         mContext = context;
         mInstance = instance;
         mControlType = controlType;
@@ -55,6 +71,10 @@
 
     @Override
     public void setCurrentVolume_impl(int currentVolume) {
+        if (currentVolume < 0) {
+            throw new IllegalArgumentException("currentVolume shouldn't be negative"
+                    + ", currentVolume=" + currentVolume);
+        }
         mCurrentVolume = currentVolume;
         if (mCallback != null) {
             mCallback.onVolumeChanged(mInstance);