From 3b566b84708eea887ab3e1e1bbba4b2242b261d6 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 12 Nov 2014 10:39:56 -0800 Subject: [PATCH] Move ringtone redirection to MediaPlayer. Way back in API 1 we defined Settings.System.DEFAULT_NOTIFICATION_URI which redirects through SettingsProvider before finally ariving at the real underlying ContentProvider, usually MediaStore. With new SELinux rules, we're no longer allowing the system_server to hold open FDs to shared storage devices, which causes these proxied openFile() calls to fail. To work around this, teach MediaPlayer to resolve the final ringtone Uri without going through the system. Bug: 18226181 Change-Id: I40c68617c952c0bb3e939e5084f5b68a35e31ae3 --- media/java/android/media/MediaPlayer.java | 12 ++- .../providers/settings/SettingsProvider.java | 76 +------------------ 2 files changed, 11 insertions(+), 77 deletions(-) diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index afa0b6e8ce21b..91b1018d9ce24 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -37,6 +37,7 @@ import android.os.Process; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.provider.Settings; import android.system.ErrnoException; import android.system.OsConstants; import android.util.Log; @@ -968,11 +969,16 @@ public class MediaPlayer implements SubtitleController.Listener * @throws IllegalStateException if it is called in an invalid state */ public void setDataSource(Context context, Uri uri, Map headers) - throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { - String scheme = uri.getScheme(); - if(scheme == null || scheme.equals("file")) { + throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { + final String scheme = uri.getScheme(); + if (ContentResolver.SCHEME_FILE.equals(scheme)) { setDataSource(uri.getPath()); return; + } else if (ContentResolver.SCHEME_CONTENT.equals(scheme) + && Settings.AUTHORITY.equals(uri.getAuthority())) { + // Redirect ringtones to go directly to underlying provider + uri = RingtoneManager.getActualDefaultRingtoneUri(context, + RingtoneManager.getDefaultType(uri)); } AssetFileDescriptor fd = null; diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 34e57bcae4a6f..6828301cf2d94 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -37,13 +37,11 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; -import android.content.res.AssetFileDescriptor; import android.database.AbstractCursor; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteQueryBuilder; -import android.media.RingtoneManager; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -54,7 +52,6 @@ import android.os.Process; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; -import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.Secure; import android.text.TextUtils; @@ -1228,77 +1225,8 @@ public class SettingsProvider extends ContentProvider { @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - - /* - * When a client attempts to openFile the default ringtone or - * notification setting Uri, we will proxy the call to the current - * default ringtone's Uri (if it is in the media provider). - */ - int ringtoneType = RingtoneManager.getDefaultType(uri); - // Above call returns -1 if the Uri doesn't match a default type - if (ringtoneType != -1) { - Context context = getContext(); - - // Get the current value for the default sound - Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); - - if (soundUri != null) { - // Proxy the openFile call to media provider - String authority = soundUri.getAuthority(); - if (authority.equals(MediaStore.AUTHORITY)) { - return context.getContentResolver().openFileDescriptor(soundUri, mode); - } - } - } - - return super.openFile(uri, mode); - } - - @Override - public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { - - /* - * When a client attempts to openFile the default ringtone or - * notification setting Uri, we will proxy the call to the current - * default ringtone's Uri (if it is in the media provider). - */ - int ringtoneType = RingtoneManager.getDefaultType(uri); - // Above call returns -1 if the Uri doesn't match a default type - if (ringtoneType != -1) { - Context context = getContext(); - - // Get the current value for the default sound - Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); - - if (soundUri != null) { - // Proxy the openFile call to media provider - String authority = soundUri.getAuthority(); - if (authority.equals(MediaStore.AUTHORITY)) { - ParcelFileDescriptor pfd = null; - try { - pfd = context.getContentResolver().openFileDescriptor(soundUri, mode); - return new AssetFileDescriptor(pfd, 0, -1); - } catch (FileNotFoundException ex) { - // fall through and open the fallback ringtone below - } - } - - try { - return super.openAssetFile(soundUri, mode); - } catch (FileNotFoundException ex) { - // Since a non-null Uri was specified, but couldn't be opened, - // fall back to the built-in ringtone. - return context.getResources().openRawResourceFd( - com.android.internal.R.raw.fallbackring); - } - } - // no need to fall through and have openFile() try again, since we - // already know that will fail. - throw new FileNotFoundException(); // or return null ? - } - - // Note that this will end up calling openFile() above. - return super.openAssetFile(uri, mode); + throw new FileNotFoundException("Direct file access no longer supported; " + + "ringtone playback is available through android.media.Ringtone"); } /**