Add attributionTag to audio-recordings

... by switching from packageName/uid/pid to the Identity class.

This allows up to track which parts of the app trigger audio-recordings.

Test: atest CtsAppOpsTestCases
            CtsNativeMediaAAudioTestCases
Fixes: 160150145
Change-Id: I0913a336a862e4a1cb38b9d967cfbdc490513ab0
This commit is contained in:
Philip P. Moltmann
2020-07-17 16:39:54 -07:00
committed by Nate Myren
parent 50f0175f3e
commit fece2436d4
25 changed files with 333 additions and 84 deletions

View File

@@ -20565,6 +20565,7 @@ package android.media {
method @NonNull public android.media.AudioRecord.Builder setAudioPlaybackCaptureConfig(@NonNull android.media.AudioPlaybackCaptureConfiguration);
method public android.media.AudioRecord.Builder setAudioSource(int) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
method @NonNull public android.media.AudioRecord.Builder setContext(@NonNull android.content.Context);
method @NonNull public android.media.AudioRecord.Builder setPrivacySensitive(boolean);
}
@@ -22739,7 +22740,8 @@ package android.media {
}
public class MediaRecorder implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection {
ctor public MediaRecorder();
ctor @Deprecated public MediaRecorder();
ctor public MediaRecorder(@NonNull android.content.Context);
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method protected void finalize();
method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;

View File

@@ -1,4 +1,3 @@
package {
default_applicable_licenses: ["frameworks_base_core_jni_license"],
}
@@ -218,6 +217,7 @@ cc_library_shared {
"fd_utils.cpp",
"android_hardware_input_InputWindowHandle.cpp",
"android_hardware_input_InputApplicationHandle.cpp",
"permission_utils.cpp",
],
static_libs: [
@@ -236,6 +236,7 @@ cc_library_shared {
"audioflinger-aidl-cpp",
"av-types-aidl-cpp",
"android.hardware.camera.device@3.2",
"media_permission-aidl-cpp",
"libandroidicu",
"libbpf_android",
"libnetdbpf",

View File

@@ -97,6 +97,7 @@ extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
extern int register_android_media_midi(JNIEnv *env);
extern int register_android_media_permission_Identity(JNIEnv* env);
namespace android {
@@ -1562,6 +1563,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_media_RemoteDisplay),
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_media_midi),
REG_JNI(register_android_media_permission_Identity),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_server_NetworkManagementSocketTagger),

View File

@@ -22,6 +22,7 @@
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
#include "permission_utils.h"
#include <utils/Log.h>
#include <media/AudioRecord.h>
@@ -39,6 +40,9 @@
// ----------------------------------------------------------------------------
using android::media::permission::convertIdentity;
using android::media::permission::Identity;
using namespace android;
// ----------------------------------------------------------------------------
@@ -181,12 +185,11 @@ static sp<AudioRecord> setAudioRecord(JNIEnv* env, jobject thiz, const sp<AudioR
}
// ----------------------------------------------------------------------------
static jint
android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jobject jaa, jintArray jSampleRate, jint channelMask, jint channelIndexMask,
jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName,
jlong nativeRecordInJavaObj)
{
static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jobject jaa, jintArray jSampleRate, jint channelMask,
jint channelIndexMask, jint audioFormat,
jint buffSizeInBytes, jintArray jSession,
jobject jIdentity, jlong nativeRecordInJavaObj) {
//ALOGV(">> Entering android_media_AudioRecord_setup");
//ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d "
// "nativeRecordInJavaObj=0x%llX",
@@ -262,10 +265,8 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
size_t frameSize = channelCount * bytesPerSample;
size_t frameCount = buffSizeInBytes / frameSize;
ScopedUtfChars opPackageNameStr(env, opPackageName);
// create an uninitialized AudioRecord object
lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str()));
lpRecorder = new AudioRecord(convertIdentity(env, jIdentity));
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -373,8 +374,6 @@ native_init_failure:
return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
}
// ----------------------------------------------------------------------------
static jint
android_media_AudioRecord_start(JNIEnv *env, jobject thiz, jint event, jint triggerSession)
@@ -893,9 +892,11 @@ static jint android_media_AudioRecord_get_port_id(JNIEnv *env, jobject thiz) {
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;J)I",
{"native_setup",
"(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILandroid/media/permission/Identity;J)I",
(void *)android_media_AudioRecord_setup},
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
{"native_release", "()V", (void *)android_media_AudioRecord_release},

View File

@@ -48,6 +48,7 @@
using namespace android;
using ::android::media::VolumeShaper;
using ::android::media::permission::Identity;
// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/AudioTrack";
@@ -328,7 +329,10 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
// create the native AudioTrack object
ScopedUtfChars opPackageNameStr(env, opPackageName);
lpTrack = new AudioTrack(opPackageNameStr.c_str());
// TODO b/182469354: make consistent with AudioRecord
Identity identity = Identity();
identity.packageName = std::string(opPackageNameStr.c_str());
lpTrack = new AudioTrack(identity);
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -390,8 +394,8 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
sessionId, // audio session ID
offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
: AudioTrack::TRANSFER_SYNC,
(offload || encapsulationMode) ? &offloadInfo : NULL, -1,
-1, // default uid, pid values
(offload || encapsulationMode) ? &offloadInfo : NULL,
Identity(), // default uid, pid values
paa.get());
break;
@@ -416,8 +420,8 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
true, // thread can call Java
sessionId, // audio session ID
AudioTrack::TRANSFER_SHARED,
NULL, // default offloadInfo
-1, -1, // default uid, pid values
NULL, // default offloadInfo
Identity(), // default uid, pid values
paa.get());
break;

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2021 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.
*/
#include "permission_utils.h"
#include "core_jni_helpers.h"
static struct {
jfieldID fieldUid; // Identity.uid
jfieldID fieldPid; // Identity.pid
jfieldID fieldPackageName; // Identity.packageName
jfieldID fieldAttributionTag; // Identity.attributionTag
} javaIdentityFields;
static const JNINativeMethod method_table[] = {
// no static methods, currently
};
int register_android_media_permission_Identity(JNIEnv* env) {
jclass identityClass = android::FindClassOrDie(env, "android/media/permission/Identity");
javaIdentityFields.fieldUid = android::GetFieldIDOrDie(env, identityClass, "uid", "I");
javaIdentityFields.fieldPid = android::GetFieldIDOrDie(env, identityClass, "pid", "I");
javaIdentityFields.fieldPackageName =
android::GetFieldIDOrDie(env, identityClass, "packageName", "Ljava/lang/String;");
javaIdentityFields.fieldAttributionTag =
android::GetFieldIDOrDie(env, identityClass, "attributionTag", "Ljava/lang/String;");
return android::RegisterMethodsOrDie(env, "android/media/permission/Identity", method_table,
NELEM(method_table));
}
namespace android::media::permission {
Identity convertIdentity(JNIEnv* env, const jobject& jIdentity) {
Identity identity;
identity.uid = env->GetIntField(jIdentity, javaIdentityFields.fieldUid);
identity.pid = env->GetIntField(jIdentity, javaIdentityFields.fieldPid);
jstring packageNameStr = static_cast<jstring>(
env->GetObjectField(jIdentity, javaIdentityFields.fieldPackageName));
if (packageNameStr == nullptr) {
identity.packageName = std::nullopt;
} else {
identity.packageName = std::string(ScopedUtfChars(env, packageNameStr).c_str());
}
jstring attributionTagStr = static_cast<jstring>(
env->GetObjectField(jIdentity, javaIdentityFields.fieldAttributionTag));
if (attributionTagStr == nullptr) {
identity.attributionTag = std::nullopt;
} else {
identity.attributionTag = std::string(ScopedUtfChars(env, attributionTagStr).c_str());
}
return identity;
}
} // namespace android::media::permission

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2021 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.
*/
#pragma once
#include <android/media/permission/Identity.h>
#include <jni.h>
namespace android::media::permission {
Identity convertIdentity(JNIEnv* env, const jobject& jIdentity);
}
int register_android_media_permission_Identity(JNIEnv* env);

View File

@@ -27,6 +27,9 @@ aidl_interface {
aidl_interface {
name: "media_permission-aidl",
unstable: true,
host_supported: true,
vendor_available: true,
double_loadable: true,
local_include_dir: "aidl",
srcs: [
"aidl/android/media/permission/Identity.aidl",

View File

@@ -22,11 +22,11 @@ package android.media.permission;
*/
parcelable Identity {
/** Linux user ID. */
int uid;
int uid = -1;
/** Linux process ID. */
int pid;
int pid = -1;
/** Package name. If null, the first package owned by the given uid will be assumed. */
@nullable String packageName;
@nullable @utf8InCpp String packageName;
/** Attribution tag. Mostly used for diagnostic purposes. */
@nullable String attributionTag;
@nullable @utf8InCpp String attributionTag;
}

View File

@@ -16,6 +16,8 @@
package android.media;
import static android.media.permission.PermissionUtil.myIdentity;
import android.annotation.CallbackExecutor;
import android.annotation.FloatRange;
import android.annotation.IntDef;
@@ -26,9 +28,11 @@ import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaRecorder.Source;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
import android.media.permission.Identity;
import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Build;
@@ -54,6 +58,7 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -352,6 +357,32 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
@RequiresPermission(android.Manifest.permission.RECORD_AUDIO)
public AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
int sessionId) throws IllegalArgumentException {
this(attributes, format, bufferSizeInBytes, sessionId, ActivityThread.currentApplication());
}
/**
* @hide
* Class constructor with {@link AudioAttributes} and {@link AudioFormat}.
* @param attributes a non-null {@link AudioAttributes} instance. Use
* {@link AudioAttributes.Builder#setCapturePreset(int)} for configuring the audio
* source for this instance.
* @param format a non-null {@link AudioFormat} instance describing the format of the data
* that will be recorded through this AudioRecord. See {@link AudioFormat.Builder} for
* configuring the audio format parameters such as encoding, channel mask and sample rate.
* @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written
* to during the recording. New audio data can be read from this buffer in smaller chunks
* than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
* required buffer size for the successful creation of an AudioRecord instance. Using values
* smaller than getMinBufferSize() will result in an initialization failure.
* @param sessionId ID of audio session the AudioRecord must be attached to, or
* {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction
* time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before
* construction.
* @param context An optional context to pull an attribution tag from.
* @throws IllegalArgumentException
*/
private AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
int sessionId, @Nullable Context context) throws IllegalArgumentException {
mRecordingState = RECORDSTATE_STOPPED;
if (attributes == null) {
@@ -414,15 +445,21 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
audioBuffSizeCheck(bufferSizeInBytes);
Identity identity = myIdentity(context);
if (identity.packageName == null) {
// Command line utility
identity.packageName = "uid:" + Binder.getCallingUid();
}
int[] sampleRate = new int[] {mSampleRate};
int[] session = new int[1];
session[0] = sessionId;
//TODO: update native initialization when information about hardware init failure
// due to capture device already open is available.
int initResult = native_setup( new WeakReference<AudioRecord>(this),
int initResult = native_setup(new WeakReference<AudioRecord>(this),
mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
mAudioFormat, mNativeBufferSizeInBytes,
session, getCurrentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
session, identity, 0 /*nativeRecordInJavaObj*/);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing native AudioRecord object.");
return; // with mState == STATE_UNINITIALIZED
@@ -434,15 +471,6 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
mState = STATE_INITIALIZED;
}
private String getCurrentOpPackageName() {
String opPackageName = ActivityThread.currentOpPackageName();
if (opPackageName != null) {
return opPackageName;
}
// Command line utility
return "uid:" + Binder.getCallingUid();
}
/**
* A constructor which explicitly connects a Native (C++) AudioRecord. For use by
* the AudioRecordRoutingProxy subclass.
@@ -492,7 +520,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
0 /*mAudioFormat*/,
0 /*mNativeBufferSizeInBytes*/,
session,
ActivityThread.currentOpPackageName(),
myIdentity(null),
nativeRecordInJavaObj);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing native AudioRecord object.");
@@ -548,6 +576,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
private AudioPlaybackCaptureConfiguration mAudioPlaybackCaptureConfiguration;
private AudioAttributes mAttributes;
private AudioFormat mFormat;
private Context mContext;
private int mBufferSizeInBytes;
private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
@@ -582,6 +611,18 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
return this;
}
/**
* Sets the context the record belongs to.
* @param context a non-null {@link Context} instance
* @return the same Builder instance.
*/
public @NonNull Builder setContext(@NonNull Context context) {
Objects.requireNonNull(context);
// keep reference, we only copy the data when building
mContext = context;
return this;
}
/**
* @hide
* To be only used by system components. Allows specifying non-public capture presets
@@ -793,7 +834,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
* mFormat.getBytesPerSample(mFormat.getEncoding());
}
final AudioRecord record = new AudioRecord(
mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
mAttributes, mFormat, mBufferSizeInBytes, mSessionId, mContext);
if (record.getState() == STATE_UNINITIALIZED) {
// release is not necessary
throw new UnsupportedOperationException("Cannot create AudioRecord");
@@ -2035,15 +2076,32 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
// Native methods called from the Java side
//--------------------
@UnsupportedAppUsage
private native final int native_setup(Object audiorecord_this,
/**
* @deprecated Use native_setup that takes an Identity object
* @return
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R,
publicAlternatives = "{@code AudioRecord.Builder}")
@Deprecated
private int native_setup(Object audiorecordThis,
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int[] sessionId, String opPackageName,
long nativeRecordInJavaObj);
long nativeRecordInJavaObj) {
Identity identity = myIdentity(null);
identity.packageName = opPackageName;
return native_setup(audiorecordThis, attributes, sampleRate, channelMask, channelIndexMask,
audioFormat, buffSizeInBytes, sessionId, identity, nativeRecordInJavaObj);
}
private native int native_setup(Object audiorecordThis,
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int[] sessionId, Identity identity, long nativeRecordInJavaObj);
// TODO remove: implementation calls directly into implementation of native_release()
private native final void native_finalize();
private native void native_finalize();
/**
* @hide

View File

@@ -18,6 +18,7 @@ package android.media;
import static android.Manifest.permission.BIND_IMS_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.media.permission.PermissionUtil.myIdentity;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -34,6 +35,7 @@ import android.content.res.AssetFileDescriptor;
import android.graphics.SurfaceTexture;
import android.media.SubtitleController.Anchor;
import android.media.SubtitleTrack.RenderingWidget;
import android.media.permission.Identity;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -53,6 +55,7 @@ import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
@@ -684,11 +687,14 @@ public class MediaPlayer extends PlayerBase
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
Identity identity = myIdentity(null);
// set the package name to empty if it was null
identity.packageName = TextUtils.emptyIfNull(identity.packageName);
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference<MediaPlayer>(this),
getCurrentOpPackageName());
native_setup(new WeakReference<MediaPlayer>(this), identity);
baseRegisterPlayer(sessionId);
}
@@ -2471,7 +2477,7 @@ public class MediaPlayer extends PlayerBase
private native final int native_setMetadataFilter(Parcel request);
private static native final void native_init();
private native void native_setup(Object mediaplayerThis, @NonNull String opPackageName);
private native void native_setup(Object mediaplayerThis, @NonNull Identity identity);
private native final void native_finalize();
/**

View File

@@ -16,6 +16,8 @@
package android.media;
import static android.media.permission.PermissionUtil.myIdentity;
import android.annotation.CallbackExecutor;
import android.annotation.FloatRange;
import android.annotation.IntDef;
@@ -25,7 +27,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.Camera;
import android.media.permission.Identity;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -48,6 +52,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -127,9 +132,21 @@ public class MediaRecorder implements AudioRouting,
/**
* Default constructor.
*
* @deprecated Use {@link #MediaRecorder(Context)} instead
*/
@Deprecated
public MediaRecorder() {
this(ActivityThread.currentApplication());
}
/**
* Default constructor.
*
* @param context Context the recorder belongs to
*/
public MediaRecorder(@NonNull Context context) {
Objects.requireNonNull(context);
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
@@ -140,12 +157,11 @@ public class MediaRecorder implements AudioRouting,
}
mChannelCount = 1;
String packageName = ActivityThread.currentPackageName();
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference<MediaRecorder>(this), packageName,
ActivityThread.currentOpPackageName());
native_setup(new WeakReference<MediaRecorder>(this),
ActivityThread.currentPackageName(), myIdentity(context));
}
/**
@@ -1740,12 +1756,22 @@ public class MediaRecorder implements AudioRouting,
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private static native final void native_init();
@UnsupportedAppUsage
private native final void native_setup(Object mediarecorder_this,
String clientName, String opPackageName) throws IllegalStateException;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R,
publicAlternatives = "{@link MediaRecorder}")
private void native_setup(Object mediarecorderThis,
String clientName, String opPackageName) throws IllegalStateException {
Identity identity = myIdentity(null);
identity.packageName = opPackageName;
native_setup(mediarecorderThis, clientName, identity);
}
private native void native_setup(Object mediarecorderThis,
String clientName, Identity identity)
throws IllegalStateException;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private native final void native_finalize();
private native void native_finalize();
@UnsupportedAppUsage
private native void setParameter(String nameValuePair);

View File

@@ -16,6 +16,8 @@
package android.media.audiofx;
import static android.media.permission.PermissionUtil.myIdentity;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -23,11 +25,11 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioSystem;
import android.media.permission.Identity;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -515,10 +517,11 @@ public class AudioEffect {
}
// native initialization
// TODO b/182469354: Make consistent with AudioRecord
int initResult = native_setup(new WeakReference<AudioEffect>(this),
type.toString(), uuid.toString(), priority, audioSession,
deviceType, deviceAddress,
id, desc, ActivityThread.currentOpPackageName(), probe);
id, desc, myIdentity(null), probe);
if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
Log.e(TAG, "Error code " + initResult
+ " when initializing AudioEffect.");
@@ -1385,7 +1388,7 @@ public class AudioEffect {
private native final int native_setup(Object audioeffect_this, String type,
String uuid, int priority, int audioSession,
int deviceType, String deviceAddress, int[] id, Object[] desc,
String opPackageName, boolean probe);
Identity identity, boolean probe);
private native final void native_finalize();

View File

@@ -16,8 +16,10 @@
package android.media.audiofx;
import android.app.ActivityThread;
import static android.media.permission.PermissionUtil.myIdentity;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.permission.Identity;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -217,9 +219,11 @@ public class Visualizer {
synchronized (mStateLock) {
mState = STATE_UNINITIALIZED;
// native initialization
// TODO b/182469354: make consistent with AudioRecord
int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id,
ActivityThread.currentOpPackageName());
myIdentity(null));
if (result != SUCCESS && result != ALREADY_EXISTS) {
Log.e(TAG, "Error code "+result+" when initializing Visualizer.");
switch (result) {
@@ -686,7 +690,7 @@ public class Visualizer {
private native final int native_setup(Object audioeffect_this,
int audioSession,
int[] id,
String opPackageName);
Identity identity);
@GuardedBy("mStateLock")
private native final void native_finalize();

View File

@@ -17,9 +17,12 @@
package android.media.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.content.Context;
import android.content.PermissionChecker;
import android.os.Binder;
import android.os.Process;
import java.util.Objects;
@@ -48,6 +51,25 @@ import java.util.Objects;
* @hide
*/
public class PermissionUtil {
/**
* Create an identity for the current process and the passed context.
*
* @param context The process the identity is for. If {@code null}, the process's default
* identity is chosen.
* @return The identity for the current process and context
*/
public static @NonNull Identity myIdentity(@Nullable Context context) {
Identity identity = new Identity();
identity.pid = Process.myPid();
identity.uid = Process.myUid();
identity.packageName = context != null ? context.getOpPackageName()
: ActivityThread.currentOpPackageName();
identity.attributionTag = context != null ? context.getAttributionTag() : null;
return identity;
}
/**
* Authenticate an originator, where the binder call is coming from a middleman.
*

View File

@@ -84,6 +84,7 @@ cc_library_shared {
"android.hardware.drm@1.4",
"android.hidl.memory@1.0",
"android.hidl.token@1.0-utils",
"media_permission-aidl-cpp",
],
header_libs: [
@@ -182,7 +183,7 @@ cc_library_shared {
"libnativehelper",
"libutils",
"tv_tuner_aidl_interface-ndk_platform",
"tv_tuner_resource_manager_aidl_interface-ndk_platform"
"tv_tuner_resource_manager_aidl_interface-ndk_platform",
],
static_libs: [
@@ -212,4 +213,3 @@ cc_library_shared {
"-Wunreachable-code",
],
}

View File

@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer-JNI"
#include "permission_utils.h"
#include "utils/Log.h"
#include <media/mediaplayer.h>
@@ -79,6 +80,8 @@ static StateExceptionFields gStateExceptionFields;
using namespace android;
using media::VolumeShaper;
using media::permission::Identity;
using media::permission::convertIdentity;
// ----------------------------------------------------------------------------
@@ -946,11 +949,11 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring opPackageName)
jobject jIdentity)
{
ALOGV("native_setup");
ScopedUtfChars opPackageNameStr(env, opPackageName);
sp<MediaPlayer> mp = new MediaPlayer(opPackageNameStr.c_str());
sp<MediaPlayer> mp = new MediaPlayer(convertIdentity(env, jIdentity));
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -1406,7 +1409,7 @@ static const JNINativeMethod gMethods[] = {
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_native_setup},
{"native_setup", "(Ljava/lang/Object;Landroid/media/permission/Identity;)V",(void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"native_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},

View File

@@ -24,6 +24,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaRecorderJNI"
#include "permission_utils.h"
#include <utils/Log.h>
#include <gui/Surface.h>
@@ -50,6 +51,8 @@
using namespace android;
using android::media::permission::convertIdentity;
// ----------------------------------------------------------------------------
// helper function to extract a native Camera object from a Camera Java object
@@ -617,13 +620,12 @@ android_media_MediaRecorder_native_init(JNIEnv *env)
static void
android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring packageName, jstring opPackageName)
jstring packageName, jobject jIdentity)
{
ALOGV("setup");
ScopedUtfChars opPackageNameStr(env, opPackageName);
sp<MediaRecorder> mr = new MediaRecorder(convertIdentity(env, jIdentity));
sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str()));
if (mr == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -869,7 +871,7 @@ static const JNINativeMethod gMethods[] = {
{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},
{"release", "()V", (void *)android_media_MediaRecorder_release},
{"native_init", "()V", (void *)android_media_MediaRecorder_native_init},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V",
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Landroid/media/permission/Identity;)V",
(void *)android_media_MediaRecorder_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},
{"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },

View File

@@ -27,6 +27,11 @@ cc_library_shared {
"libaudioclient",
"libaudioutils",
"libaudiofoundation",
"media_permission-aidl-cpp",
],
export_shared_lib_headers: [
"media_permission-aidl-cpp",
],
version_script: "exports.lds",

View File

@@ -34,8 +34,8 @@ namespace android {
// ---------------------------------------------------------------------------
Visualizer::Visualizer (const String16& opPackageName)
: AudioEffect(opPackageName)
Visualizer::Visualizer (const Identity& identity)
: AudioEffect(identity)
{
}

View File

@@ -20,6 +20,9 @@
#include <media/AudioEffect.h>
#include <system/audio_effects/effect_visualizer.h>
#include <utils/Thread.h>
#include "android/media/permission/Identity.h"
using namespace android::media::permission;
/**
* The Visualizer class enables application to retrieve part of the currently playing audio for
@@ -65,7 +68,7 @@ public:
/* Constructor.
* See AudioEffect constructor for details on parameters.
*/
explicit Visualizer(const String16& opPackageName);
explicit Visualizer(const Identity& identity);
~Visualizer();

View File

@@ -25,6 +25,7 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include "media/AudioEffect.h"
#include "permission_utils.h"
#include <nativehelper/ScopedUtfChars.h>
@@ -34,6 +35,8 @@
using namespace android;
using media::permission::convertIdentity;
#define AUDIOEFFECT_SUCCESS 0
#define AUDIOEFFECT_ERROR (-1)
#define AUDIOEFFECT_ERROR_ALREADY_EXISTS (-2)
@@ -270,7 +273,7 @@ static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring type, jstring uuid, jint priority, jint sessionId,
jint deviceType, jstring deviceAddress,
jintArray jId, jobjectArray javadesc, jstring opPackageName, jboolean probe)
jintArray jId, jobjectArray javadesc, jobject jIdentity, jboolean probe)
{
ALOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
@@ -283,8 +286,6 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
jobject jdesc;
AudioDeviceTypeAddr device;
ScopedUtfChars opPackageNameStr(env, opPackageName);
setAudioEffect(env, thiz, 0);
if (type != NULL) {
@@ -337,7 +338,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
}
// create the native AudioEffect object
lpAudioEffect = new AudioEffect(String16(opPackageNameStr.c_str()));
lpAudioEffect = new AudioEffect(convertIdentity(env, jIdentity));
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
@@ -773,7 +774,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Ljava/lang/String;Z)I",
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Landroid/media/permission/Identity;Z)I",
(void *)android_media_AudioEffect_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
{"native_release", "()V", (void *)android_media_AudioEffect_native_release},

View File

@@ -25,6 +25,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/threads.h>
#include "Visualizer.h"
#include "permission_utils.h"
#include <nativehelper/ScopedUtfChars.h>
@@ -347,7 +348,7 @@ static void android_media_visualizer_effect_callback(int32_t event,
static jint
android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jint sessionId, jintArray jId, jstring opPackageName)
jint sessionId, jintArray jId, jobject jIdentity)
{
ALOGV("android_media_visualizer_native_setup");
VisualizerJniStorage* lpJniStorage = NULL;
@@ -355,8 +356,6 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
sp<Visualizer> lpVisualizer;
jint* nId = NULL;
ScopedUtfChars opPackageNameStr(env, opPackageName);
setVisualizer(env, thiz, 0);
lpJniStorage = new VisualizerJniStorage();
@@ -382,7 +381,7 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
}
// create the native Visualizer object
lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()));
lpVisualizer = new Visualizer(convertIdentity(env, jIdentity));
if (lpVisualizer == 0) {
ALOGE("Error creating Visualizer");
goto setup_failure;
@@ -679,7 +678,7 @@ android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_visualizer_native_init},
{"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I",
{"native_setup", "(Ljava/lang/Object;I[ILandroid/media/permission/Identity;)I",
(void *)android_media_visualizer_native_setup},
{"native_finalize", "()V", (void *)android_media_visualizer_native_finalize},
{"native_release", "()V", (void *)android_media_visualizer_native_release},

View File

@@ -63,7 +63,7 @@ tidy_errors = [
// Remove some pedantic stylistic requirements.
"-google-readability-casting", // C++ casts not always necessary and may be verbose
"-google-readability-todo", // do not require TODO(info)
"-google-readability-todo", // do not require TODO(info)
"-google-build-using-namespace", // Reenable and fix later.
"-google-explicit-constructor", // found in StreamManager.h
@@ -100,7 +100,7 @@ cc_defaults {
tidy_checks: tidy_errors,
tidy_checks_as_errors: tidy_errors,
tidy_flags: [
"-format-style=file",
"-format-style=file",
],
}
@@ -135,6 +135,7 @@ cc_library_shared {
"libaudioclient",
"libmediandk",
"libbinder",
"media_permission-aidl-cpp",
],
cflags: [

View File

@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoundPool::Stream"
#include <utils/Log.h>
#include<android/media/permission/Identity.h>
#include "Stream.h"
@@ -24,6 +25,8 @@
namespace android::soundpool {
using media::permission::Identity;
Stream::~Stream()
{
ALOGV("%s(%p)", __func__, this);
@@ -326,15 +329,17 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
// do not create a new audio track if current track is compatible with sound parameters
Identity identity = Identity();
identity.packageName = mStreamManager->getOpPackageName();
// TODO b/182469354 make consistent with AudioRecord, add util for native source
newTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
staticCallback, userData,
0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
AudioTrack::TRANSFER_DEFAULT,
nullptr /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/,
nullptr /*offloadInfo*/, identity,
mStreamManager->getAttributes(),
false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/,
mStreamManager->getOpPackageName());
false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/);
// Set caller name so it can be logged in destructor.
// MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL
newTrack->setCallerName("soundpool");