Loading core/jni/android_media_AudioSystem.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -396,7 +396,7 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val) } static void android_media_AudioSystem_recording_callback(int event, audio_session_t session, int source, android_media_AudioSystem_recording_callback(int event, const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) { Loading @@ -404,8 +404,8 @@ android_media_AudioSystem_recording_callback(int event, audio_session_t session, if (env == NULL) { return; } if (clientConfig == NULL || deviceConfig == NULL) { ALOGE("Unexpected null client/device configurations in recording callback"); if (clientInfo == NULL || clientConfig == NULL || deviceConfig == NULL) { ALOGE("Unexpected null client/device info or configurations in recording callback"); return; } Loading Loading @@ -433,7 +433,7 @@ android_media_AudioSystem_recording_callback(int event, audio_session_t session, jclass clazz = env->FindClass(kClassPathName); env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative, event, session, source, recParamArray); event, (jint) clientInfo->uid, clientInfo->session, clientInfo->source, recParamArray); env->DeleteLocalRef(clazz); env->DeleteLocalRef(recParamArray); Loading Loading @@ -1930,7 +1930,7 @@ int register_android_media_AudioSystem(JNIEnv *env) "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V"); gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "recordingCallbackFromNative", "(III[I)V"); "recordingCallbackFromNative", "(IIII[I)V"); jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); Loading media/java/android/media/AudioFormat.java +42 −0 Original line number Diff line number Diff line Loading @@ -267,6 +267,42 @@ public final class AudioFormat implements Parcelable { **/ public static final int ENCODING_DOLBY_TRUEHD = 14; /** @hide */ public static String toLogFriendlyEncoding(int enc) { switch(enc) { case ENCODING_INVALID: return "ENCODING_INVALID"; case ENCODING_PCM_16BIT: return "ENCODING_PCM_16BIT"; case ENCODING_PCM_8BIT: return "ENCODING_PCM_8BIT"; case ENCODING_PCM_FLOAT: return "ENCODING_PCM_FLOAT"; case ENCODING_AC3: return "ENCODING_AC3"; case ENCODING_E_AC3: return "ENCODING_E_AC3"; case ENCODING_DTS: return "ENCODING_DTS"; case ENCODING_DTS_HD: return "ENCODING_DTS_HD"; case ENCODING_MP3: return "ENCODING_MP3"; case ENCODING_AAC_LC: return "ENCODING_AAC_LC"; case ENCODING_AAC_HE_V1: return "ENCODING_AAC_HE_V1"; case ENCODING_AAC_HE_V2: return "ENCODING_AAC_HE_V2"; case ENCODING_IEC61937: return "ENCODING_IEC61937"; case ENCODING_DOLBY_TRUEHD: return "ENCODING_DOLBY_TRUEHD"; default : return "invalid encoding " + enc; } } /** Invalid audio channel configuration */ /** @deprecated Use {@link #CHANNEL_INVALID} instead. */ @Deprecated public static final int CHANNEL_CONFIGURATION_INVALID = 0; Loading Loading @@ -693,6 +729,12 @@ public final class AudioFormat implements Parcelable { return mPropertySetMask; } /** @hide */ public String toLogFriendlyString() { return String.format("%dch %dHz %s", getChannelCount(), mSampleRate, toLogFriendlyEncoding(mEncoding)); } /** * Builder class for {@link AudioFormat} objects. * Use this class to configure and create an AudioFormat instance. By setting format Loading media/java/android/media/AudioRecordingConfiguration.java +77 −4 Original line number Diff line number Diff line Loading @@ -17,10 +17,12 @@ package android.media; import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; Loading Loading @@ -52,18 +54,59 @@ public final class AudioRecordingConfiguration implements Parcelable { private final AudioFormat mDeviceFormat; private final AudioFormat mClientFormat; @NonNull private final String mClientPackageName; private final int mClientUid; private final int mPatchHandle; /** * @hide */ public AudioRecordingConfiguration(int session, int source, AudioFormat clientFormat, AudioFormat devFormat, int patchHandle) { public AudioRecordingConfiguration(int uid, int session, int source, AudioFormat clientFormat, AudioFormat devFormat, int patchHandle, String packageName) { mClientUid = uid; mSessionId = session; mClientSource = source; mClientFormat = clientFormat; mDeviceFormat = devFormat; mPatchHandle = patchHandle; mClientPackageName = packageName; } /** * @hide * For AudioService dump * @param pw */ public void dump(PrintWriter pw) { pw.println(" " + toLogFriendlyString(this)); } /** * @hide */ public static String toLogFriendlyString(AudioRecordingConfiguration arc) { return new String("session:" + arc.mSessionId + " -- source:" + MediaRecorder.toLogFriendlyAudioSource(arc.mClientSource) + " -- uid:" + arc.mClientUid + " -- patch:" + arc.mPatchHandle + " -- pack:" + arc.mClientPackageName + " -- format client=" + arc.mClientFormat.toLogFriendlyString() + ", dev=" + arc.mDeviceFormat.toLogFriendlyString()); } // Note that this method is called server side, so no "privileged" information is ever sent // to a client that is not supposed to have access to it. /** * @hide * Creates a copy of the recording configuration that is stripped of any data enabling * identification of which application it is associated with ("anonymized"). * @param in */ public static AudioRecordingConfiguration anonymizedCopy(AudioRecordingConfiguration in) { return new AudioRecordingConfiguration( /*anonymized uid*/ -1, in.mSessionId, in.mClientSource, in.mClientFormat, in.mDeviceFormat, in.mPatchHandle, "" /*empty package name*/); } // matches the sources that return false in MediaRecorder.isSystemOnlyAudioSource(source) Loading Loading @@ -119,6 +162,30 @@ public final class AudioRecordingConfiguration implements Parcelable { */ public AudioFormat getClientFormat() { return mClientFormat; } /** * @pending for SystemApi * Returns the package name of the application performing the recording. * Where there are multiple packages sharing the same user id through the "sharedUserId" * mechanism, only the first one with that id will be returned * (see {@link PackageManager#getPackagesForUid(int)}). * <p>This information is only available if the caller has the * {@link android.Manifest.permission.MODIFY_AUDIO_ROUTING} permission. * <br>When called without the permission, the result is an empty string. * @return the package name */ public String getClientPackageName() { return mClientPackageName; } /** * @pending for SystemApi * Returns the user id of the application performing the recording. * <p>This information is only available if the caller has the * {@link android.Manifest.permission.MODIFY_AUDIO_ROUTING} * permission. * <br>The result is -1 without the permission. * @return the user id */ public int getClientUid() { return mClientUid; } /** * Returns information about the audio input device used for this recording. * @return the audio recording device or null if this information cannot be retrieved Loading Loading @@ -185,6 +252,8 @@ public final class AudioRecordingConfiguration implements Parcelable { mClientFormat.writeToParcel(dest, 0); mDeviceFormat.writeToParcel(dest, 0); dest.writeInt(mPatchHandle); dest.writeString(mClientPackageName); dest.writeInt(mClientUid); } private AudioRecordingConfiguration(Parcel in) { Loading @@ -193,6 +262,8 @@ public final class AudioRecordingConfiguration implements Parcelable { mClientFormat = AudioFormat.CREATOR.createFromParcel(in); mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in); mPatchHandle = in.readInt(); mClientPackageName = in.readString(); mClientUid = in.readInt(); } @Override Loading @@ -202,10 +273,12 @@ public final class AudioRecordingConfiguration implements Parcelable { AudioRecordingConfiguration that = (AudioRecordingConfiguration) o; return ((mSessionId == that.mSessionId) return ((mClientUid == that.mClientUid) && (mSessionId == that.mSessionId) && (mClientSource == that.mClientSource) && (mPatchHandle == that.mPatchHandle) && (mClientFormat.equals(that.mClientFormat)) && (mDeviceFormat.equals(that.mDeviceFormat))); && (mDeviceFormat.equals(that.mDeviceFormat)) && (mClientPackageName.equals(that.mClientPackageName))); } } media/java/android/media/AudioSystem.java +9 −6 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ public class AudioSystem /** * Callback for recording activity notifications events * @param event * @param uid uid of the client app performing the recording * @param session * @param source * @param recordingFormat an array of ints containing respectively the client and device Loading @@ -298,9 +299,10 @@ public class AudioSystem * 4: device channel mask * 5: device sample rate * 6: patch handle * @param packName package name of the client app performing the recording. NOT SUPPORTED */ void onRecordingConfigurationChanged(int event, int session, int source, int[] recordingFormat); void onRecordingConfigurationChanged(int event, int uid, int session, int source, int[] recordingFormat, String packName); } private static AudioRecordingCallback sRecordingCallback; Loading @@ -318,17 +320,18 @@ public class AudioSystem * @param session * @param source * @param recordingFormat see * {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} for * the description of the record format. * {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int, int[])} * for the description of the record format. */ private static void recordingCallbackFromNative(int event, int session, int source, private static void recordingCallbackFromNative(int event, int uid, int session, int source, int[] recordingFormat) { AudioRecordingCallback cb = null; synchronized (AudioSystem.class) { cb = sRecordingCallback; } if (cb != null) { cb.onRecordingConfigurationChanged(event, session, source, recordingFormat); // TODO receive package name from native cb.onRecordingConfigurationChanged(event, uid, session, source, recordingFormat, ""); } } Loading media/java/android/media/MediaRecorder.java +34 −0 Original line number Diff line number Diff line Loading @@ -324,6 +324,40 @@ public class MediaRecorder } } /** @hide */ public static final String toLogFriendlyAudioSource(int source) { switch(source) { case AudioSource.DEFAULT: return "DEFAULT"; case AudioSource.MIC: return "MIC"; case AudioSource.VOICE_UPLINK: return "VOICE_UPLINK"; case AudioSource.VOICE_DOWNLINK: return "VOICE_DOWNLINK"; case AudioSource.VOICE_CALL: return "VOICE_CALL"; case AudioSource.CAMCORDER: return "CAMCORDER"; case AudioSource.VOICE_RECOGNITION: return "VOICE_RECOGNITION"; case AudioSource.VOICE_COMMUNICATION: return "VOICE_COMMUNICATION"; case AudioSource.REMOTE_SUBMIX: return "REMOTE_SUBMIX"; case AudioSource.UNPROCESSED: return "UNPROCESSED"; case AudioSource.RADIO_TUNER: return "RADIO_TUNER"; case AudioSource.HOTWORD: return "HOTWORD"; case AudioSource.AUDIO_SOURCE_INVALID: return "AUDIO_SOURCE_INVALID"; default: return "unknown source " + source; } } /** * Defines the video source. These constants are used with * {@link MediaRecorder#setVideoSource(int)}. Loading Loading
core/jni/android_media_AudioSystem.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -396,7 +396,7 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val) } static void android_media_AudioSystem_recording_callback(int event, audio_session_t session, int source, android_media_AudioSystem_recording_callback(int event, const record_client_info_t *clientInfo, const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) { Loading @@ -404,8 +404,8 @@ android_media_AudioSystem_recording_callback(int event, audio_session_t session, if (env == NULL) { return; } if (clientConfig == NULL || deviceConfig == NULL) { ALOGE("Unexpected null client/device configurations in recording callback"); if (clientInfo == NULL || clientConfig == NULL || deviceConfig == NULL) { ALOGE("Unexpected null client/device info or configurations in recording callback"); return; } Loading Loading @@ -433,7 +433,7 @@ android_media_AudioSystem_recording_callback(int event, audio_session_t session, jclass clazz = env->FindClass(kClassPathName); env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative, event, session, source, recParamArray); event, (jint) clientInfo->uid, clientInfo->session, clientInfo->source, recParamArray); env->DeleteLocalRef(clazz); env->DeleteLocalRef(recParamArray); Loading Loading @@ -1930,7 +1930,7 @@ int register_android_media_AudioSystem(JNIEnv *env) "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V"); gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative = GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), "recordingCallbackFromNative", "(III[I)V"); "recordingCallbackFromNative", "(IIII[I)V"); jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); Loading
media/java/android/media/AudioFormat.java +42 −0 Original line number Diff line number Diff line Loading @@ -267,6 +267,42 @@ public final class AudioFormat implements Parcelable { **/ public static final int ENCODING_DOLBY_TRUEHD = 14; /** @hide */ public static String toLogFriendlyEncoding(int enc) { switch(enc) { case ENCODING_INVALID: return "ENCODING_INVALID"; case ENCODING_PCM_16BIT: return "ENCODING_PCM_16BIT"; case ENCODING_PCM_8BIT: return "ENCODING_PCM_8BIT"; case ENCODING_PCM_FLOAT: return "ENCODING_PCM_FLOAT"; case ENCODING_AC3: return "ENCODING_AC3"; case ENCODING_E_AC3: return "ENCODING_E_AC3"; case ENCODING_DTS: return "ENCODING_DTS"; case ENCODING_DTS_HD: return "ENCODING_DTS_HD"; case ENCODING_MP3: return "ENCODING_MP3"; case ENCODING_AAC_LC: return "ENCODING_AAC_LC"; case ENCODING_AAC_HE_V1: return "ENCODING_AAC_HE_V1"; case ENCODING_AAC_HE_V2: return "ENCODING_AAC_HE_V2"; case ENCODING_IEC61937: return "ENCODING_IEC61937"; case ENCODING_DOLBY_TRUEHD: return "ENCODING_DOLBY_TRUEHD"; default : return "invalid encoding " + enc; } } /** Invalid audio channel configuration */ /** @deprecated Use {@link #CHANNEL_INVALID} instead. */ @Deprecated public static final int CHANNEL_CONFIGURATION_INVALID = 0; Loading Loading @@ -693,6 +729,12 @@ public final class AudioFormat implements Parcelable { return mPropertySetMask; } /** @hide */ public String toLogFriendlyString() { return String.format("%dch %dHz %s", getChannelCount(), mSampleRate, toLogFriendlyEncoding(mEncoding)); } /** * Builder class for {@link AudioFormat} objects. * Use this class to configure and create an AudioFormat instance. By setting format Loading
media/java/android/media/AudioRecordingConfiguration.java +77 −4 Original line number Diff line number Diff line Loading @@ -17,10 +17,12 @@ package android.media; import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; Loading Loading @@ -52,18 +54,59 @@ public final class AudioRecordingConfiguration implements Parcelable { private final AudioFormat mDeviceFormat; private final AudioFormat mClientFormat; @NonNull private final String mClientPackageName; private final int mClientUid; private final int mPatchHandle; /** * @hide */ public AudioRecordingConfiguration(int session, int source, AudioFormat clientFormat, AudioFormat devFormat, int patchHandle) { public AudioRecordingConfiguration(int uid, int session, int source, AudioFormat clientFormat, AudioFormat devFormat, int patchHandle, String packageName) { mClientUid = uid; mSessionId = session; mClientSource = source; mClientFormat = clientFormat; mDeviceFormat = devFormat; mPatchHandle = patchHandle; mClientPackageName = packageName; } /** * @hide * For AudioService dump * @param pw */ public void dump(PrintWriter pw) { pw.println(" " + toLogFriendlyString(this)); } /** * @hide */ public static String toLogFriendlyString(AudioRecordingConfiguration arc) { return new String("session:" + arc.mSessionId + " -- source:" + MediaRecorder.toLogFriendlyAudioSource(arc.mClientSource) + " -- uid:" + arc.mClientUid + " -- patch:" + arc.mPatchHandle + " -- pack:" + arc.mClientPackageName + " -- format client=" + arc.mClientFormat.toLogFriendlyString() + ", dev=" + arc.mDeviceFormat.toLogFriendlyString()); } // Note that this method is called server side, so no "privileged" information is ever sent // to a client that is not supposed to have access to it. /** * @hide * Creates a copy of the recording configuration that is stripped of any data enabling * identification of which application it is associated with ("anonymized"). * @param in */ public static AudioRecordingConfiguration anonymizedCopy(AudioRecordingConfiguration in) { return new AudioRecordingConfiguration( /*anonymized uid*/ -1, in.mSessionId, in.mClientSource, in.mClientFormat, in.mDeviceFormat, in.mPatchHandle, "" /*empty package name*/); } // matches the sources that return false in MediaRecorder.isSystemOnlyAudioSource(source) Loading Loading @@ -119,6 +162,30 @@ public final class AudioRecordingConfiguration implements Parcelable { */ public AudioFormat getClientFormat() { return mClientFormat; } /** * @pending for SystemApi * Returns the package name of the application performing the recording. * Where there are multiple packages sharing the same user id through the "sharedUserId" * mechanism, only the first one with that id will be returned * (see {@link PackageManager#getPackagesForUid(int)}). * <p>This information is only available if the caller has the * {@link android.Manifest.permission.MODIFY_AUDIO_ROUTING} permission. * <br>When called without the permission, the result is an empty string. * @return the package name */ public String getClientPackageName() { return mClientPackageName; } /** * @pending for SystemApi * Returns the user id of the application performing the recording. * <p>This information is only available if the caller has the * {@link android.Manifest.permission.MODIFY_AUDIO_ROUTING} * permission. * <br>The result is -1 without the permission. * @return the user id */ public int getClientUid() { return mClientUid; } /** * Returns information about the audio input device used for this recording. * @return the audio recording device or null if this information cannot be retrieved Loading Loading @@ -185,6 +252,8 @@ public final class AudioRecordingConfiguration implements Parcelable { mClientFormat.writeToParcel(dest, 0); mDeviceFormat.writeToParcel(dest, 0); dest.writeInt(mPatchHandle); dest.writeString(mClientPackageName); dest.writeInt(mClientUid); } private AudioRecordingConfiguration(Parcel in) { Loading @@ -193,6 +262,8 @@ public final class AudioRecordingConfiguration implements Parcelable { mClientFormat = AudioFormat.CREATOR.createFromParcel(in); mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in); mPatchHandle = in.readInt(); mClientPackageName = in.readString(); mClientUid = in.readInt(); } @Override Loading @@ -202,10 +273,12 @@ public final class AudioRecordingConfiguration implements Parcelable { AudioRecordingConfiguration that = (AudioRecordingConfiguration) o; return ((mSessionId == that.mSessionId) return ((mClientUid == that.mClientUid) && (mSessionId == that.mSessionId) && (mClientSource == that.mClientSource) && (mPatchHandle == that.mPatchHandle) && (mClientFormat.equals(that.mClientFormat)) && (mDeviceFormat.equals(that.mDeviceFormat))); && (mDeviceFormat.equals(that.mDeviceFormat)) && (mClientPackageName.equals(that.mClientPackageName))); } }
media/java/android/media/AudioSystem.java +9 −6 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ public class AudioSystem /** * Callback for recording activity notifications events * @param event * @param uid uid of the client app performing the recording * @param session * @param source * @param recordingFormat an array of ints containing respectively the client and device Loading @@ -298,9 +299,10 @@ public class AudioSystem * 4: device channel mask * 5: device sample rate * 6: patch handle * @param packName package name of the client app performing the recording. NOT SUPPORTED */ void onRecordingConfigurationChanged(int event, int session, int source, int[] recordingFormat); void onRecordingConfigurationChanged(int event, int uid, int session, int source, int[] recordingFormat, String packName); } private static AudioRecordingCallback sRecordingCallback; Loading @@ -318,17 +320,18 @@ public class AudioSystem * @param session * @param source * @param recordingFormat see * {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} for * the description of the record format. * {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int, int[])} * for the description of the record format. */ private static void recordingCallbackFromNative(int event, int session, int source, private static void recordingCallbackFromNative(int event, int uid, int session, int source, int[] recordingFormat) { AudioRecordingCallback cb = null; synchronized (AudioSystem.class) { cb = sRecordingCallback; } if (cb != null) { cb.onRecordingConfigurationChanged(event, session, source, recordingFormat); // TODO receive package name from native cb.onRecordingConfigurationChanged(event, uid, session, source, recordingFormat, ""); } } Loading
media/java/android/media/MediaRecorder.java +34 −0 Original line number Diff line number Diff line Loading @@ -324,6 +324,40 @@ public class MediaRecorder } } /** @hide */ public static final String toLogFriendlyAudioSource(int source) { switch(source) { case AudioSource.DEFAULT: return "DEFAULT"; case AudioSource.MIC: return "MIC"; case AudioSource.VOICE_UPLINK: return "VOICE_UPLINK"; case AudioSource.VOICE_DOWNLINK: return "VOICE_DOWNLINK"; case AudioSource.VOICE_CALL: return "VOICE_CALL"; case AudioSource.CAMCORDER: return "CAMCORDER"; case AudioSource.VOICE_RECOGNITION: return "VOICE_RECOGNITION"; case AudioSource.VOICE_COMMUNICATION: return "VOICE_COMMUNICATION"; case AudioSource.REMOTE_SUBMIX: return "REMOTE_SUBMIX"; case AudioSource.UNPROCESSED: return "UNPROCESSED"; case AudioSource.RADIO_TUNER: return "RADIO_TUNER"; case AudioSource.HOTWORD: return "HOTWORD"; case AudioSource.AUDIO_SOURCE_INVALID: return "AUDIO_SOURCE_INVALID"; default: return "unknown source " + source; } } /** * Defines the video source. These constants are used with * {@link MediaRecorder#setVideoSource(int)}. Loading