1/* 2 * Copyright (C) 2016 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 17package android.media; 18 19import android.annotation.IntDef; 20import android.os.Parcel; 21import android.os.Parcelable; 22import android.util.Log; 23 24import java.lang.annotation.Retention; 25import java.lang.annotation.RetentionPolicy; 26import java.util.ArrayList; 27import java.util.Objects; 28 29/** 30 * The AudioRecordingConfiguration class collects the information describing an audio recording 31 * session. This information is returned through the 32 * {@link AudioManager#getActiveRecordingConfigurations()} method. 33 * 34 */ 35public final class AudioRecordingConfiguration implements Parcelable { 36 private final static String TAG = new String("AudioRecordingConfiguration"); 37 38 private final int mSessionId; 39 40 private final int mClientSource; 41 42 private final AudioFormat mDeviceFormat; 43 private final AudioFormat mClientFormat; 44 45 private final int mPatchHandle; 46 47 /** 48 * @hide 49 */ 50 public AudioRecordingConfiguration(int session, int source, AudioFormat devFormat, 51 AudioFormat clientFormat, int patchHandle) { 52 mSessionId = session; 53 mClientSource = source; 54 mDeviceFormat = devFormat; 55 mClientFormat = clientFormat; 56 mPatchHandle = patchHandle; 57 } 58 59 // matches the sources that return false in MediaRecorder.isSystemOnlyAudioSource(source) 60 /** @hide */ 61 @IntDef({ 62 MediaRecorder.AudioSource.DEFAULT, 63 MediaRecorder.AudioSource.MIC, 64 MediaRecorder.AudioSource.VOICE_UPLINK, 65 MediaRecorder.AudioSource.VOICE_DOWNLINK, 66 MediaRecorder.AudioSource.VOICE_CALL, 67 MediaRecorder.AudioSource.CAMCORDER, 68 MediaRecorder.AudioSource.VOICE_RECOGNITION, 69 MediaRecorder.AudioSource.VOICE_COMMUNICATION, 70 MediaRecorder.AudioSource.UNPROCESSED 71 }) 72 @Retention(RetentionPolicy.SOURCE) 73 public @interface AudioSource {} 74 75 // documented return values match the sources that return false 76 // in MediaRecorder.isSystemOnlyAudioSource(source) 77 /** 78 * Returns the audio source being used for the recording. 79 * @return one of {@link MediaRecorder.AudioSource#DEFAULT}, 80 * {@link MediaRecorder.AudioSource#MIC}, 81 * {@link MediaRecorder.AudioSource#VOICE_UPLINK}, 82 * {@link MediaRecorder.AudioSource#VOICE_DOWNLINK}, 83 * {@link MediaRecorder.AudioSource#VOICE_CALL}, 84 * {@link MediaRecorder.AudioSource#CAMCORDER}, 85 * {@link MediaRecorder.AudioSource#VOICE_RECOGNITION}, 86 * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}, 87 * {@link MediaRecorder.AudioSource#UNPROCESSED}. 88 */ 89 public @AudioSource int getClientAudioSource() { return mClientSource; } 90 91 /** 92 * Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}. 93 * @return the session number. 94 */ 95 public int getClientAudioSessionId() { return mSessionId; } 96 97 /** 98 * Returns the audio format at which audio is recorded on this Android device. 99 * Note that it may differ from the client application recording format 100 * (see {@link #getClientFormat()}). 101 * @return the device recording format 102 */ 103 public AudioFormat getFormat() { return mDeviceFormat; } 104 105 /** 106 * Returns the audio format at which the client application is recording audio. 107 * Note that it may differ from the actual recording format (see {@link #getFormat()}). 108 * @return the recording format 109 */ 110 public AudioFormat getClientFormat() { return mClientFormat; } 111 112 /** 113 * Returns information about the audio input device used for this recording. 114 * @return the audio recording device or null if this information cannot be retrieved 115 */ 116 public AudioDeviceInfo getAudioDevice() { 117 // build the AudioDeviceInfo from the patch handle 118 ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>(); 119 if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) { 120 Log.e(TAG, "Error retrieving list of audio patches"); 121 return null; 122 } 123 for (int i = 0 ; i < patches.size() ; i++) { 124 final AudioPatch patch = patches.get(i); 125 if (patch.id() == mPatchHandle) { 126 final AudioPortConfig[] sources = patch.sources(); 127 if ((sources != null) && (sources.length > 0)) { 128 // not supporting multiple sources, so just look at the first source 129 final int devId = sources[0].port().id(); 130 final AudioDeviceInfo[] devices = 131 AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_INPUTS); 132 for (int j = 0; j < devices.length; j++) { 133 if (devices[j].getId() == devId) { 134 return devices[j]; 135 } 136 } 137 } 138 // patch handle is unique, there won't be another with the same handle 139 break; 140 } 141 } 142 Log.e(TAG, "Couldn't find device for recording, did recording end already?"); 143 return null; 144 } 145 146 public static final Parcelable.Creator<AudioRecordingConfiguration> CREATOR 147 = new Parcelable.Creator<AudioRecordingConfiguration>() { 148 /** 149 * Rebuilds an AudioRecordingConfiguration previously stored with writeToParcel(). 150 * @param p Parcel object to read the AudioRecordingConfiguration from 151 * @return a new AudioRecordingConfiguration created from the data in the parcel 152 */ 153 public AudioRecordingConfiguration createFromParcel(Parcel p) { 154 return new AudioRecordingConfiguration(p); 155 } 156 public AudioRecordingConfiguration[] newArray(int size) { 157 return new AudioRecordingConfiguration[size]; 158 } 159 }; 160 161 @Override 162 public int hashCode() { 163 return Objects.hash(mSessionId, mClientSource); 164 } 165 166 @Override 167 public int describeContents() { 168 return 0; 169 } 170 171 @Override 172 public void writeToParcel(Parcel dest, int flags) { 173 dest.writeInt(mSessionId); 174 dest.writeInt(mClientSource); 175 mClientFormat.writeToParcel(dest, 0); 176 mDeviceFormat.writeToParcel(dest, 0); 177 dest.writeInt(mPatchHandle); 178 } 179 180 private AudioRecordingConfiguration(Parcel in) { 181 mSessionId = in.readInt(); 182 mClientSource = in.readInt(); 183 mClientFormat = AudioFormat.CREATOR.createFromParcel(in); 184 mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in); 185 mPatchHandle = in.readInt(); 186 } 187 188 @Override 189 public boolean equals(Object o) { 190 if (this == o) return true; 191 if (o == null || !(o instanceof AudioRecordingConfiguration)) return false; 192 193 AudioRecordingConfiguration that = (AudioRecordingConfiguration) o; 194 195 return ((mSessionId == that.mSessionId) 196 && (mClientSource == that.mClientSource) 197 && (mPatchHandle == that.mPatchHandle) 198 && (mClientFormat.equals(that.mClientFormat)) 199 && (mDeviceFormat.equals(that.mDeviceFormat))); 200 } 201}