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

Commit 833b169e authored by Edgar Arriaga's avatar Edgar Arriaga
Browse files

Reuse ringtone across multiple ringer operations

This patch avoids multiple ringtone loads when taking place
that were redundant as previous approach instantiated the
same ringtone multiple times over the play flow instead we
gather all the requirements for a ringtone and instantiate
it once.

Bug: 240621827
Test: atest RingtoneTest
Test: atest RingerTest
Test: atest IncomingCallTest
Test: Verified ringtone and vibration works in various forms when
receiving call.

Change-Id: I7ac0a52c99d48fb7241c55c709a9a876a6057319
parent 5f359071
Loading
Loading
Loading
Loading
+33 −7
Original line number Original line Diff line number Diff line
@@ -158,13 +158,15 @@ public class Ringtone {


    /**
    /**
     * Creates a local media player for the ringtone using currently set attributes.
     * Creates a local media player for the ringtone using currently set attributes.
     * @return true if media player creation succeeded or is deferred,
     * false if it did not succeed and can't be tried remotely.
     * @hide
     * @hide
     */
     */
    public void createLocalMediaPlayer() {
    public boolean createLocalMediaPlayer() {
        Trace.beginSection("createLocalMediaPlayer");
        Trace.beginSection("createLocalMediaPlayer");
        if (mUri == null) {
        if (mUri == null) {
            Log.e(TAG, "Could not create media player as no URI was provided.");
            Log.e(TAG, "Could not create media player as no URI was provided.");
            return;
            return mAllowRemote && mRemotePlayer != null;
        }
        }
        destroyLocalPlayer();
        destroyLocalPlayer();
        // try opening uri locally before delegating to remote player
        // try opening uri locally before delegating to remote player
@@ -195,6 +197,30 @@ public class Ringtone {
            }
            }
        }
        }
        Trace.endSection();
        Trace.endSection();
        return mLocalPlayer != null || (mAllowRemote && mRemotePlayer != null);
    }

    /**
     * Same as AudioManager.hasHapticChannels except it assumes an already created ringtone.
     * If the ringtone has not been created, it will load based on URI provided at {@link #setUri}
     * and if not URI has been set, it will assume no haptic channels are present.
     * @hide
     */
    public boolean hasHapticChannels() {
        // FIXME: support remote player, or internalize haptic channels support and remove entirely.
        try {
            android.os.Trace.beginSection("Ringtone.hasHapticChannels");
            if (mLocalPlayer != null) {
                for(MediaPlayer.TrackInfo trackInfo : mLocalPlayer.getTrackInfo()) {
                    if (trackInfo.hasHapticChannels()) {
                        return true;
                    }
                }
            }
        } finally {
            android.os.Trace.endSection();
        }
        return false;
    }
    }


    /**
    /**
@@ -423,7 +449,6 @@ public class Ringtone {
     */
     */
    public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) {
    public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) {
        mVolumeShaperConfig = volumeShaperConfig;
        mVolumeShaperConfig = volumeShaperConfig;

        mUri = uri;
        mUri = uri;
        if (mUri == null) {
        if (mUri == null) {
            destroyLocalPlayer();
            destroyLocalPlayer();
@@ -443,10 +468,11 @@ public class Ringtone {
        if (mLocalPlayer != null) {
        if (mLocalPlayer != null) {
            // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
            // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
            // (typically because ringer mode is vibrate).
            // (typically because ringer mode is vibrate).
            boolean isHapticOnly = AudioManager.hasHapticChannels(mContext, mUri)
            if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
                    && !mAudioAttributes.areHapticChannelsMuted() && mVolume == 0;
                    != 0) {
            if (isHapticOnly || mAudioManager.getStreamVolume(
                startLocalPlayer();
                    AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) {
            } else if (!mAudioAttributes.areHapticChannelsMuted() && hasHapticChannels()) {
                // is haptic only ringtone
                startLocalPlayer();
                startLocalPlayer();
            }
            }
        } else if (mAllowRemote && (mRemotePlayer != null) && (mUri != null)) {
        } else if (mAllowRemote && (mRemotePlayer != null) && (mUri != null)) {
+38 −31
Original line number Original line Diff line number Diff line
@@ -720,11 +720,14 @@ public class RingtoneManager {
            @Nullable VolumeShaper.Configuration volumeShaperConfig,
            @Nullable VolumeShaper.Configuration volumeShaperConfig,
            AudioAttributes audioAttributes) {
            AudioAttributes audioAttributes) {
        // Don't set the stream type
        // Don't set the stream type
        Ringtone ringtone =
        Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */,
                getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false);
                volumeShaperConfig, false);
        if (ringtone != null) {
        if (ringtone != null) {
            ringtone.setAudioAttributesField(audioAttributes);
            ringtone.setAudioAttributesField(audioAttributes);
            ringtone.createLocalMediaPlayer();
            if (!ringtone.createLocalMediaPlayer()) {
                Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
                return null;
            }
        }
        }
        return ringtone;
        return ringtone;
    }
    }
@@ -750,19 +753,6 @@ public class RingtoneManager {
                createLocalMediaPlayer);
                createLocalMediaPlayer);
    }
    }


    //FIXME bypass the notion of stream types within the class
    /**
     * Returns a {@link Ringtone} with {@link VolumeShaper} if required for a given sound URI on
     * the given stream type. Normally, if you change the stream type on the returned
     * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just
     * an optimized route to avoid that.
     *
     * @param streamType The stream type for the ringtone, or -1 if it should
     *            not be set (and the default used instead).
     * @param volumeShaperConfig config for volume shaper of the ringtone if applied.
     * @see #getRingtone(Context, Uri)
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType,
            @Nullable VolumeShaper.Configuration volumeShaperConfig,
            @Nullable VolumeShaper.Configuration volumeShaperConfig,
            boolean createLocalMediaPlayer) {
            boolean createLocalMediaPlayer) {
@@ -776,7 +766,10 @@ public class RingtoneManager {
            r.setVolumeShaperConfig(volumeShaperConfig);
            r.setVolumeShaperConfig(volumeShaperConfig);
            r.setUri(ringtoneUri, volumeShaperConfig);
            r.setUri(ringtoneUri, volumeShaperConfig);
            if (createLocalMediaPlayer) {
            if (createLocalMediaPlayer) {
                r.createLocalMediaPlayer();
                if (!r.createLocalMediaPlayer()) {
                    Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
                    return null;
                }
            }
            }
            return r;
            return r;
        } catch (Exception ex) {
        } catch (Exception ex) {
@@ -1157,6 +1150,20 @@ public class RingtoneManager {
                continue;
                continue;
            }
            }


            // Try finding the scanned ringtone
            Uri ringtoneUri = computeDefaultRingtoneUri(context, type);
            if (ringtoneUri != null) {
                RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
                Settings.System.putInt(context.getContentResolver(), setting, 1);
            }
        }
    }

    /**
     * @param type the type of ringtone (e.g {@link #TYPE_RINGTONE})
     * @return the system default URI if found, null otherwise.
     */
    private static Uri computeDefaultRingtoneUri(@NonNull Context context, int type) {
        // Try finding the scanned ringtone
        // Try finding the scanned ringtone
        final String filename = getDefaultRingtoneFilename(type);
        final String filename = getDefaultRingtoneFilename(type);
        final String whichAudio = getQueryStringForType(type);
        final String whichAudio = getQueryStringForType(type);
@@ -1169,11 +1176,11 @@ public class RingtoneManager {
            if (cursor.moveToFirst()) {
            if (cursor.moveToFirst()) {
                final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse(
                final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse(
                        ContentUris.withAppendedId(baseUri, cursor.getLong(0)));
                        ContentUris.withAppendedId(baseUri, cursor.getLong(0)));
                    RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
                return ringtoneUri;
                    Settings.System.putInt(context.getContentResolver(), setting, 1);
                }
            }
            }
        }
        }

        return null;
    }
    }


    private static String getDefaultRingtoneSetting(int type) {
    private static String getDefaultRingtoneSetting(int type) {