19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.media;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
22e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
231af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.app.ActivityThread;
241af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.app.AppOpsManager;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetFileDescriptor;
27f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Handler;
281af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.IBinder;
29f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Looper;
30f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Message;
31e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrillimport android.os.ParcelFileDescriptor;
321af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.Process;
331af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.RemoteException;
341af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.ServiceManager;
35e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrillimport android.os.SystemProperties;
36e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrillimport android.util.AndroidRuntimeException;
37e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrillimport android.util.Log;
38e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
391af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport com.android.internal.app.IAppOpsService;
401af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
41f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
42cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks/**
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The SoundPool class manages and plays audio resources for applications.
44cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
45cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>A SoundPool is a collection of samples that can be loaded into memory
46cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * from a resource inside the APK or from a file in the file system. The
47cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * SoundPool library uses the MediaPlayer service to decode the audio
48cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * into a raw 16-bit PCM mono or stereo stream. This allows applications
49cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * to ship with compressed streams without having to suffer the CPU load
50cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * and latency of decompressing during playback.</p>
51cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
52cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>In addition to low-latency playback, SoundPool can also manage the number
53cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * of audio streams being rendered at once. When the SoundPool object is
54cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * constructed, the maxStreams parameter sets the maximum number of streams
55cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * that can be played at a time from this single SoundPool. SoundPool tracks
56cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the number of active streams. If the maximum number of streams is exceeded,
57cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * SoundPool will automatically stop a previously playing stream based first
58cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * on priority and then by age within that priority. Limiting the maximum
59cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * number of streams helps to cap CPU loading and reducing the likelihood that
60cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * audio mixing will impact visuals or UI performance.</p>
61cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>Sounds can be looped by setting a non-zero loop value. A value of -1
636cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * causes the sound to loop forever. In this case, the application must
646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * explicitly call the stop() function to stop the sound. Any other non-zero
656cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * value will cause the sound to repeat the specified number of times, e.g.
666cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * a value of 3 causes the sound to play a total of 4 times.</p>
676cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
686cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>The playback rate can also be changed. A playback rate of 1.0 causes
696cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the sound to play at its original frequency (resampled, if necessary,
706cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * to the hardware output frequency). A playback rate of 2.0 causes the
716cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * sound to play at twice its original frequency, and a playback rate of
726cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * 0.5 causes it to play at half its original frequency. The playback
736cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * rate range is 0.5 to 2.0.</p>
746cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
75cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Priority runs low to high, i.e. higher numbers are higher priority.
76cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * Priority is used when a call to play() would cause the number of active
77cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * streams to exceed the value established by the maxStreams parameter when
78cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the SoundPool was created. In this case, the stream allocator will stop
79cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the lowest priority stream. If there are multiple streams with the same
80cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * low priority, it will choose the oldest stream to stop. In the case
81cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * where the priority of the new stream is lower than all the active
82cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * streams, the new sound will not play and the play() function will return
83cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * a streamID of zero.</p>
84cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
85cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Let's examine a typical use case: A game consists of several levels of
86cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * play. For each level, there is a set of unique sounds that are used only
87cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * by that level. In this case, the game logic should create a new SoundPool
88cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * object when the first level is loaded. The level data itself might contain
89cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the list of sounds to be used by this level. The loading logic iterates
90cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * through the list of sounds calling the appropriate SoundPool.load()
91cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * function. This should typically be done early in the process to allow time
92cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * for decompressing the audio to raw PCM format before they are needed for
93cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * playback.</p>
94cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
95cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Once the sounds are loaded and play has started, the application can
96cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * trigger sounds by calling SoundPool.play(). Playing streams can be
97cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * paused or resumed, and the application can also alter the pitch by
98cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * adjusting the playback rate in real-time for doppler or synthesis
99cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * effects.</p>
100cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
1016cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>Note that since streams can be stopped due to resource constraints, the
1026cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * streamID is a reference to a particular instance of a stream. If the stream
1036cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * is stopped to allow a higher priority stream to play, the stream is no
1046cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * longer be valid. However, the application is allowed to call methods on
1056cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the streamID without error. This may help simplify program logic since
1066cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the application need not concern itself with the stream lifecycle.</p>
1076cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
108cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>In our example, when the player has completed the level, the game
109cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * logic should call SoundPool.release() to release all the native resources
110cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * in use and then set the SoundPool reference to null. If the player starts
111cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * another level, a new SoundPool is created, sounds are loaded, and play
112cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * resumes.</p>
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
114e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrillpublic class SoundPool {
115e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    private final SoundPoolDelegate mImpl;
116f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
117cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
118cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * Constructor. Constructs a SoundPool object with the following
119cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * characteristics:
120cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
121cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param maxStreams the maximum number of simultaneous streams for this
122cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   SoundPool object
123cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamType the audio stream type as described in AudioManager
124cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   For example, game applications will normally use
125cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   {@link AudioManager#STREAM_MUSIC}.
126cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param srcQuality the sample-rate converter quality. Currently has no
127cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   effect. Use 0 for the default.
128cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a SoundPool object, or null if creation failed
129fb52139bd81e8ac53ec923b005f10c5cb7d80e0cJean-Michel Trivi     * @deprecated use {@link SoundPool.Builder} instead to create and configure a
130fb52139bd81e8ac53ec923b005f10c5cb7d80e0cJean-Michel Trivi     *     SoundPool instance
131cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SoundPool(int maxStreams, int streamType, int srcQuality) {
13355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        this(maxStreams,
13455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
13555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi    }
13655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi
13755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi    private SoundPool(int maxStreams, AudioAttributes attributes) {
138e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        if (SystemProperties.getBoolean("config.disable_media", false)) {
139e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            mImpl = new SoundPoolStub();
140e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        } else {
14155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            mImpl = new SoundPoolImpl(this, maxStreams, attributes);
14255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        }
14355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi    }
14455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi
14555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi    /**
14655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi     * Builder class for {@link SoundPool} objects.
14755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi     */
14855a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi    public static class Builder {
14955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        private int mMaxStreams = 1;
15055a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        private AudioAttributes mAudioAttributes;
15155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi
15255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        /**
15355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * Constructs a new Builder with the defaults format values.
1542d17128f6e9954a818a71513ad6da4180e95356bJean-Michel Trivi         * If not provided, the maximum number of streams is 1 (see {@link #setMaxStreams(int)} to
1552d17128f6e9954a818a71513ad6da4180e95356bJean-Michel Trivi         * change it), and the audio attributes have a usage value of
1562d17128f6e9954a818a71513ad6da4180e95356bJean-Michel Trivi         * {@link AudioAttributes#USAGE_MEDIA} (see {@link #setAudioAttributes(AudioAttributes)} to
1572d17128f6e9954a818a71513ad6da4180e95356bJean-Michel Trivi         * change them).
15855a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         */
15955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        public Builder() {
16055a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        }
16155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi
16255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        /**
16355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * Sets the maximum of number of simultaneous streams that can be played simultaneously.
16455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * @param maxStreams a value equal to 1 or greater.
16555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * @return the same Builder instance
16655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * @throws IllegalArgumentException
16755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         */
16855a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        public Builder setMaxStreams(int maxStreams) throws IllegalArgumentException {
16955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            if (maxStreams <= 0) {
17055a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                throw new IllegalArgumentException(
171fb52139bd81e8ac53ec923b005f10c5cb7d80e0cJean-Michel Trivi                        "Strictly positive value required for the maximum number of streams");
17255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            }
17355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            mMaxStreams = maxStreams;
17455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            return this;
17555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        }
17655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi
17755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        /**
17855a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * Sets the {@link AudioAttributes}. For examples, game applications will use attributes
17955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * built with usage information set to {@link AudioAttributes#USAGE_GAME}.
18055a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * @param attributes a non-null
18155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         * @return
18255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi         */
18355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        public Builder setAudioAttributes(AudioAttributes attributes)
18455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                throws IllegalArgumentException {
18555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            if (attributes == null) {
18655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                throw new IllegalArgumentException("Invalid null AudioAttributes");
18755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            }
18855a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            mAudioAttributes = attributes;
18955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            return this;
19055a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        }
19155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi
19255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        public SoundPool build() {
19355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            if (mAudioAttributes == null) {
19455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                mAudioAttributes = new AudioAttributes.Builder()
19555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                        .setUsage(AudioAttributes.USAGE_MEDIA).build();
19655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            }
19755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            return new SoundPool(mMaxStreams, mAudioAttributes);
198f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
201cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2026cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from the specified path.
2036cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
204cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param path the path to the audio file
2056cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2066cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
207cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
208cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
209e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public int load(String path, int priority) {
210e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        return mImpl.load(path, priority);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
213cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2146cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from the specified APK resource.
215cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2166cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Note that the extension is dropped. For example, if you want to load
217cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * a sound from the raw resource file "explosion.mp3", you would specify
218cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * "R.raw.explosion" as the resource ID. Note that this means you cannot
219cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * have both an "explosion.wav" and an "explosion.mp3" in the res/raw
2206cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * directory.
221cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
222cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param context the application context
223cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param resId the resource ID
2246cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2256cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
226cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
227cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(Context context, int resId, int priority) {
229e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        return mImpl.load(context, resId, priority);
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
232cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2336cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from an asset file descriptor.
234cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
235cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param afd an asset file descriptor
2366cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2376cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
238cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
239cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(AssetFileDescriptor afd, int priority) {
241e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        return mImpl.load(afd, priority);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
244cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2456cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from a FileDescriptor.
246cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2476cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * This version is useful if you store multiple sounds in a single
248cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * binary. The offset specifies the offset from the start of the file
2496cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * and the length specifies the length of the sound within the file.
250cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
251cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param fd a FileDescriptor object
252cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param offset offset to the start of the sound
253cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param length length of the sound
2546cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2556cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
256cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
257cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(FileDescriptor fd, long offset, long length, int priority) {
259e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        return mImpl.load(fd, offset, length, priority);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
262cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2636cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Unload a sound from a sound ID.
264cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2656cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Unloads the sound specified by the soundID. This is the value
266cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * returned by the load() function. Returns true if the sound is
2676cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * successfully unloaded, false if the sound was already unloaded.
268cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
269cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param soundID a soundID returned by the load() function
270cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return true if just unloaded, false if previously unloaded
271cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
272e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final boolean unload(int soundID) {
273e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        return mImpl.unload(soundID);
274e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
276cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2776cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Play a sound from a sound ID.
278cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2796cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Play the sound specified by the soundID. This is the value
280cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * returned by the load() function. Returns a non-zero streamID
281cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * if successful, zero if it fails. The streamID can be used to
282cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * further control playback. Note that calling play() may cause
283cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * another sound to stop playing if the maximum number of active
2846cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * streams is exceeded. A loop value of -1 means loop forever,
2856cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * a value of 0 means don't loop, other values indicate the
2866cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * number of repeats, e.g. a value of 1 plays the audio twice.
2876cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * The playback rate allows the application to vary the playback
2886cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * rate (pitch) of the sound. A value of 1.0 means play back at
2896cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * the original frequency. A value of 2.0 means play back twice
2906cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * as fast, and a value of 0.5 means playback at half speed.
291cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
292cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param soundID a soundID returned by the load() function
2936cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param leftVolume left volume value (range = 0.0 to 1.0)
2946cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rightVolume right volume value (range = 0.0 to 1.0)
2956cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority stream priority (0 = lowest priority)
2966cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param loop loop mode (0 = no loop, -1 = loop forever)
2976cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
298cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return non-zero streamID if successful, zero if failed
299cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
300e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final int play(int soundID, float leftVolume, float rightVolume,
301e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            int priority, int loop, float rate) {
302e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        return mImpl.play(
303e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            soundID, leftVolume, rightVolume, priority, loop, rate);
304e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
306cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3076cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Pause a playback stream.
308cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3096cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Pause the stream specified by the streamID. This is the
310cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * value returned by the play() function. If the stream is
311cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * playing, it will be paused. If the stream is not playing
312cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * (e.g. is stopped or was previously paused), calling this
3136cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * function will have no effect.
314cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
315cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
316cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
317e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void pause(int streamID) {
318e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.pause(streamID);
319e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
321cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3226cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Resume a playback stream.
323cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3246cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Resume the stream specified by the streamID. This
325cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is the value returned by the play() function. If the stream
326cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is paused, this will resume playback. If the stream was not
3276cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * previously paused, calling this function will have no effect.
328cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
329cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
330cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
331e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void resume(int streamID) {
332e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.resume(streamID);
333e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
335cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
336f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Pause all active streams.
337f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     *
338f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Pause all streams that are currently playing. This function
339f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * iterates through all the active streams and pauses any that
340f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * are playing. It also sets a flag so that any streams that
341f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * are playing can be resumed by calling autoResume().
342f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     */
343e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void autoPause() {
344e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.autoPause();
345e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
346f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks
347f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks    /**
348f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Resume all previously active streams.
349f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     *
350f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Automatically resumes all streams that were paused in previous
351f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * calls to autoPause().
352f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     */
353e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void autoResume() {
354e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.autoResume();
355e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
356f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks
357f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks    /**
3586cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Stop a playback stream.
359cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3606cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Stop the stream specified by the streamID. This
361cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is the value returned by the play() function. If the stream
362cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is playing, it will be stopped. It also releases any native
363cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * resources associated with this stream. If the stream is not
3646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * playing, it will have no effect.
365cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
366cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
367cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
368e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void stop(int streamID) {
369e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.stop(streamID);
370e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
372cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3736cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Set stream volume.
374cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3756cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Sets the volume on the stream specified by the streamID.
376cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * This is the value returned by the play() function. The
377cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * value must be in the range of 0.0 to 1.0. If the stream does
3786cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * not exist, it will have no effect.
379cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
380cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
381cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param leftVolume left volume value (range = 0.0 to 1.0)
382cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param rightVolume right volume value (range = 0.0 to 1.0)
383cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
384e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void setVolume(int streamID,
385e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            float leftVolume, float rightVolume) {
386e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.setVolume(streamID, leftVolume, rightVolume);
387e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
390068225de0197df07a0247b2877666ea91c22c992Glenn Kasten     * Similar, except set volume of all channels to same value.
391068225de0197df07a0247b2877666ea91c22c992Glenn Kasten     * @hide
392068225de0197df07a0247b2877666ea91c22c992Glenn Kasten     */
393068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    public void setVolume(int streamID, float volume) {
394068225de0197df07a0247b2877666ea91c22c992Glenn Kasten        setVolume(streamID, volume, volume);
395068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    }
396068225de0197df07a0247b2877666ea91c22c992Glenn Kasten
397068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    /**
3986cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change stream priority.
399cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
4006cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change the priority of the stream specified by the streamID.
401cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * This is the value returned by the play() function. Affects the
4026cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * order in which streams are re-used to play new sounds. If the
4036cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * stream does not exist, it will have no effect.
404cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
405cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
406cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
407e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void setPriority(int streamID, int priority) {
408e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.setPriority(streamID, priority);
409e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
411cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
4126cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Set loop mode.
413cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
4146cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change the loop mode. A loop value of -1 means loop forever,
4156cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * a value of 0 means don't loop, other values indicate the
4166cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * number of repeats, e.g. a value of 1 plays the audio twice.
4176cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * If the stream does not exist, it will have no effect.
418cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
419cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
4206cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param loop loop mode (0 = no loop, -1 = loop forever)
421cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
422e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void setLoop(int streamID, int loop) {
423e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.setLoop(streamID, loop);
424e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4266cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks    /**
4276cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change playback rate.
4286cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
4296cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * The playback rate allows the application to vary the playback
4306cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * rate (pitch) of the sound. A value of 1.0 means playback at
4316cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * the original frequency. A value of 2.0 means playback twice
4326cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * as fast, and a value of 0.5 means playback at half speed.
4336cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * If the stream does not exist, it will have no effect.
4346cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
4356cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param streamID a streamID returned by the play() function
4366cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
4376cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     */
438e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void setRate(int streamID, float rate) {
439e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.setRate(streamID, rate);
440e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
442e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public interface OnLoadCompleteListener {
443f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        /**
444f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * Called when a sound has completed loading.
445f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         *
446f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param soundPool SoundPool object from the load() method
44736b692d8ef595eee1e28d20b740be548365a5671David Friedman         * @param sampleId the sample ID of the sound loaded.
448f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param status the status of the load operation (0 = success)
449f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         */
450f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public void onLoadComplete(SoundPool soundPool, int sampleId, int status);
451f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
452f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
453f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    /**
454f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * Sets the callback hook for the OnLoadCompleteListener.
455f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     */
456e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public void setOnLoadCompleteListener(OnLoadCompleteListener listener) {
457e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.setOnLoadCompleteListener(listener);
458e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
459e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
460e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    /**
461e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * Release the SoundPool resources.
462e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     *
463e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * Release all memory and native resources used by the SoundPool
464e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * object. The SoundPool can no longer be used and the reference
465e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * should be set to null.
466e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     */
467e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    public final void release() {
468e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        mImpl.release();
469e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
470e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
471e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    /**
472e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * Interface for SoundPool implementations.
473e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * SoundPool is statically referenced and unconditionally called from all
474e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * over the framework, so we can't simply omit the class or make it throw
475e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * runtime exceptions, as doing so would break the framework. Instead we
476e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * now select either a real or no-op impl object based on whether media is
477e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * enabled.
478e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     *
479e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * @hide
480e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     */
481e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    /* package */ interface SoundPoolDelegate {
482e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(String path, int priority);
483e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(Context context, int resId, int priority);
484e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(AssetFileDescriptor afd, int priority);
485e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(
486e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                FileDescriptor fd, long offset, long length, int priority);
487e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public boolean unload(int soundID);
488e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int play(
489e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                int soundID, float leftVolume, float rightVolume,
490e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                int priority, int loop, float rate);
491e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void pause(int streamID);
492e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void resume(int streamID);
493e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void autoPause();
494e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void autoResume();
495e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void stop(int streamID);
496e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setVolume(int streamID, float leftVolume, float rightVolume);
497e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setVolume(int streamID, float volume);
498e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setPriority(int streamID, int priority);
499e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setLoop(int streamID, int loop);
500e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setRate(int streamID, float rate);
501e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setOnLoadCompleteListener(OnLoadCompleteListener listener);
502e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void release();
503e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
504e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
505e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
506e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    /**
507e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * Real implementation of the delegate interface. This was formerly the
508e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * body of SoundPool itself.
509e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     */
510e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    /* package */ static class SoundPoolImpl implements SoundPoolDelegate {
511e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        static { System.loadLibrary("soundpool"); }
512e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
513e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private final static String TAG = "SoundPool";
514e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private final static boolean DEBUG = false;
515e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
516075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        private long mNativeContext; // accessed by native methods
517e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
518e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private EventHandler mEventHandler;
519e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener;
520e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private SoundPool mProxy;
521e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
522e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private final Object mLock;
52355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        private final AudioAttributes mAttributes;
5241af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        private final IAppOpsService mAppOps;
525e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
526e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        // SoundPool messages
527e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        //
528e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        // must match SoundPool.h
529e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private static final int SAMPLE_LOADED = 1;
530e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
53155a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        public SoundPoolImpl(SoundPool proxy, int maxStreams, AudioAttributes attr) {
532e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
533e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            // do native setup
53455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            if (native_setup(new WeakReference(this), maxStreams, attr) != 0) {
535e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                throw new RuntimeException("Native setup failed");
536e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            }
537e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            mLock = new Object();
538e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            mProxy = proxy;
53955a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi            mAttributes = attr;
5401af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
5411af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            mAppOps = IAppOpsService.Stub.asInterface(b);
542e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
543e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
544e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(String path, int priority)
545e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        {
546e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            // pass network streams to player
547e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            if (path.startsWith("http:"))
548e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                return _load(path, priority);
549e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
550e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            // try local path
551e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            int id = 0;
552e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            try {
553e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                File f = new File(path);
554e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
555e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                if (fd != null) {
556e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    id = _load(fd.getFileDescriptor(), 0, f.length(), priority);
557e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    fd.close();
558a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent                }
559e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            } catch (java.io.IOException e) {
560e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                Log.e(TAG, "error loading " + path);
561e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            }
562e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return id;
563e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
564e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
565e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(Context context, int resId, int priority) {
566e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
567e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            int id = 0;
568e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            if (afd != null) {
569e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                id = _load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), priority);
570e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                try {
571e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    afd.close();
572e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                } catch (java.io.IOException ex) {
573e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    //Log.d(TAG, "close failed:", ex);
574e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                }
575e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            }
576e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return id;
577e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
578e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
579e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(AssetFileDescriptor afd, int priority) {
580e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            if (afd != null) {
581e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                long len = afd.getLength();
582e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                if (len < 0) {
583e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    throw new AndroidRuntimeException("no length for fd");
584e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                }
585e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                return _load(afd.getFileDescriptor(), afd.getStartOffset(), len, priority);
586a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            } else {
587e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                return 0;
588a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            }
589f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
590f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
591e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(FileDescriptor fd, long offset, long length, int priority) {
592e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return _load(fd, offset, length, priority);
593e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
594e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
595e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private native final int _load(String uri, int priority);
596e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
597e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private native final int _load(FileDescriptor fd, long offset, long length, int priority);
598e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
599e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final boolean unload(int soundID);
600e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
6011af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        public final int play(int soundID, float leftVolume, float rightVolume,
6021af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                int priority, int loop, float rate) {
6031af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            if (isRestricted()) {
6041af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                leftVolume = rightVolume = 0;
6051af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
6061af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            return _play(soundID, leftVolume, rightVolume, priority, loop, rate);
6071af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
6081af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
6091af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        public native final int _play(int soundID, float leftVolume, float rightVolume,
610e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                int priority, int loop, float rate);
611e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
6121af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        private boolean isRestricted() {
6131af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            try {
6141af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
61555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                        mAttributes.getUsage(),
61655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                        Process.myUid(), ActivityThread.currentPackageName());
6171af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                return mode != AppOpsManager.MODE_ALLOWED;
6181af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            } catch (RemoteException e) {
6191af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                return false;
6201af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
6211af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
6221af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
623e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void pause(int streamID);
624e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
625e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void resume(int streamID);
626e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
627e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void autoPause();
628e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
629e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void autoResume();
630e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
631e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void stop(int streamID);
632f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
6331af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        public final void setVolume(int streamID, float leftVolume, float rightVolume) {
6341af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            if (isRestricted()) {
6351af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                return;
6361af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
6371af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            _setVolume(streamID, leftVolume, rightVolume);
6381af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
6391af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
6401af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
641e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
642e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setVolume(int streamID, float volume) {
643e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            setVolume(streamID, volume, volume);
644f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
645f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
646e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void setPriority(int streamID, int priority);
647e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
648e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void setLoop(int streamID, int loop);
649e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
650e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void setRate(int streamID, float rate);
651e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
652e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
653e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        {
654e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            synchronized(mLock) {
655e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                if (listener != null) {
656e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    // setup message handler
657e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    Looper looper;
658e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    if ((looper = Looper.myLooper()) != null) {
659e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                        mEventHandler = new EventHandler(mProxy, looper);
660e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    } else if ((looper = Looper.getMainLooper()) != null) {
661e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                        mEventHandler = new EventHandler(mProxy, looper);
662e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    } else {
663e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                        mEventHandler = null;
664f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                    }
665e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                } else {
666e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    mEventHandler = null;
667f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                }
668e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                mOnLoadCompleteListener = listener;
669f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            }
670f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
671f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
672e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private class EventHandler extends Handler
673e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        {
674e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            private SoundPool mSoundPool;
675e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
676e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            public EventHandler(SoundPool soundPool, Looper looper) {
677e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                super(looper);
678e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                mSoundPool = soundPool;
679e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            }
680f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
681e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            @Override
682e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            public void handleMessage(Message msg) {
683e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                switch(msg.what) {
684e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                case SAMPLE_LOADED:
685e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
686e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    synchronized(mLock) {
687e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                        if (mOnLoadCompleteListener != null) {
688e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                            mOnLoadCompleteListener.onLoadComplete(mSoundPool, msg.arg1, msg.arg2);
689e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                        }
690e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    }
691e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    break;
692e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                default:
693e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    Log.e(TAG, "Unknown message type " + msg.what);
694e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                    return;
695e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                }
696e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            }
697f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
698e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
699e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        // post event from native code to message handler
700e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        private static void postEventFromNative(Object weakRef, int msg, int arg1, int arg2, Object obj)
701e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        {
702e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            SoundPoolImpl soundPoolImpl = (SoundPoolImpl)((WeakReference)weakRef).get();
703e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            if (soundPoolImpl == null)
704e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                return;
705e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
706e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            if (soundPoolImpl.mEventHandler != null) {
707e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                Message m = soundPoolImpl.mEventHandler.obtainMessage(msg, arg1, arg2, obj);
708e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                soundPoolImpl.mEventHandler.sendMessage(m);
709e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            }
710e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
711e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
712e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public native final void release();
713e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
71455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi        private native final int native_setup(Object weakRef, int maxStreams,
71555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi                Object/*AudioAttributes*/ attributes);
716e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
717e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        protected void finalize() { release(); }
718f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
719f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
720f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    /**
721e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * No-op implementation of SoundPool.
722e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * Used when media is disabled by the system.
723e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill     * @hide
7246cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     */
725e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    /* package */ static class SoundPoolStub implements SoundPoolDelegate {
726e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public SoundPoolStub() { }
727e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
728e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(String path, int priority) {
729e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return 0;
730e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
731e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
732e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(Context context, int resId, int priority) {
733e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return 0;
734e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
735e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
736e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(AssetFileDescriptor afd, int priority) {
737e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return 0;
738e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
739e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
740e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public int load(FileDescriptor fd, long offset, long length, int priority) {
741e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return 0;
742e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
743e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
744e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final boolean unload(int soundID) {
745e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return true;
746e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
747e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
748e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final int play(int soundID, float leftVolume, float rightVolume,
749e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                int priority, int loop, float rate) {
750e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill            return 0;
751e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
752e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
753e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void pause(int streamID) { }
754e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
755e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void resume(int streamID) { }
756e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
757e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void autoPause() { }
758e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
759e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void autoResume() { }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
761e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void stop(int streamID) { }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
763e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void setVolume(int streamID,
764e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill                float leftVolume, float rightVolume) { }
765e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
766e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setVolume(int streamID, float volume) {
767e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
768e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
769e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void setPriority(int streamID, int priority) { }
770e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
771e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void setLoop(int streamID, int loop) { }
772e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
773e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void setRate(int streamID, float rate) { }
774e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
775e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) {
776e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        }
777e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill
778e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill        public final void release() { }
779e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill    }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
781