Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media.cts;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.NonNull;
     21 import android.util.Log;
     22 
     23 import com.android.compatibility.common.util.CtsAndroidTestCase;
     24 
     25 import java.lang.annotation.Retention;
     26 import java.lang.annotation.RetentionPolicy;
     27 
     28 public class AudioTrackNative {
     29     // Must be kept in sync with C++ JNI audio-track-native (AudioTrackNative) WRITE_FLAG_*
     30     public static final int WRITE_FLAG_BLOCKING = 1 << 0;
     31     /** @hide */
     32     @IntDef(flag = true,
     33             value = {
     34                     WRITE_FLAG_BLOCKING,
     35             })
     36     @Retention(RetentionPolicy.SOURCE)
     37     public @interface WriteFlags { }
     38 
     39     public AudioTrackNative() {
     40         mNativeTrackInJavaObj = nativeCreateTrack();
     41     }
     42 
     43     // TODO: eventually accept AudioFormat
     44     // numBuffers is the number of internal buffers before hitting the OpenSL ES.
     45     // A value of 0 means that all writes are blocking.
     46     public boolean open(int numChannels, int sampleRate, boolean useFloat, int numBuffers) {
     47         return open(numChannels, 0, sampleRate, useFloat, numBuffers);
     48     }
     49 
     50     public boolean open(int numChannels, int channelMask, int sampleRate,
     51             boolean useFloat, int numBuffers) {
     52         if (nativeOpen(mNativeTrackInJavaObj, numChannels, channelMask,
     53                 sampleRate, useFloat, numBuffers) == STATUS_OK) {
     54             mChannelCount = numChannels;
     55             return true;
     56         }
     57         return false;
     58     }
     59 
     60     public void close() {
     61         nativeClose(mNativeTrackInJavaObj);
     62     }
     63 
     64     public boolean start() {
     65         return nativeStart(mNativeTrackInJavaObj) == STATUS_OK;
     66     }
     67 
     68     public boolean stop() {
     69         return nativeStop(mNativeTrackInJavaObj) == STATUS_OK;
     70     }
     71 
     72     public boolean pause() {
     73         return nativePause(mNativeTrackInJavaObj) == STATUS_OK;
     74     }
     75 
     76     public boolean flush() {
     77         return nativeFlush(mNativeTrackInJavaObj) == STATUS_OK;
     78     }
     79 
     80     public long getPositionInMsec() {
     81         long[] position = new long[1];
     82         if (nativeGetPositionInMsec(mNativeTrackInJavaObj, position) != STATUS_OK) {
     83             throw new IllegalStateException();
     84         }
     85         return position[0];
     86     }
     87 
     88     public int getBuffersPending() {
     89         return nativeGetBuffersPending(mNativeTrackInJavaObj);
     90     }
     91 
     92     /* returns number of samples written.
     93      * 0 may be returned if !isBlocking.
     94      * negative value indicates error.
     95      */
     96     public int write(@NonNull byte[] byteArray,
     97             int offsetInSamples, int sizeInSamples, @WriteFlags int writeFlags) {
     98         return nativeWriteByteArray(
     99                 mNativeTrackInJavaObj, byteArray, offsetInSamples, sizeInSamples, writeFlags);
    100     }
    101 
    102     public int write(@NonNull short[] shortArray,
    103             int offsetInSamples, int sizeInSamples, @WriteFlags int writeFlags) {
    104         return nativeWriteShortArray(
    105                 mNativeTrackInJavaObj, shortArray, offsetInSamples, sizeInSamples, writeFlags);
    106     }
    107 
    108     public int write(@NonNull float[] floatArray,
    109             int offsetInSamples, int sizeInSamples, @WriteFlags int writeFlags) {
    110         return nativeWriteFloatArray(
    111                 mNativeTrackInJavaObj, floatArray, offsetInSamples, sizeInSamples, writeFlags);
    112     }
    113 
    114     public int getChannelCount() {
    115         return mChannelCount;
    116     }
    117 
    118     public static boolean test(int numChannels, int sampleRate, boolean useFloat,
    119             int msecPerBuffer, int numBuffers) {
    120         return test(numChannels, 0, sampleRate, useFloat, msecPerBuffer, numBuffers);
    121     }
    122 
    123     public static boolean test(int numChannels, int channelMask, int sampleRate, boolean useFloat,
    124             int msecPerBuffer, int numBuffers) {
    125         return nativeTest(numChannels, channelMask, sampleRate, useFloat, msecPerBuffer, numBuffers)
    126                 == STATUS_OK;
    127     }
    128 
    129     @Override
    130     protected void finalize() {
    131         nativeClose(mNativeTrackInJavaObj);
    132         nativeDestroyTrack(mNativeTrackInJavaObj);
    133     }
    134 
    135     static {
    136         System.loadLibrary("audio_jni");
    137     }
    138 
    139     private static final String TAG = "AudioTrackNative";
    140     private int mChannelCount;
    141     private final long mNativeTrackInJavaObj;
    142     private static final int STATUS_OK = 0;
    143 
    144     // static native API.
    145     // The native API uses a long "track handle" created by nativeCreateTrack.
    146     // The handle must be destroyed after use by nativeDestroyTrack.
    147     //
    148     // Return codes from the native layer are status_t.
    149     // Converted to Java booleans or exceptions at the public API layer.
    150     private static native long nativeCreateTrack();
    151     private static native void nativeDestroyTrack(long track);
    152     private static native int nativeOpen(
    153             long track, int numChannels, int channelMask,
    154             int sampleRate, boolean useFloat, int numBuffers);
    155     private static native void nativeClose(long track);
    156     private static native int nativeStart(long track);
    157     private static native int nativeStop(long track);
    158     private static native int nativePause(long track);
    159     private static native int nativeFlush(long track);
    160     private static native int nativeGetPositionInMsec(long track, @NonNull long[] position);
    161     private static native int nativeGetBuffersPending(long track);
    162     private static native int nativeWriteByteArray(long track, @NonNull byte[] byteArray,
    163             int offsetInSamples, int sizeInSamples, @WriteFlags int writeFlags);
    164     private static native int nativeWriteShortArray(long track, @NonNull short[] shortArray,
    165             int offsetInSamples, int sizeInSamples, @WriteFlags int writeFlags);
    166     private static native int nativeWriteFloatArray(long track, @NonNull float[] floatArray,
    167             int offsetInSamples, int sizeInSamples, @WriteFlags int writeFlags);
    168 
    169     // native interface for all-in-one testing, no track handle required.
    170     private static native int nativeTest(
    171             int numChannels, int channelMask, int sampleRate,
    172             boolean useFloat, int msecPerBuffer, int numBuffers);
    173 }
    174