From 04d5e6d78b49b14c0f8ffc6fc8b8e9abbc52d30b Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Mon, 19 Oct 2020 10:19:12 -0700 Subject: [PATCH 1/4] Add dependency to libandroid_runtime audioflinger-aidl aidl_interface module has been extracted from libaudioclient as part of an AIDL focused refactoring. Clients need to depend on this module to compile. Test: compiles Change-Id: Ia4be7f7cfc24e897304423a58d112af77214bbbf --- core/jni/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 1123f20c3e7e8..a278551c5d7d5 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -204,6 +204,7 @@ cc_library_shared { ], shared_libs: [ + "audioflinger-aidl-unstable-cpp", "libandroidicu", "libbpf_android", "libnetdbpf", From f12e518cc5eaf04f669b836baad523f9f1391c07 Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Mon, 26 Oct 2020 13:27:45 -0700 Subject: [PATCH 2/4] Add dependencies to libandroid_runtime, libmedia_jni audioclient-types-aidlaudioflinger-aidl aidl_interface module has been extracted from libaudioclient as part of an AIDL focused refactoring. Clients need to depend on this module to compile. Test: compiles Change-Id: If1b773e7505f93c01027563dd3b1123577ebe495 --- core/jni/Android.bp | 1 + media/jni/Android.bp | 1 + 2 files changed, 2 insertions(+) diff --git a/core/jni/Android.bp b/core/jni/Android.bp index a278551c5d7d5..20a37ba3e9882 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -204,6 +204,7 @@ cc_library_shared { ], shared_libs: [ + "audioclient-types-aidl-unstable-cpp", "audioflinger-aidl-unstable-cpp", "libandroidicu", "libbpf_android", diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 724965dac9471..e71c141980d53 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -31,6 +31,7 @@ cc_library_shared { ], shared_libs: [ + "audioclient-types-aidl-unstable-cpp", "libandroid_runtime", "libaudioclient", "libnativehelper", From 203e4e667256323822ca2ec9003e3f0eba5b7525 Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Thu, 29 Oct 2020 11:19:10 -0700 Subject: [PATCH 3/4] Add av-types-aidl to libandroid_runtime, libmedia_jni This new module has been extracted from frameworks/av headers Change-Id: I8b4b46ea7cb41fab3fc947087a0a195eb7470274 --- core/jni/Android.bp | 1 + media/jni/Android.bp | 1 + 2 files changed, 2 insertions(+) diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 20a37ba3e9882..dd1c87b68ca5b 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -206,6 +206,7 @@ cc_library_shared { shared_libs: [ "audioclient-types-aidl-unstable-cpp", "audioflinger-aidl-unstable-cpp", + "av-types-aidl-unstable-cpp", "libandroidicu", "libbpf_android", "libnetdbpf", diff --git a/media/jni/Android.bp b/media/jni/Android.bp index e71c141980d53..c7fb50f616666 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -32,6 +32,7 @@ cc_library_shared { shared_libs: [ "audioclient-types-aidl-unstable-cpp", + "av-types-aidl-unstable-cpp", "libandroid_runtime", "libaudioclient", "libnativehelper", From c3cd3cda9b710b1fd9de75ac13912dc09bd9af3d Mon Sep 17 00:00:00 2001 From: Ytai Ben-Tsvi Date: Fri, 30 Oct 2020 12:34:51 -0700 Subject: [PATCH 4/4] Remove manual parceling from Interpolator and VolumeShaper Change-Id: Ic5c3bfeb67c6e1b9b2b3c6275ea4badbef8536d3 --- Android.bp | 2 + ApiDocs.bp | 2 + StubLibraries.bp | 1 + media/java/android/media/PlayerBase.java | 7 +- media/java/android/media/PlayerProxy.java | 3 +- media/java/android/media/VolumeShaper.java | 274 ++++++++++++++++----- 6 files changed, 225 insertions(+), 64 deletions(-) diff --git a/Android.bp b/Android.bp index 6b55cc9f5ea86..36799e4bbf823 100644 --- a/Android.bp +++ b/Android.bp @@ -580,6 +580,7 @@ java_defaults { aidl: { generate_get_transaction_name: true, local_include_dirs: ["media/aidl"], + include_dirs: ["frameworks/av/aidl"], }, dxflags: [ "--core-library", @@ -614,6 +615,7 @@ java_defaults { // If MimeMap ever becomes its own APEX, then this dependency would need to be removed // in favor of an API stubs dependency in java_library "framework" below. "mimemap", + "av-types-aidl-java", "mediatranscoding_aidl_interface-java", "soundtrigger_middleware-aidl-java", ], diff --git a/ApiDocs.bp b/ApiDocs.bp index faa0e5dba9973..7ed7ec526686f 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -86,6 +86,7 @@ stubs_defaults { // TODO(b/169090544): remove below aidl includes. aidl: { local_include_dirs: ["media/aidl"], + include_dirs: ["frameworks/av/aidl"], }, } @@ -157,6 +158,7 @@ doc_defaults { // TODO(b/169090544): remove below aidl includes. aidl: { local_include_dirs: ["media/aidl"], + include_dirs: ["frameworks/av/aidl"], }, } diff --git a/StubLibraries.bp b/StubLibraries.bp index 8090bec24fdb7..9ca3739d9a266 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -57,6 +57,7 @@ stubs_defaults { "telephony/java", "media/aidl", ], + include_dirs: ["frameworks/av/aidl"], }, // These are libs from framework-internal-utils that are required (i.e. being referenced) // from framework-non-updatable-sources. Add more here when there's a need. diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java index df5e85edbc305..da69c6cbbb5c7 100644 --- a/media/java/android/media/PlayerBase.java +++ b/media/java/android/media/PlayerBase.java @@ -520,11 +520,12 @@ public abstract class PlayerBase { @Override public void applyVolumeShaper( - @NonNull VolumeShaper.Configuration configuration, - @NonNull VolumeShaper.Operation operation) { + @NonNull VolumeShaperConfiguration configuration, + @NonNull VolumeShaperOperation operation) { final PlayerBase pb = mWeakPB.get(); if (pb != null) { - pb.playerApplyVolumeShaper(configuration, operation); + pb.playerApplyVolumeShaper(VolumeShaper.Configuration.fromParcelable(configuration), + VolumeShaper.Operation.fromParcelable(operation)); } } } diff --git a/media/java/android/media/PlayerProxy.java b/media/java/android/media/PlayerProxy.java index 5f3997a50ce44..ec391284b0b2e 100644 --- a/media/java/android/media/PlayerProxy.java +++ b/media/java/android/media/PlayerProxy.java @@ -143,7 +143,8 @@ public class PlayerProxy { @NonNull VolumeShaper.Configuration configuration, @NonNull VolumeShaper.Operation operation) { try { - mConf.getIPlayer().applyVolumeShaper(configuration, operation); + mConf.getIPlayer().applyVolumeShaper(configuration.toParcelable(), + operation.toParcelable()); } catch (NullPointerException|RemoteException e) { throw new IllegalStateException( "No player to proxy for applyVolumeShaper operation," diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java index df8d08e8e846a..5bad6934f981a 100644 --- a/media/java/android/media/VolumeShaper.java +++ b/media/java/android/media/VolumeShaper.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import android.os.BadParcelableException; import android.os.Parcel; import android.os.Parcelable; @@ -482,50 +483,62 @@ public final class VolumeShaper implements AutoCloseable { @Override public void writeToParcel(Parcel dest, int flags) { - // this needs to match the native VolumeShaper.Configuration parceling - dest.writeInt(mType); - dest.writeInt(mId); - if (mType != TYPE_ID) { - dest.writeInt(mOptionFlags); - dest.writeDouble(mDurationMs); - // this needs to match the native Interpolator parceling - dest.writeInt(mInterpolatorType); - dest.writeFloat(0.f); // first slope (specifying for native side) - dest.writeFloat(0.f); // last slope (specifying for native side) - // mTimes and mVolumes should have the same length. - dest.writeInt(mTimes.length); - for (int i = 0; i < mTimes.length; ++i) { - dest.writeFloat(mTimes[i]); - dest.writeFloat(mVolumes[i]); - } - } + VolumeShaperConfiguration parcelable = toParcelable(); + parcelable.writeToParcel(dest, flags); } - public static final @android.annotation.NonNull Parcelable.Creator CREATOR - = new Parcelable.Creator() { - @Override - public VolumeShaper.Configuration createFromParcel(Parcel p) { - // this needs to match the native VolumeShaper.Configuration parceling - final int type = p.readInt(); - final int id = p.readInt(); - if (type == TYPE_ID) { - return new VolumeShaper.Configuration(id); - } else { - final int optionFlags = p.readInt(); - final double durationMs = p.readDouble(); - // this needs to match the native Interpolator parceling - final int interpolatorType = p.readInt(); - final float firstSlope = p.readFloat(); // ignored on the Java side - final float lastSlope = p.readFloat(); // ignored on the Java side - final int length = p.readInt(); - final float[] times = new float[length]; - final float[] volumes = new float[length]; - for (int i = 0; i < length; ++i) { - times[i] = p.readFloat(); - volumes[i] = p.readFloat(); - } + /** @hide */ + public VolumeShaperConfiguration toParcelable() { + VolumeShaperConfiguration parcelable = new VolumeShaperConfiguration(); + parcelable.type = typeToAidl(mType); + parcelable.id = mId; + if (mType != TYPE_ID) { + parcelable.optionFlags = optionFlagsToAidl(mOptionFlags); + parcelable.durationMs = mDurationMs; + parcelable.interpolatorConfig = toInterpolatorParcelable(); + } + return parcelable; + } - return new VolumeShaper.Configuration( + private InterpolatorConfig toInterpolatorParcelable() { + InterpolatorConfig parcelable = new InterpolatorConfig(); + parcelable.type = interpolatorTypeToAidl(mInterpolatorType); + parcelable.firstSlope = 0.f; // first slope (specifying for native side) + parcelable.lastSlope = 0.f; // last slope (specifying for native side) + parcelable.xy = new float[mTimes.length * 2]; + for (int i = 0; i < mTimes.length; ++i) { + parcelable.xy[i * 2] = mTimes[i]; + parcelable.xy[i * 2 + 1] = mVolumes[i]; + } + return parcelable; + } + + /** @hide */ + public static Configuration fromParcelable(VolumeShaperConfiguration parcelable) { + // this needs to match the native VolumeShaper.Configuration parceling + final int type = typeFromAidl(parcelable.type); + final int id = parcelable.id; + if (type == TYPE_ID) { + return new VolumeShaper.Configuration(id); + } else { + final int optionFlags = optionFlagsFromAidl(parcelable.optionFlags); + final double durationMs = parcelable.durationMs; + final int interpolatorType = interpolatorTypeFromAidl( + parcelable.interpolatorConfig.type); + // parcelable.interpolatorConfig.firstSlope is ignored on the Java side + // parcelable.interpolatorConfig.lastSlope is ignored on the Java side + final int length = parcelable.interpolatorConfig.xy.length; + if (length % 2 != 0) { + throw new android.os.BadParcelableException("xy length must be even"); + } + final float[] times = new float[length / 2]; + final float[] volumes = new float[length / 2]; + for (int i = 0; i < length / 2; ++i) { + times[i] = parcelable.interpolatorConfig.xy[i * 2]; + volumes[i] = parcelable.interpolatorConfig.xy[i * 2 + 1]; + } + + return new VolumeShaper.Configuration( type, id, optionFlags, @@ -533,7 +546,14 @@ public final class VolumeShaper implements AutoCloseable { interpolatorType, times, volumes); - } + } + } + + public static final @android.annotation.NonNull Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public VolumeShaper.Configuration createFromParcel(Parcel p) { + return fromParcelable(VolumeShaperConfiguration.CREATOR.createFromParcel(p)); } @Override @@ -542,6 +562,84 @@ public final class VolumeShaper implements AutoCloseable { } }; + private static @InterpolatorType + int interpolatorTypeFromAidl(@android.media.InterpolatorType int aidl) { + switch (aidl) { + case android.media.InterpolatorType.STEP: + return INTERPOLATOR_TYPE_STEP; + case android.media.InterpolatorType.LINEAR: + return INTERPOLATOR_TYPE_LINEAR; + case android.media.InterpolatorType.CUBIC: + return INTERPOLATOR_TYPE_CUBIC; + case android.media.InterpolatorType.CUBIC_MONOTONIC: + return INTERPOLATOR_TYPE_CUBIC_MONOTONIC; + default: + throw new BadParcelableException("Unknown interpolator type"); + } + } + + private static @android.media.InterpolatorType + int interpolatorTypeToAidl(@InterpolatorType int type) { + switch (type) { + case INTERPOLATOR_TYPE_STEP: + return android.media.InterpolatorType.STEP; + case INTERPOLATOR_TYPE_LINEAR: + return android.media.InterpolatorType.LINEAR; + case INTERPOLATOR_TYPE_CUBIC: + return android.media.InterpolatorType.CUBIC; + case INTERPOLATOR_TYPE_CUBIC_MONOTONIC: + return android.media.InterpolatorType.CUBIC_MONOTONIC; + default: + throw new RuntimeException("Unknown interpolator type"); + } + } + + private static @Type + int typeFromAidl(@android.media.VolumeShaperConfigurationType int aidl) { + switch (aidl) { + case VolumeShaperConfigurationType.ID: + return TYPE_ID; + case VolumeShaperConfigurationType.SCALE: + return TYPE_SCALE; + default: + throw new BadParcelableException("Unknown type"); + } + } + + private static @android.media.VolumeShaperConfigurationType + int typeToAidl(@Type int type) { + switch (type) { + case TYPE_ID: + return VolumeShaperConfigurationType.ID; + case TYPE_SCALE: + return VolumeShaperConfigurationType.SCALE; + default: + throw new RuntimeException("Unknown type"); + } + } + + private static int optionFlagsFromAidl(int aidl) { + int result = 0; + if ((aidl & (1 << VolumeShaperConfigurationOptionFlag.VOLUME_IN_DBFS)) != 0) { + result |= OPTION_FLAG_VOLUME_IN_DBFS; + } + if ((aidl & (1 << VolumeShaperConfigurationOptionFlag.CLOCK_TIME)) != 0) { + result |= OPTION_FLAG_CLOCK_TIME; + } + return result; + } + + private static int optionFlagsToAidl(int flags) { + int result = 0; + if ((flags & OPTION_FLAG_VOLUME_IN_DBFS) != 0) { + result |= (1 << VolumeShaperConfigurationOptionFlag.VOLUME_IN_DBFS); + } + if ((flags & OPTION_FLAG_CLOCK_TIME) != 0) { + result |= (1 << VolumeShaperConfigurationOptionFlag.CLOCK_TIME); + } + return result; + } + /** * @hide * Constructs a {@code VolumeShaper} from an id. @@ -1172,25 +1270,31 @@ public final class VolumeShaper implements AutoCloseable { @Override public void writeToParcel(Parcel dest, int flags) { - // this needs to match the native VolumeShaper.Operation parceling - dest.writeInt(mFlags); - dest.writeInt(mReplaceId); - dest.writeFloat(mXOffset); + toParcelable().writeToParcel(dest, flags); + } + + /** @hide */ + public VolumeShaperOperation toParcelable() { + VolumeShaperOperation result = new VolumeShaperOperation(); + result.flags = flagsToAidl(mFlags); + result.replaceId = mReplaceId; + result.xOffset = mXOffset; + return result; + } + + /** @hide */ + public static Operation fromParcelable(VolumeShaperOperation parcelable) { + return new VolumeShaper.Operation( + flagsFromAidl(parcelable.flags), + parcelable.replaceId, + parcelable.xOffset); } public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public VolumeShaper.Operation createFromParcel(Parcel p) { - // this needs to match the native VolumeShaper.Operation parceling - final int flags = p.readInt(); - final int replaceId = p.readInt(); - final float xOffset = p.readFloat(); - - return new VolumeShaper.Operation( - flags - , replaceId - , xOffset); + return fromParcelable(VolumeShaperOperation.CREATOR.createFromParcel(p)); } @Override @@ -1199,6 +1303,46 @@ public final class VolumeShaper implements AutoCloseable { } }; + private static int flagsFromAidl(int aidl) { + int result = 0; + if ((aidl & (1 << VolumeShaperOperationFlag.REVERSE)) != 0) { + result |= FLAG_REVERSE; + } + if ((aidl & (1 << VolumeShaperOperationFlag.TERMINATE)) != 0) { + result |= FLAG_TERMINATE; + } + if ((aidl & (1 << VolumeShaperOperationFlag.JOIN)) != 0) { + result |= FLAG_JOIN; + } + if ((aidl & (1 << VolumeShaperOperationFlag.DELAY)) != 0) { + result |= FLAG_DEFER; + } + if ((aidl & (1 << VolumeShaperOperationFlag.CREATE_IF_NECESSARY)) != 0) { + result |= FLAG_CREATE_IF_NEEDED; + } + return result; + } + + private static int flagsToAidl(int flags) { + int result = 0; + if ((flags & FLAG_REVERSE) != 0) { + result |= (1 << VolumeShaperOperationFlag.REVERSE); + } + if ((flags & FLAG_TERMINATE) != 0) { + result |= (1 << VolumeShaperOperationFlag.TERMINATE); + } + if ((flags & FLAG_JOIN) != 0) { + result |= (1 << VolumeShaperOperationFlag.JOIN); + } + if ((flags & FLAG_DEFER) != 0) { + result |= (1 << VolumeShaperOperationFlag.DELAY); + } + if ((flags & FLAG_CREATE_IF_NEEDED) != 0) { + result |= (1 << VolumeShaperOperationFlag.CREATE_IF_NECESSARY); + } + return result; + } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private Operation(@Flag int flags, int replaceId, float xOffset) { mFlags = flags; @@ -1393,17 +1537,27 @@ public final class VolumeShaper implements AutoCloseable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeFloat(mVolume); - dest.writeFloat(mXOffset); + toParcelable().writeToParcel(dest, flags); + } + + /** @hide */ + public VolumeShaperState toParcelable() { + VolumeShaperState result = new VolumeShaperState(); + result.volume = mVolume; + result.xOffset = mXOffset; + return result; + } + + /** @hide */ + public static State fromParcelable(VolumeShaperState p) { + return new VolumeShaper.State(p.volume, p.xOffset); } public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public VolumeShaper.State createFromParcel(Parcel p) { - return new VolumeShaper.State( - p.readFloat() // volume - , p.readFloat()); // xOffset + return fromParcelable(VolumeShaperState.CREATOR.createFromParcel(p)); } @Override