Loading Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,7 @@ LOCAL_SRC_FILES += \ media/java/android/media/IMediaRouterService.aidl \ media/java/android/media/IMediaScannerListener.aidl \ media/java/android/media/IMediaScannerService.aidl \ media/java/android/media/IRecordingConfigDispatcher.aidl \ media/java/android/media/IRemoteDisplayCallback.aidl \ media/java/android/media/IRemoteDisplayProvider.aidl \ media/java/android/media/IRemoteVolumeController.aidl \ Loading core/jni/android_media_AudioSystem.cpp +29 −3 Original line number Diff line number Diff line Loading @@ -152,7 +152,8 @@ static struct { static struct { jmethodID postDynPolicyEventFromNative; } gDynPolicyEventHandlerMethods; jmethodID postRecordConfigEventFromNative; } gAudioPolicyEventHandlerMethods; static Mutex gLock; Loading Loading @@ -378,12 +379,26 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val) const char* zechars = regId.string(); jstring zestring = env->NewStringUTF(zechars); env->CallStaticVoidMethod(clazz, gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative, env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative, event, zestring, val); env->ReleaseStringUTFChars(zestring, zechars); env->DeleteLocalRef(clazz); } static void android_media_AudioSystem_recording_callback(int event, int session, int source) { JNIEnv *env = AndroidRuntime::getJNIEnv(); if (env == NULL) { return; } jclass clazz = env->FindClass(kClassPathName); env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative, event, session, source); env->DeleteLocalRef(clazz); } static jint Loading Loading @@ -1503,6 +1518,12 @@ android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz) AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback); } static void android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz) { AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback); } static jint convertAudioMixToNative(JNIEnv *env, AudioMix *nAudioMix, Loading Loading @@ -1677,6 +1698,8 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioSystem_registerPolicyMixes}, {"native_register_dynamic_policy_callback", "()V", (void *)android_media_AudioSystem_registerDynPolicyCallback}, {"native_register_recording_callback", "()V", (void *)android_media_AudioSystem_registerRecordingCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, }; Loading Loading @@ -1780,9 +1803,12 @@ int register_android_media_AudioSystem(JNIEnv *env) gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env, eventHandlerClass, "mJniCallback", "J"); gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative = gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V"); gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "recordingCallbackFromNative", "(III)V"); jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); Loading media/java/android/media/AudioManager.java +183 −17 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * AudioManager provides access to volume and ringer mode control. Loading Loading @@ -2158,28 +2159,37 @@ public class AudioManager { } /** * Handler for audio focus events coming from the audio service. * Handler for events (audio focus change, recording config change) coming from the * audio service. */ private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate = new FocusEventHandlerDelegate(); private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate = new ServiceEventHandlerDelegate(); /** * Helper class to handle the forwarding of audio focus events to the appropriate listener * Event types */ private class FocusEventHandlerDelegate { private final static int MSSG_FOCUS_CHANGE = 0; private final static int MSSG_RECORDING_CONFIG_CHANGE = 1; /** * Helper class to handle the forwarding of audio service events to the appropriate listener */ private class ServiceEventHandlerDelegate { private final Handler mHandler; FocusEventHandlerDelegate() { ServiceEventHandlerDelegate() { Looper looper; if ((looper = Looper.myLooper()) == null) { looper = Looper.getMainLooper(); } if (looper != null) { // implement the event handler delegate to receive audio focus events // implement the event handler delegate to receive events from audio service mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSSG_FOCUS_CHANGE: OnAudioFocusChangeListener listener = null; synchronized(mFocusListenerLock) { listener = findFocusListener((String)msg.obj); Loading @@ -2187,7 +2197,35 @@ public class AudioManager { if (listener != null) { Log.d(TAG, "AudioManager dispatching onAudioFocusChange(" + msg.what + ") for " + msg.obj); listener.onAudioFocusChange(msg.what); listener.onAudioFocusChange(msg.arg1); } break; case MSSG_RECORDING_CONFIG_CHANGE: // optimizing for the case of a single callback AudioRecordingCallback singleCallback = null; ArrayList<AudioRecordingCallback> multipleCallbacks = null; synchronized(mRecordCallbackLock) { if ((mRecordCallbackList != null) && (mRecordCallbackList.size() != 0)) { if (mRecordCallbackList.size() == 1) { singleCallback = mRecordCallbackList.get(0); } else { multipleCallbacks = new ArrayList<AudioRecordingCallback>( mRecordCallbackList); } } } if (singleCallback != null) { singleCallback.onRecordConfigChanged(); } else if (multipleCallbacks != null) { for (int i=0 ; i < multipleCallbacks.size() ; i++) { multipleCallbacks.get(i).onRecordConfigChanged(); } } break; default: Log.e(TAG, "Unknown event " + msg.what); } } }; Loading @@ -2204,8 +2242,9 @@ public class AudioManager { private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { public void dispatchAudioFocusChange(int focusChange, String id) { Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id); mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m); final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage( MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/, id/*obj*/); mServiceEventHandlerDelegate.getHandler().sendMessage(m); } }; Loading Loading @@ -2702,6 +2741,8 @@ public class AudioManager { } //==================================================================== // Audio policy /** * @hide * Register the given {@link AudioPolicy}. Loading Loading @@ -2754,6 +2795,131 @@ public class AudioManager { } //==================================================================== // Recording configuration /** * @hide * candidate for public API */ public static abstract class AudioRecordingCallback { /** * @hide * candidate for public API */ public void onRecordConfigChanged() {} } /** * @hide * candidate for public API * @param non-null callback */ public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { if (cb == null) { throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); } synchronized(mRecordCallbackLock) { // lazy initialization of the list of recording callbacks if (mRecordCallbackList == null) { mRecordCallbackList = new ArrayList<AudioRecordingCallback>(); } final int oldCbCount = mRecordCallbackList.size(); if (!mRecordCallbackList.contains(cb)) { mRecordCallbackList.add(cb); final int newCbCount = mRecordCallbackList.size(); if ((oldCbCount == 0) && (newCbCount > 0)) { // register binder for callbacks final IAudioService service = getService(); try { service.registerRecordingCallback(mRecCb); } catch (RemoteException e) { Log.e(TAG, "Dead object in registerRecordingCallback", e); } } } else { Log.w(TAG, "attempt to call registerAudioRecordingCallback() on a previously" + "registered callback"); } } } /** * @hide * candidate for public API * @param non-null callback */ public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { if (cb == null) { throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); } synchronized(mRecordCallbackLock) { if (mRecordCallbackList == null) { return; } final int oldCbCount = mRecordCallbackList.size(); if (mRecordCallbackList.remove(cb)) { final int newCbCount = mRecordCallbackList.size(); if ((oldCbCount > 0) && (newCbCount == 0)) { // unregister binder for callbacks final IAudioService service = getService(); try { service.unregisterRecordingCallback(mRecCb); } catch (RemoteException e) { Log.e(TAG, "Dead object in unregisterRecordingCallback", e); } } } else { Log.w(TAG, "attempt to call unregisterAudioRecordingCallback() on a callback" + " already unregistered or never registered"); } } } /** * @hide * candidate for public API * @return a non-null array of recording configurations. An array of length 0 indicates there is * no recording active when queried. */ public @NonNull AudioRecordConfiguration[] getActiveRecordConfigurations() { final IAudioService service = getService(); try { return service.getActiveRecordConfigurations(); } catch (RemoteException e) { Log.e(TAG, "Unable to retrieve active record configurations", e); return null; } } /** * constants for the recording events, to keep in sync * with frameworks/av/include/media/AudioPolicy.h */ /** @hide */ public final static int RECORD_CONFIG_EVENT_START = 1; /** @hide */ public final static int RECORD_CONFIG_EVENT_STOP = 0; /** * All operations on this list are sync'd on mRecordCallbackLock. * List is lazy-initialized in {@link #registerAudioRecordingCallback(AudioRecordingCallback)}. * List can be null. */ private List<AudioRecordingCallback> mRecordCallbackList; private final Object mRecordCallbackLock = new Object(); private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() { public void dispatchRecordingConfigChange() { final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage( MSSG_RECORDING_CONFIG_CHANGE/*what*/); mServiceEventHandlerDelegate.getHandler().sendMessage(m); } }; //===================================================================== /** * @hide * Reload audio settings. This method is called by Settings backup Loading media/java/android/media/AudioRecordConfiguration.aidl 0 → 100644 +18 −0 Original line number Diff line number Diff line /* Copyright 2016, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ package android.media; parcelable AudioRecordConfiguration; media/java/android/media/AudioRecordConfiguration.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** * @hide * Candidate for public API, see AudioManager.getActiveRecordConfiguration() * */ public class AudioRecordConfiguration implements Parcelable { private final int mSessionId; private final int mClientSource; /** * @hide */ public AudioRecordConfiguration(int session, int source) { mSessionId = session; mClientSource = source; } /** * @return one of AudioSource.MIC, AudioSource.VOICE_UPLINK, * AudioSource.VOICE_DOWNLINK, AudioSource.VOICE_CALL, * AudioSource.CAMCORDER, AudioSource.VOICE_RECOGNITION, * AudioSource.VOICE_COMMUNICATION. */ public int getClientAudioSource() { return mClientSource; } /** * @return the session number of the recorder. */ public int getAudioSessionId() { return mSessionId; } public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR = new Parcelable.Creator<AudioRecordConfiguration>() { /** * Rebuilds an AudioRecordConfiguration previously stored with writeToParcel(). * @param p Parcel object to read the AudioRecordConfiguration from * @return a new AudioRecordConfiguration created from the data in the parcel */ public AudioRecordConfiguration createFromParcel(Parcel p) { return new AudioRecordConfiguration(p); } public AudioRecordConfiguration[] newArray(int size) { return new AudioRecordConfiguration[size]; } }; @Override public int hashCode() { return Objects.hash(mSessionId, mClientSource); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mSessionId); dest.writeInt(mClientSource); } private AudioRecordConfiguration(Parcel in) { mSessionId = in.readInt(); mClientSource = in.readInt(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || !(o instanceof AudioRecordConfiguration)) return false; final AudioRecordConfiguration that = (AudioRecordConfiguration) o; return ((mSessionId == that.mSessionId) && (mClientSource == that.mClientSource)); } } No newline at end of file Loading
Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -345,6 +345,7 @@ LOCAL_SRC_FILES += \ media/java/android/media/IMediaRouterService.aidl \ media/java/android/media/IMediaScannerListener.aidl \ media/java/android/media/IMediaScannerService.aidl \ media/java/android/media/IRecordingConfigDispatcher.aidl \ media/java/android/media/IRemoteDisplayCallback.aidl \ media/java/android/media/IRemoteDisplayProvider.aidl \ media/java/android/media/IRemoteVolumeController.aidl \ Loading
core/jni/android_media_AudioSystem.cpp +29 −3 Original line number Diff line number Diff line Loading @@ -152,7 +152,8 @@ static struct { static struct { jmethodID postDynPolicyEventFromNative; } gDynPolicyEventHandlerMethods; jmethodID postRecordConfigEventFromNative; } gAudioPolicyEventHandlerMethods; static Mutex gLock; Loading Loading @@ -378,12 +379,26 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val) const char* zechars = regId.string(); jstring zestring = env->NewStringUTF(zechars); env->CallStaticVoidMethod(clazz, gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative, env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative, event, zestring, val); env->ReleaseStringUTFChars(zestring, zechars); env->DeleteLocalRef(clazz); } static void android_media_AudioSystem_recording_callback(int event, int session, int source) { JNIEnv *env = AndroidRuntime::getJNIEnv(); if (env == NULL) { return; } jclass clazz = env->FindClass(kClassPathName); env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative, event, session, source); env->DeleteLocalRef(clazz); } static jint Loading Loading @@ -1503,6 +1518,12 @@ android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz) AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback); } static void android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz) { AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback); } static jint convertAudioMixToNative(JNIEnv *env, AudioMix *nAudioMix, Loading Loading @@ -1677,6 +1698,8 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioSystem_registerPolicyMixes}, {"native_register_dynamic_policy_callback", "()V", (void *)android_media_AudioSystem_registerDynPolicyCallback}, {"native_register_recording_callback", "()V", (void *)android_media_AudioSystem_registerRecordingCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, }; Loading Loading @@ -1780,9 +1803,12 @@ int register_android_media_AudioSystem(JNIEnv *env) gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env, eventHandlerClass, "mJniCallback", "J"); gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative = gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V"); gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "recordingCallbackFromNative", "(III)V"); jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); Loading
media/java/android/media/AudioManager.java +183 −17 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * AudioManager provides access to volume and ringer mode control. Loading Loading @@ -2158,28 +2159,37 @@ public class AudioManager { } /** * Handler for audio focus events coming from the audio service. * Handler for events (audio focus change, recording config change) coming from the * audio service. */ private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate = new FocusEventHandlerDelegate(); private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate = new ServiceEventHandlerDelegate(); /** * Helper class to handle the forwarding of audio focus events to the appropriate listener * Event types */ private class FocusEventHandlerDelegate { private final static int MSSG_FOCUS_CHANGE = 0; private final static int MSSG_RECORDING_CONFIG_CHANGE = 1; /** * Helper class to handle the forwarding of audio service events to the appropriate listener */ private class ServiceEventHandlerDelegate { private final Handler mHandler; FocusEventHandlerDelegate() { ServiceEventHandlerDelegate() { Looper looper; if ((looper = Looper.myLooper()) == null) { looper = Looper.getMainLooper(); } if (looper != null) { // implement the event handler delegate to receive audio focus events // implement the event handler delegate to receive events from audio service mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSSG_FOCUS_CHANGE: OnAudioFocusChangeListener listener = null; synchronized(mFocusListenerLock) { listener = findFocusListener((String)msg.obj); Loading @@ -2187,7 +2197,35 @@ public class AudioManager { if (listener != null) { Log.d(TAG, "AudioManager dispatching onAudioFocusChange(" + msg.what + ") for " + msg.obj); listener.onAudioFocusChange(msg.what); listener.onAudioFocusChange(msg.arg1); } break; case MSSG_RECORDING_CONFIG_CHANGE: // optimizing for the case of a single callback AudioRecordingCallback singleCallback = null; ArrayList<AudioRecordingCallback> multipleCallbacks = null; synchronized(mRecordCallbackLock) { if ((mRecordCallbackList != null) && (mRecordCallbackList.size() != 0)) { if (mRecordCallbackList.size() == 1) { singleCallback = mRecordCallbackList.get(0); } else { multipleCallbacks = new ArrayList<AudioRecordingCallback>( mRecordCallbackList); } } } if (singleCallback != null) { singleCallback.onRecordConfigChanged(); } else if (multipleCallbacks != null) { for (int i=0 ; i < multipleCallbacks.size() ; i++) { multipleCallbacks.get(i).onRecordConfigChanged(); } } break; default: Log.e(TAG, "Unknown event " + msg.what); } } }; Loading @@ -2204,8 +2242,9 @@ public class AudioManager { private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() { public void dispatchAudioFocusChange(int focusChange, String id) { Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id); mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m); final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage( MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/, id/*obj*/); mServiceEventHandlerDelegate.getHandler().sendMessage(m); } }; Loading Loading @@ -2702,6 +2741,8 @@ public class AudioManager { } //==================================================================== // Audio policy /** * @hide * Register the given {@link AudioPolicy}. Loading Loading @@ -2754,6 +2795,131 @@ public class AudioManager { } //==================================================================== // Recording configuration /** * @hide * candidate for public API */ public static abstract class AudioRecordingCallback { /** * @hide * candidate for public API */ public void onRecordConfigChanged() {} } /** * @hide * candidate for public API * @param non-null callback */ public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { if (cb == null) { throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); } synchronized(mRecordCallbackLock) { // lazy initialization of the list of recording callbacks if (mRecordCallbackList == null) { mRecordCallbackList = new ArrayList<AudioRecordingCallback>(); } final int oldCbCount = mRecordCallbackList.size(); if (!mRecordCallbackList.contains(cb)) { mRecordCallbackList.add(cb); final int newCbCount = mRecordCallbackList.size(); if ((oldCbCount == 0) && (newCbCount > 0)) { // register binder for callbacks final IAudioService service = getService(); try { service.registerRecordingCallback(mRecCb); } catch (RemoteException e) { Log.e(TAG, "Dead object in registerRecordingCallback", e); } } } else { Log.w(TAG, "attempt to call registerAudioRecordingCallback() on a previously" + "registered callback"); } } } /** * @hide * candidate for public API * @param non-null callback */ public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) { if (cb == null) { throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument"); } synchronized(mRecordCallbackLock) { if (mRecordCallbackList == null) { return; } final int oldCbCount = mRecordCallbackList.size(); if (mRecordCallbackList.remove(cb)) { final int newCbCount = mRecordCallbackList.size(); if ((oldCbCount > 0) && (newCbCount == 0)) { // unregister binder for callbacks final IAudioService service = getService(); try { service.unregisterRecordingCallback(mRecCb); } catch (RemoteException e) { Log.e(TAG, "Dead object in unregisterRecordingCallback", e); } } } else { Log.w(TAG, "attempt to call unregisterAudioRecordingCallback() on a callback" + " already unregistered or never registered"); } } } /** * @hide * candidate for public API * @return a non-null array of recording configurations. An array of length 0 indicates there is * no recording active when queried. */ public @NonNull AudioRecordConfiguration[] getActiveRecordConfigurations() { final IAudioService service = getService(); try { return service.getActiveRecordConfigurations(); } catch (RemoteException e) { Log.e(TAG, "Unable to retrieve active record configurations", e); return null; } } /** * constants for the recording events, to keep in sync * with frameworks/av/include/media/AudioPolicy.h */ /** @hide */ public final static int RECORD_CONFIG_EVENT_START = 1; /** @hide */ public final static int RECORD_CONFIG_EVENT_STOP = 0; /** * All operations on this list are sync'd on mRecordCallbackLock. * List is lazy-initialized in {@link #registerAudioRecordingCallback(AudioRecordingCallback)}. * List can be null. */ private List<AudioRecordingCallback> mRecordCallbackList; private final Object mRecordCallbackLock = new Object(); private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() { public void dispatchRecordingConfigChange() { final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage( MSSG_RECORDING_CONFIG_CHANGE/*what*/); mServiceEventHandlerDelegate.getHandler().sendMessage(m); } }; //===================================================================== /** * @hide * Reload audio settings. This method is called by Settings backup Loading
media/java/android/media/AudioRecordConfiguration.aidl 0 → 100644 +18 −0 Original line number Diff line number Diff line /* Copyright 2016, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ package android.media; parcelable AudioRecordConfiguration;
media/java/android/media/AudioRecordConfiguration.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** * @hide * Candidate for public API, see AudioManager.getActiveRecordConfiguration() * */ public class AudioRecordConfiguration implements Parcelable { private final int mSessionId; private final int mClientSource; /** * @hide */ public AudioRecordConfiguration(int session, int source) { mSessionId = session; mClientSource = source; } /** * @return one of AudioSource.MIC, AudioSource.VOICE_UPLINK, * AudioSource.VOICE_DOWNLINK, AudioSource.VOICE_CALL, * AudioSource.CAMCORDER, AudioSource.VOICE_RECOGNITION, * AudioSource.VOICE_COMMUNICATION. */ public int getClientAudioSource() { return mClientSource; } /** * @return the session number of the recorder. */ public int getAudioSessionId() { return mSessionId; } public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR = new Parcelable.Creator<AudioRecordConfiguration>() { /** * Rebuilds an AudioRecordConfiguration previously stored with writeToParcel(). * @param p Parcel object to read the AudioRecordConfiguration from * @return a new AudioRecordConfiguration created from the data in the parcel */ public AudioRecordConfiguration createFromParcel(Parcel p) { return new AudioRecordConfiguration(p); } public AudioRecordConfiguration[] newArray(int size) { return new AudioRecordConfiguration[size]; } }; @Override public int hashCode() { return Objects.hash(mSessionId, mClientSource); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mSessionId); dest.writeInt(mClientSource); } private AudioRecordConfiguration(Parcel in) { mSessionId = in.readInt(); mClientSource = in.readInt(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || !(o instanceof AudioRecordConfiguration)) return false; final AudioRecordConfiguration that = (AudioRecordConfiguration) o; return ((mSessionId == that.mSessionId) && (mClientSource == that.mClientSource)); } } No newline at end of file