1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package org.chromium.media; 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.Context; 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.media.AudioManager; 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.media.MediaPlayer; 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.CalledByNative; 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.JNINamespace; 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class implements all the listener interface for android mediaplayer. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callbacks will be sent to the native class for processing. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@JNINamespace("media") 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MediaPlayerListener implements MediaPlayer.OnPreparedListener, 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MediaPlayer.OnCompletionListener, 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MediaPlayer.OnBufferingUpdateListener, 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MediaPlayer.OnSeekCompleteListener, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MediaPlayer.OnVideoSizeChangedListener, 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MediaPlayer.OnErrorListener, 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioManager.OnAudioFocusChangeListener { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These values are mirrored as enums in media/base/android/media_player_bridge.h. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Please ensure they stay in sync. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int MEDIA_ERROR_FORMAT = 0; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int MEDIA_ERROR_DECODE = 1; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 2; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private static final int MEDIA_ERROR_INVALID_CODE = 3; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These values are copied from android media player. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final int MEDIA_ERROR_MALFORMED = -1007; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public static final int MEDIA_ERROR_TIMED_OUT = -110; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to determine the class instance to dispatch the native call to. 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private long mNativeMediaPlayerListener = 0; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final Context mContext; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private MediaPlayerListener(long nativeMediaPlayerListener, Context context) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mNativeMediaPlayerListener = nativeMediaPlayerListener; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContext = context; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public boolean onError(MediaPlayer mp, int what, int extra) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errorType; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (what) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MediaPlayer.MEDIA_ERROR_UNKNOWN: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (extra) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MEDIA_ERROR_MALFORMED: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errorType = MEDIA_ERROR_DECODE; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MEDIA_ERROR_TIMED_OUT: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errorType = MEDIA_ERROR_INVALID_CODE; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errorType = MEDIA_ERROR_FORMAT; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MediaPlayer.MEDIA_ERROR_SERVER_DIED: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errorType = MEDIA_ERROR_DECODE; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errorType = MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There are some undocumented error codes for android media player. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For example, when surfaceTexture got deleted before we setVideoSuface 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to NULL, mediaplayer will report error -38. These errors should be ignored 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and not be treated as an error to webkit. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errorType = MEDIA_ERROR_INVALID_CODE; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeOnMediaError(mNativeMediaPlayerListener, errorType); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeOnVideoSizeChanged(mNativeMediaPlayerListener, width, height); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void onSeekComplete(MediaPlayer mp) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeOnSeekComplete(mNativeMediaPlayerListener); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void onBufferingUpdate(MediaPlayer mp, int percent) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeOnBufferingUpdate(mNativeMediaPlayerListener, percent); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void onCompletion(MediaPlayer mp) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeOnPlaybackComplete(mNativeMediaPlayerListener); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @Override 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public void onPrepared(MediaPlayer mp) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nativeOnMediaPrepared(mNativeMediaPlayerListener); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void onAudioFocusChange(int focusChange) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (focusChange == AudioManager.AUDIOFOCUS_LOSS || 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nativeOnMediaInterrupted(mNativeMediaPlayerListener); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @CalledByNative 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void releaseResources() { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mContext != null) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Unregister the wish for audio focus. 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (am != null) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) am.abandonAudioFocus(this); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @CalledByNative 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) private static MediaPlayerListener create(long nativeMediaPlayerListener, 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Context context, MediaPlayerBridge mediaPlayerBridge) { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final MediaPlayerListener listener = 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new MediaPlayerListener(nativeMediaPlayerListener, context); 1281675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch if (mediaPlayerBridge != null) { 1291675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch mediaPlayerBridge.setOnBufferingUpdateListener(listener); 1301675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch mediaPlayerBridge.setOnCompletionListener(listener); 1311675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch mediaPlayerBridge.setOnErrorListener(listener); 1321675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch mediaPlayerBridge.setOnPreparedListener(listener); 1331675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch mediaPlayerBridge.setOnSeekCompleteListener(listener); 1341675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch mediaPlayerBridge.setOnVideoSizeChangedListener(listener); 1351675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) am.requestAudioFocus( 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listener, 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioManager.STREAM_MUSIC, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Request permanent focus. 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return listener; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See media/base/android/media_player_listener.cc for all the following functions. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private native void nativeOnMediaError( 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeMediaPlayerListener, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errorType); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private native void nativeOnVideoSizeChanged( 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeMediaPlayerListener, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width, int height); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private native void nativeOnBufferingUpdate( 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) long nativeMediaPlayerListener, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int percent); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeOnMediaPrepared(long nativeMediaPlayerListener); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeOnPlaybackComplete(long nativeMediaPlayerListener); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeOnSeekComplete(long nativeMediaPlayerListener); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private native void nativeOnMediaInterrupted(long nativeMediaPlayerListener); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 170