Loading media/java/android/media/Ringtone.java +33 −7 Original line number Diff line number Diff line Loading @@ -158,13 +158,15 @@ public class Ringtone { /** * 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 */ public void createLocalMediaPlayer() { public boolean createLocalMediaPlayer() { Trace.beginSection("createLocalMediaPlayer"); if (mUri == null) { Log.e(TAG, "Could not create media player as no URI was provided."); return; return mAllowRemote && mRemotePlayer != null; } destroyLocalPlayer(); // try opening uri locally before delegating to remote player Loading Loading @@ -195,6 +197,30 @@ public class Ringtone { } } 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; } /** Loading Loading @@ -423,7 +449,6 @@ public class Ringtone { */ public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) { mVolumeShaperConfig = volumeShaperConfig; mUri = uri; if (mUri == null) { destroyLocalPlayer(); Loading @@ -443,10 +468,11 @@ public class Ringtone { if (mLocalPlayer != null) { // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone // (typically because ringer mode is vibrate). boolean isHapticOnly = AudioManager.hasHapticChannels(mContext, mUri) && !mAudioAttributes.areHapticChannelsMuted() && mVolume == 0; if (isHapticOnly || mAudioManager.getStreamVolume( AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) { if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) { startLocalPlayer(); } else if (!mAudioAttributes.areHapticChannelsMuted() && hasHapticChannels()) { // is haptic only ringtone startLocalPlayer(); } } else if (mAllowRemote && (mRemotePlayer != null) && (mUri != null)) { Loading media/java/android/media/RingtoneManager.java +38 −31 Original line number Diff line number Diff line Loading @@ -720,11 +720,14 @@ public class RingtoneManager { @Nullable VolumeShaper.Configuration volumeShaperConfig, AudioAttributes audioAttributes) { // Don't set the stream type Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false); Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false); if (ringtone != null) { ringtone.setAudioAttributesField(audioAttributes); ringtone.createLocalMediaPlayer(); if (!ringtone.createLocalMediaPlayer()) { Log.e(TAG, "Failed to open ringtone " + ringtoneUri); return null; } } return ringtone; } Loading @@ -750,19 +753,6 @@ public class RingtoneManager { 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, @Nullable VolumeShaper.Configuration volumeShaperConfig, boolean createLocalMediaPlayer) { Loading @@ -776,7 +766,10 @@ public class RingtoneManager { r.setVolumeShaperConfig(volumeShaperConfig); r.setUri(ringtoneUri, volumeShaperConfig); if (createLocalMediaPlayer) { r.createLocalMediaPlayer(); if (!r.createLocalMediaPlayer()) { Log.e(TAG, "Failed to open ringtone " + ringtoneUri); return null; } } return r; } catch (Exception ex) { Loading Loading @@ -1157,6 +1150,20 @@ public class RingtoneManager { 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 final String filename = getDefaultRingtoneFilename(type); final String whichAudio = getQueryStringForType(type); Loading @@ -1169,11 +1176,11 @@ public class RingtoneManager { if (cursor.moveToFirst()) { final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse( ContentUris.withAppendedId(baseUri, cursor.getLong(0))); RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri); Settings.System.putInt(context.getContentResolver(), setting, 1); } return ringtoneUri; } } return null; } private static String getDefaultRingtoneSetting(int type) { Loading Loading
media/java/android/media/Ringtone.java +33 −7 Original line number Diff line number Diff line Loading @@ -158,13 +158,15 @@ public class Ringtone { /** * 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 */ public void createLocalMediaPlayer() { public boolean createLocalMediaPlayer() { Trace.beginSection("createLocalMediaPlayer"); if (mUri == null) { Log.e(TAG, "Could not create media player as no URI was provided."); return; return mAllowRemote && mRemotePlayer != null; } destroyLocalPlayer(); // try opening uri locally before delegating to remote player Loading Loading @@ -195,6 +197,30 @@ public class Ringtone { } } 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; } /** Loading Loading @@ -423,7 +449,6 @@ public class Ringtone { */ public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) { mVolumeShaperConfig = volumeShaperConfig; mUri = uri; if (mUri == null) { destroyLocalPlayer(); Loading @@ -443,10 +468,11 @@ public class Ringtone { if (mLocalPlayer != null) { // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone // (typically because ringer mode is vibrate). boolean isHapticOnly = AudioManager.hasHapticChannels(mContext, mUri) && !mAudioAttributes.areHapticChannelsMuted() && mVolume == 0; if (isHapticOnly || mAudioManager.getStreamVolume( AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) { if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) { startLocalPlayer(); } else if (!mAudioAttributes.areHapticChannelsMuted() && hasHapticChannels()) { // is haptic only ringtone startLocalPlayer(); } } else if (mAllowRemote && (mRemotePlayer != null) && (mUri != null)) { Loading
media/java/android/media/RingtoneManager.java +38 −31 Original line number Diff line number Diff line Loading @@ -720,11 +720,14 @@ public class RingtoneManager { @Nullable VolumeShaper.Configuration volumeShaperConfig, AudioAttributes audioAttributes) { // Don't set the stream type Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false); Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false); if (ringtone != null) { ringtone.setAudioAttributesField(audioAttributes); ringtone.createLocalMediaPlayer(); if (!ringtone.createLocalMediaPlayer()) { Log.e(TAG, "Failed to open ringtone " + ringtoneUri); return null; } } return ringtone; } Loading @@ -750,19 +753,6 @@ public class RingtoneManager { 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, @Nullable VolumeShaper.Configuration volumeShaperConfig, boolean createLocalMediaPlayer) { Loading @@ -776,7 +766,10 @@ public class RingtoneManager { r.setVolumeShaperConfig(volumeShaperConfig); r.setUri(ringtoneUri, volumeShaperConfig); if (createLocalMediaPlayer) { r.createLocalMediaPlayer(); if (!r.createLocalMediaPlayer()) { Log.e(TAG, "Failed to open ringtone " + ringtoneUri); return null; } } return r; } catch (Exception ex) { Loading Loading @@ -1157,6 +1150,20 @@ public class RingtoneManager { 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 final String filename = getDefaultRingtoneFilename(type); final String whichAudio = getQueryStringForType(type); Loading @@ -1169,11 +1176,11 @@ public class RingtoneManager { if (cursor.moveToFirst()) { final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse( ContentUris.withAppendedId(baseUri, cursor.getLong(0))); RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri); Settings.System.putInt(context.getContentResolver(), setting, 1); } return ringtoneUri; } } return null; } private static String getDefaultRingtoneSetting(int type) { Loading