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

Commit 9fded33b authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "Muting notifications due to focus is conditional on recording" into main

parents 0d6c1096 a97cd681
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1882,6 +1882,7 @@ package android.media {
    method public void setRampingRingerEnabled(boolean);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void setRs2Value(float);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setTestDeviceConnectionState(@NonNull android.media.AudioDeviceAttributes, boolean);
    method @FlaggedApi("android.media.audio.focus_exclusive_with_recording") @RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE) public boolean shouldNotificationSoundPlay(@NonNull android.media.AudioAttributes);
  }

  public static final class AudioRecord.MetricsConstants {
+23 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING;
import static android.media.audio.Flags.FLAG_FOCUS_FREEZE_TEST_API;
import static android.media.audiopolicy.Flags.FLAG_ENABLE_FADE_MANAGER_CONFIGURATION;

@@ -10081,6 +10082,28 @@ public class AudioManager {
        }
    }

    /**
     * @hide
     * Checks whether a notification sound should be played or not, as reported by the state
     * of the audio framework. Querying whether playback should proceed is favored over
     * playing and letting the sound be muted or not.
     * @param aa the {@link AudioAttributes} of the notification about to maybe play
     * @return true if the audio framework state is such that the notification should be played
     *    because at time of checking, and the notification will be heard,
     *    false otherwise
     */
    @TestApi
    @FlaggedApi(FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING)
    @RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE)
    public boolean shouldNotificationSoundPlay(@NonNull final AudioAttributes aa) {
        final IAudioService service = getService();
        try {
            return service.shouldNotificationSoundPlay(Objects.requireNonNull(aa));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    //====================================================================
    // Mute await connection

+4 −0
Original line number Diff line number Diff line
@@ -775,4 +775,8 @@ interface IAudioService {
    @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)")
    FadeManagerConfiguration getFadeManagerConfigurationForFocusLoss();

    @EnforcePermission("QUERY_AUDIO_STATE")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE)")
    boolean shouldNotificationSoundPlay(in AudioAttributes aa);
}
+40 −0
Original line number Diff line number Diff line
@@ -13591,6 +13591,46 @@ public class AudioService extends IAudioService.Stub
        }
    }
    /**
     * @see AudioManager#shouldNotificationSoundPlay(AudioAttributes)
     */
    @android.annotation.EnforcePermission(
            android.Manifest.permission.QUERY_AUDIO_STATE)
    public boolean shouldNotificationSoundPlay(@NonNull final AudioAttributes aa) {
        super.shouldNotificationSoundPlay_enforcePermission();
        Objects.requireNonNull(aa);
        // don't play notifications if the stream volume associated with the
        // AudioAttributes of the notification record is 0 (non-zero volume implies
        // not silenced by SILENT or VIBRATE ringer mode)
        final int stream = AudioAttributes.toLegacyStreamType(aa);
        final boolean mutingFromVolume = getStreamVolume(stream) == 0;
        if (mutingFromVolume) {
            if (DEBUG_VOL) {
                Slog.d(TAG, "notification should not play due to muted stream " + stream);
            }
            return false;
        }
        // don't play notifications if there is a user of GAIN_TRANSIENT_EXCLUSIVE audio focus
        // and the focus owner is recording
        final int uid = mMediaFocusControl.getExclusiveFocusOwnerUid();
        if (uid == -1) { // return value is -1 if focus isn't GAIN_TRANSIENT_EXCLUSIVE
            return true;
        }
        // is the owner of GAIN_TRANSIENT_EXCLUSIVE focus also recording?
        final boolean mutingFromFocusAndRecording = mRecordMonitor.isRecordingActiveForUid(uid);
        if (mutingFromFocusAndRecording) {
            if (DEBUG_VOL) {
                Slog.d(TAG, "notification should not play due to exclusive focus owner recording "
                        + " uid:" + uid);
            }
            return false;
        }
        return true;
    }
    //======================
    // Audioserver state dispatch
    //======================
+17 −0
Original line number Diff line number Diff line
@@ -296,6 +296,23 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
        }
    }

    /**
     * Return the UID of the focus owner that has focus with exclusive focus gain
     * @return -1 if nobody has exclusive focus, the UID of the owner otherwise
     */
    protected int getExclusiveFocusOwnerUid() {
        synchronized (mAudioFocusLock) {
            if (mFocusStack.empty()) {
                return -1;
            }
            final FocusRequester owner = mFocusStack.peek();
            if (owner.getGainRequest() != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
                return -1;
            }
            return owner.getClientUid();
        }
    }

    /**
     * Send AUDIOFOCUS_LOSS to a specific stack entry.
     * Note this method is supporting an external API, and is restricted to LOSS in order to
Loading