Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f91d50b6 authored by Kevin Rocard's avatar Kevin Rocard
Browse files

Introduce playback capture application manifest flag

Allow apps to opt-out of their playback beeing recorded with an
application wide out-out.

Previously an application had to opt-out on each of its audio tracks.

Application targeting an SDK < Q are considered opt-out by default.
Application targeting an SDK >= Q are considered opt-in by default.

Test: adb shell audiorecorder --target /data/file1.raw &
      adb shell am start -a android.intent.action.VIEW -d file:///system/media/audio/ringtones/Lollipop.ogg -t audio/ogg
      adb dumpsys media.audio_policy # check playback is *not* recorded
      # change packages/apps/Music manifest to allowPlaybackCapture=true
      adb install out/target/product/walleye/system/product/app/Music/Music.apk
      adb shell am start -a android.intent.action.VIEW -d file:///system/media/audio/ringtones/Lollipop.ogg

 -t audio/ogg
      adb dumpsys media.audio_policy # check playback is recorded
      kill %1
      adb pull /data/file1.raw && sox -r 48000 -e signed -b 16 -c 2 file1.raw file.wav&& audacity file.wav
      # check that the audio file contains first silence then the ringtone after the manifest flag was added
Bug: 111453086
Change-Id: Ie617b15f481a7f148b6e9fc9d64e61acaa5ce71d
Signed-off-by: default avatarKevin Rocard <krocard@google.com>
parent 2f9dd0aa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ package android {
    field public static final int alertDialogTheme = 16843529; // 0x1010309
    field public static final int alignmentMode = 16843642; // 0x101037a
    field public static final int allContactsName = 16843468; // 0x10102cc
    field public static final int allowAudioPlaybackCapture = 16844199; // 0x10105a7
    field public static final int allowBackup = 16843392; // 0x1010280
    field public static final int allowClearUserData = 16842757; // 0x1010005
    field public static final int allowEmbedded = 16843765; // 0x10103f5
+23 −1
Original line number Diff line number Diff line
@@ -662,6 +662,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     */
    public static final int PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE = 1 << 26;

    /**
     * Value for {@link #privateFlags}: true if the application allows its audio playback
     * to be captured by other apps.
     *
     * @hide
     */
    public static final int PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE  = 1 << 27;

    /** @hide */
    @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
            PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -688,7 +696,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
            PRIVATE_FLAG_VENDOR,
            PRIVATE_FLAG_VIRTUAL_PRELOAD,
            PRIVATE_FLAG_HAS_FRAGILE_USER_DATA,
            PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE
            PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE,
            PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ApplicationInfoPrivateFlags {}
@@ -1342,6 +1351,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
            }
            pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
            pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
            pw.println(prefix + "allowsPlaybackCapture="
                        + (isAudioPlaybackCaptureAllowed() ? "true" : "false"));
        }
        super.dumpBack(pw, prefix);
    }
@@ -1790,6 +1801,17 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        return (privateFlags & PRIVATE_FLAG_HAS_FRAGILE_USER_DATA) != 0;
    }

    /**
     * Whether an app allows its playback audio to be captured by other apps.
     *
     * @return {@code true} if the app indicates that its audio can be captured by other apps.
     *
     * @hide
     */
    public boolean isAudioPlaybackCaptureAllowed() {
        return (privateFlags & PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE) != 0;
    }

    private boolean isAllowedToUseHiddenApis() {
        if (isSignedWithPlatformKey()) {
            return true;
+6 −0
Original line number Diff line number Diff line
@@ -3753,6 +3753,12 @@ public class PackageParser {
            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
        }

        if (sa.getBoolean(
                R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture,
                owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) {
            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE;
        }

        ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
        ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);

+3 −0
Original line number Diff line number Diff line
@@ -1667,6 +1667,9 @@
             This flag is turned on by default. <em>This attribute is usable only by system apps.
             </em> -->
        <attr name="allowClearUserDataOnFailedRestore"/>
        <!-- If {@code true} the app's non sensitive audio can be capture by other apps.
             The default value is true. -->
        <attr name="allowAudioPlaybackCapture" format="boolean" />
    </declare-styleable>
    <!-- The <code>permission</code> tag declares a security permission that can be
         used to control access from other packages to specific components or
+1 −0
Original line number Diff line number Diff line
@@ -2941,6 +2941,7 @@
        <public name="forceUriPermissions" />
        <!-- @hide @SystemApi -->
        <public name="allowClearUserDataOnFailedRestore"/>
        <public name="allowAudioPlaybackCapture"/>
    </public-group>

    <public-group type="drawable" first-id="0x010800b4">
Loading