blob: 50dbd035b84da2a2bebbeb4916361ea215d2e3c0 [file] [log] [blame]
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001/*
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
Jean-Michel Trivi28ff76b2016-03-02 09:36:30 -080019import android.annotation.IntDef;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080020import android.os.Parcel;
21import android.os.Parcelable;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -080022import android.util.Log;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080023
Jean-Michel Trivi28ff76b2016-03-02 09:36:30 -080024import java.lang.annotation.Retention;
25import java.lang.annotation.RetentionPolicy;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -080026import java.util.ArrayList;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080027import java.util.Objects;
28
29/**
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -080030 * The AudioRecordingConfiguration class collects the information describing an audio recording
Jean-Michel Trivi7872aff2016-07-06 14:34:52 -070031 * session.
32 * <p>Direct polling (see {@link AudioManager#getActiveRecordingConfigurations()}) or callback
33 * (see {@link AudioManager#registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler)}
34 * methods are ways to receive information about the current recording configuration of the device.
35 * <p>An audio recording configuration contains information about the recording format as used by
36 * the application ({@link #getClientFormat()}, as well as the recording format actually used by
37 * the device ({@link #getFormat()}). The two recording formats may, for instance, be at different
38 * sampling rates due to hardware limitations (e.g. application recording at 44.1kHz whereas the
39 * device always records at 48kHz, and the Android framework resamples for the application).
40 * <p>The configuration also contains the use case for which audio is recorded
41 * ({@link #getClientAudioSource()}), enabling the ability to distinguish between different
42 * activities such as ongoing voice recognition or camcorder recording.
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080043 *
44 */
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -080045public final class AudioRecordingConfiguration implements Parcelable {
46 private final static String TAG = new String("AudioRecordingConfiguration");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080047
48 private final int mSessionId;
49
50 private final int mClientSource;
51
Jean-Michel Trivif730d872016-01-27 19:05:29 -080052 private final AudioFormat mDeviceFormat;
53 private final AudioFormat mClientFormat;
54
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -080055 private final int mPatchHandle;
Jean-Michel Trivif730d872016-01-27 19:05:29 -080056
57 /**
58 * @hide
59 */
Jean-Michel Trivi74eb6f62016-07-26 11:19:18 -070060 public AudioRecordingConfiguration(int session, int source, AudioFormat clientFormat,
61 AudioFormat devFormat, int patchHandle) {
Jean-Michel Trivif730d872016-01-27 19:05:29 -080062 mSessionId = session;
63 mClientSource = source;
Jean-Michel Trivif730d872016-01-27 19:05:29 -080064 mClientFormat = clientFormat;
Jean-Michel Trivi74eb6f62016-07-26 11:19:18 -070065 mDeviceFormat = devFormat;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -080066 mPatchHandle = patchHandle;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080067 }
68
Jean-Michel Trivi3b118922016-05-05 18:01:56 -070069 // matches the sources that return false in MediaRecorder.isSystemOnlyAudioSource(source)
Jean-Michel Trivi28ff76b2016-03-02 09:36:30 -080070 /** @hide */
71 @IntDef({
72 MediaRecorder.AudioSource.DEFAULT,
Jean-Michel Trivi3b118922016-05-05 18:01:56 -070073 MediaRecorder.AudioSource.MIC,
Jean-Michel Trivi28ff76b2016-03-02 09:36:30 -080074 MediaRecorder.AudioSource.VOICE_UPLINK,
75 MediaRecorder.AudioSource.VOICE_DOWNLINK,
76 MediaRecorder.AudioSource.VOICE_CALL,
77 MediaRecorder.AudioSource.CAMCORDER,
78 MediaRecorder.AudioSource.VOICE_RECOGNITION,
Jean-Michel Trivi3b118922016-05-05 18:01:56 -070079 MediaRecorder.AudioSource.VOICE_COMMUNICATION,
80 MediaRecorder.AudioSource.UNPROCESSED
Jean-Michel Trivi28ff76b2016-03-02 09:36:30 -080081 })
82 @Retention(RetentionPolicy.SOURCE)
83 public @interface AudioSource {}
84
Jean-Michel Trivi3b118922016-05-05 18:01:56 -070085 // documented return values match the sources that return false
86 // in MediaRecorder.isSystemOnlyAudioSource(source)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080087 /**
Jean-Michel Trivib919f6f2016-01-12 18:27:17 -080088 * Returns the audio source being used for the recording.
Jean-Michel Trivi3b118922016-05-05 18:01:56 -070089 * @return one of {@link MediaRecorder.AudioSource#DEFAULT},
90 * {@link MediaRecorder.AudioSource#MIC},
Jean-Michel Trivib919f6f2016-01-12 18:27:17 -080091 * {@link MediaRecorder.AudioSource#VOICE_UPLINK},
92 * {@link MediaRecorder.AudioSource#VOICE_DOWNLINK},
93 * {@link MediaRecorder.AudioSource#VOICE_CALL},
94 * {@link MediaRecorder.AudioSource#CAMCORDER},
95 * {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
Jean-Michel Trivi3b118922016-05-05 18:01:56 -070096 * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION},
97 * {@link MediaRecorder.AudioSource#UNPROCESSED}.
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080098 */
Jean-Michel Trivi28ff76b2016-03-02 09:36:30 -080099 public @AudioSource int getClientAudioSource() { return mClientSource; }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800100
101 /**
Jean-Michel Trivib919f6f2016-01-12 18:27:17 -0800102 * Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
103 * @return the session number.
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800104 */
Jean-Michel Trivif730d872016-01-27 19:05:29 -0800105 public int getClientAudioSessionId() { return mSessionId; }
106
107 /**
108 * Returns the audio format at which audio is recorded on this Android device.
109 * Note that it may differ from the client application recording format
110 * (see {@link #getClientFormat()}).
111 * @return the device recording format
112 */
113 public AudioFormat getFormat() { return mDeviceFormat; }
114
115 /**
116 * Returns the audio format at which the client application is recording audio.
117 * Note that it may differ from the actual recording format (see {@link #getFormat()}).
118 * @return the recording format
119 */
120 public AudioFormat getClientFormat() { return mClientFormat; }
121
122 /**
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800123 * Returns information about the audio input device used for this recording.
124 * @return the audio recording device or null if this information cannot be retrieved
Jean-Michel Trivif730d872016-01-27 19:05:29 -0800125 */
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800126 public AudioDeviceInfo getAudioDevice() {
127 // build the AudioDeviceInfo from the patch handle
128 ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
129 if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) {
130 Log.e(TAG, "Error retrieving list of audio patches");
131 return null;
132 }
133 for (int i = 0 ; i < patches.size() ; i++) {
134 final AudioPatch patch = patches.get(i);
135 if (patch.id() == mPatchHandle) {
136 final AudioPortConfig[] sources = patch.sources();
137 if ((sources != null) && (sources.length > 0)) {
138 // not supporting multiple sources, so just look at the first source
139 final int devId = sources[0].port().id();
140 final AudioDeviceInfo[] devices =
141 AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_INPUTS);
142 for (int j = 0; j < devices.length; j++) {
143 if (devices[j].getId() == devId) {
144 return devices[j];
145 }
146 }
147 }
148 // patch handle is unique, there won't be another with the same handle
149 break;
150 }
151 }
152 Log.e(TAG, "Couldn't find device for recording, did recording end already?");
153 return null;
154 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800155
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800156 public static final Parcelable.Creator<AudioRecordingConfiguration> CREATOR
157 = new Parcelable.Creator<AudioRecordingConfiguration>() {
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800158 /**
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800159 * Rebuilds an AudioRecordingConfiguration previously stored with writeToParcel().
160 * @param p Parcel object to read the AudioRecordingConfiguration from
161 * @return a new AudioRecordingConfiguration created from the data in the parcel
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800162 */
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800163 public AudioRecordingConfiguration createFromParcel(Parcel p) {
164 return new AudioRecordingConfiguration(p);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800165 }
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800166 public AudioRecordingConfiguration[] newArray(int size) {
167 return new AudioRecordingConfiguration[size];
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800168 }
169 };
170
171 @Override
172 public int hashCode() {
173 return Objects.hash(mSessionId, mClientSource);
174 }
175
176 @Override
177 public int describeContents() {
178 return 0;
179 }
180
181 @Override
182 public void writeToParcel(Parcel dest, int flags) {
183 dest.writeInt(mSessionId);
184 dest.writeInt(mClientSource);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800185 mClientFormat.writeToParcel(dest, 0);
186 mDeviceFormat.writeToParcel(dest, 0);
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800187 dest.writeInt(mPatchHandle);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800188 }
189
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800190 private AudioRecordingConfiguration(Parcel in) {
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800191 mSessionId = in.readInt();
192 mClientSource = in.readInt();
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800193 mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
194 mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800195 mPatchHandle = in.readInt();
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800196 }
197
198 @Override
199 public boolean equals(Object o) {
200 if (this == o) return true;
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800201 if (o == null || !(o instanceof AudioRecordingConfiguration)) return false;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800202
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -0800203 AudioRecordingConfiguration that = (AudioRecordingConfiguration) o;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800204
205 return ((mSessionId == that.mSessionId)
206 && (mClientSource == that.mClientSource)
207 && (mPatchHandle == that.mPatchHandle)
208 && (mClientFormat.equals(that.mClientFormat))
209 && (mDeviceFormat.equals(that.mDeviceFormat)));
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800210 }
Jean-Michel Trivi7872aff2016-07-06 14:34:52 -0700211}