MediaPlayerListener.java revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package org.chromium.media; 6 7import android.Manifest.permission; 8import android.content.Context; 9import android.content.pm.PackageManager; 10import android.media.AudioManager; 11import android.media.MediaPlayer; 12 13import org.chromium.base.CalledByNative; 14import org.chromium.base.JNINamespace; 15 16// This class implements all the listener interface for android mediaplayer. 17// Callbacks will be sent to the native class for processing. 18@JNINamespace("media") 19class MediaPlayerListener implements MediaPlayer.OnPreparedListener, 20 MediaPlayer.OnCompletionListener, 21 MediaPlayer.OnBufferingUpdateListener, 22 MediaPlayer.OnSeekCompleteListener, 23 MediaPlayer.OnVideoSizeChangedListener, 24 MediaPlayer.OnErrorListener, 25 AudioManager.OnAudioFocusChangeListener { 26 // These values are mirrored as enums in media/base/android/media_player_bridge.h. 27 // Please ensure they stay in sync. 28 private static final int MEDIA_ERROR_FORMAT = 0; 29 private static final int MEDIA_ERROR_DECODE = 1; 30 private static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 2; 31 private static final int MEDIA_ERROR_INVALID_CODE = 3; 32 33 // These values are copied from android media player. 34 public static final int MEDIA_ERROR_MALFORMED = -1007; 35 public static final int MEDIA_ERROR_TIMED_OUT = -110; 36 37 // Used to determine the class instance to dispatch the native call to. 38 private int mNativeMediaPlayerListener = 0; 39 private final Context mContext; 40 41 private MediaPlayerListener(int nativeMediaPlayerListener, Context context) { 42 mNativeMediaPlayerListener = nativeMediaPlayerListener; 43 mContext = context; 44 } 45 46 @Override 47 public boolean onError(MediaPlayer mp, int what, int extra) { 48 int errorType; 49 switch (what) { 50 case MediaPlayer.MEDIA_ERROR_UNKNOWN: 51 switch (extra) { 52 case MEDIA_ERROR_MALFORMED: 53 errorType = MEDIA_ERROR_DECODE; 54 break; 55 case MEDIA_ERROR_TIMED_OUT: 56 errorType = MEDIA_ERROR_INVALID_CODE; 57 break; 58 default: 59 errorType = MEDIA_ERROR_FORMAT; 60 break; 61 } 62 break; 63 case MediaPlayer.MEDIA_ERROR_SERVER_DIED: 64 errorType = MEDIA_ERROR_DECODE; 65 break; 66 case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: 67 errorType = MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK; 68 break; 69 default: 70 // There are some undocumented error codes for android media player. 71 // For example, when surfaceTexture got deleted before we setVideoSuface 72 // to NULL, mediaplayer will report error -38. These errors should be ignored 73 // and not be treated as an error to webkit. 74 errorType = MEDIA_ERROR_INVALID_CODE; 75 break; 76 } 77 nativeOnMediaError(mNativeMediaPlayerListener, errorType); 78 return true; 79 } 80 81 @Override 82 public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 83 nativeOnVideoSizeChanged(mNativeMediaPlayerListener, width, height); 84 } 85 86 @Override 87 public void onSeekComplete(MediaPlayer mp) { 88 nativeOnSeekComplete(mNativeMediaPlayerListener); 89 } 90 91 @Override 92 public void onBufferingUpdate(MediaPlayer mp, int percent) { 93 nativeOnBufferingUpdate(mNativeMediaPlayerListener, percent); 94 } 95 96 @Override 97 public void onCompletion(MediaPlayer mp) { 98 nativeOnPlaybackComplete(mNativeMediaPlayerListener); 99 } 100 101 @Override 102 public void onPrepared(MediaPlayer mp) { 103 nativeOnMediaPrepared(mNativeMediaPlayerListener); 104 } 105 106 @Override 107 public void onAudioFocusChange(int focusChange) { 108 if (focusChange == AudioManager.AUDIOFOCUS_LOSS || 109 focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 110 nativeOnMediaInterrupted(mNativeMediaPlayerListener); 111 } 112 } 113 114 @CalledByNative 115 public void releaseResources() { 116 if (mContext != null) { 117 // Unregister the wish for audio focus. 118 AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 119 if (am != null) { 120 am.abandonAudioFocus(this); 121 } 122 } 123 } 124 125 @CalledByNative 126 private static MediaPlayerListener create(int nativeMediaPlayerListener, 127 Context context, MediaPlayerBridge mediaPlayerBridge) { 128 final MediaPlayerListener listener = 129 new MediaPlayerListener(nativeMediaPlayerListener, context); 130 mediaPlayerBridge.setOnBufferingUpdateListener(listener); 131 mediaPlayerBridge.setOnCompletionListener(listener); 132 mediaPlayerBridge.setOnErrorListener(listener); 133 mediaPlayerBridge.setOnPreparedListener(listener); 134 mediaPlayerBridge.setOnSeekCompleteListener(listener); 135 mediaPlayerBridge.setOnVideoSizeChangedListener(listener); 136 if (PackageManager.PERMISSION_GRANTED == 137 context.checkCallingOrSelfPermission(permission.WAKE_LOCK)) { 138 mediaPlayerBridge.setWakeMode(context, android.os.PowerManager.FULL_WAKE_LOCK); 139 } 140 141 AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 142 am.requestAudioFocus( 143 listener, 144 AudioManager.STREAM_MUSIC, 145 146 // Request permanent focus. 147 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); 148 return listener; 149 } 150 151 /** 152 * See media/base/android/media_player_listener.cc for all the following functions. 153 */ 154 private native void nativeOnMediaError( 155 int nativeMediaPlayerListener, 156 int errorType); 157 158 private native void nativeOnVideoSizeChanged( 159 int nativeMediaPlayerListener, 160 int width, int height); 161 162 private native void nativeOnBufferingUpdate( 163 int nativeMediaPlayerListener, 164 int percent); 165 166 private native void nativeOnMediaPrepared(int nativeMediaPlayerListener); 167 168 private native void nativeOnPlaybackComplete(int nativeMediaPlayerListener); 169 170 private native void nativeOnSeekComplete(int nativeMediaPlayerListener); 171 172 private native void nativeOnMediaInterrupted(int nativeMediaPlayerListener); 173} 174