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