diff options
| -rw-r--r-- | core/java/android/preference/VolumePreference.java | 38 | ||||
| -rw-r--r-- | core/java/android/view/VolumePanel.java | 31 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 2 | ||||
| -rw-r--r-- | media/java/android/media/RingtoneManager.java | 22 | ||||
| -rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 68 |
5 files changed, 128 insertions, 33 deletions
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java index abdcd93..db25cfa 100644 --- a/core/java/android/preference/VolumePreference.java +++ b/core/java/android/preference/VolumePreference.java @@ -28,6 +28,7 @@ import android.preference.PreferenceManager; import android.provider.Settings; import android.provider.Settings.System; import android.util.AttributeSet; +import android.view.KeyEvent; import android.view.View; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -36,7 +37,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener; * @hide */ public class VolumePreference extends SeekBarPreference implements - PreferenceManager.OnActivityStopListener { + PreferenceManager.OnActivityStopListener, View.OnKeyListener { private static final String TAG = "VolumePreference"; @@ -66,6 +67,30 @@ public class VolumePreference extends SeekBarPreference implements mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType); getPreferenceManager().registerOnActivityStopListener(this); + + // grab focus and key events so that pressing the volume buttons in the + // dialog doesn't also show the normal volume adjust toast. + view.setOnKeyListener(this); + view.setFocusableInTouchMode(true); + view.requestFocus(); + } + + public boolean onKey(View v, int keyCode, KeyEvent event) { + boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN); + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + if (isdown) { + mSeekBarVolumizer.changeVolumeBy(-1); + } + return true; + case KeyEvent.KEYCODE_VOLUME_UP: + if (isdown) { + mSeekBarVolumizer.changeVolumeBy(1); + } + return true; + default: + return false; + } } @Override @@ -158,7 +183,9 @@ public class VolumePreference extends SeekBarPreference implements } mRingtone = RingtoneManager.getRingtone(mContext, defaultUri); - mRingtone.setStreamType(mStreamType); + if (mRingtone != null) { + mRingtone.setStreamType(mStreamType); + } } public void stop() { @@ -215,5 +242,12 @@ public class VolumePreference extends SeekBarPreference implements return mSeekBar; } + public void changeVolumeBy(int amount) { + mSeekBar.incrementProgressBy(amount); + if (mRingtone != null && !mRingtone.isPlaying()) { + sample(); + } + postSetVolume(mSeekBar.getProgress()); + } } } diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java index a573983..e21824e 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -23,7 +23,9 @@ import android.content.res.Resources; import android.media.AudioManager; import android.media.AudioService; import android.media.AudioSystem; +import android.media.RingtoneManager; import android.media.ToneGenerator; +import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.Vibrator; @@ -44,7 +46,7 @@ import android.widget.Toast; public class VolumePanel extends Handler { private static final String TAG = "VolumePanel"; - private static boolean LOGD = false || Config.LOGD; + private static boolean LOGD = false; /** * The delay before playing a sound. This small period exists so the user @@ -86,6 +88,7 @@ public class VolumePanel extends Handler protected Context mContext; private AudioManager mAudioManager; protected AudioService mAudioService; + private boolean mRingIsSilent; private final Toast mToast; private final View mView; @@ -138,7 +141,7 @@ public class VolumePanel extends Handler onShowVolumeChanged(streamType, flags); } - if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) { + if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) { removeMessages(MSG_PLAY_SOUND); sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY); } @@ -157,6 +160,7 @@ public class VolumePanel extends Handler int index = mAudioService.getStreamVolume(streamType); int message = UNKNOWN_VOLUME_TEXT; int additionalMessage = 0; + mRingIsSilent = false; if (LOGD) { Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType @@ -169,8 +173,15 @@ public class VolumePanel extends Handler switch (streamType) { case AudioManager.STREAM_RING: { + setRingerIcon(); message = RINGTONE_VOLUME_TEXT; - setRingerIcon(index); + Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri( + mContext, RingtoneManager.TYPE_RINGTONE); + if (ringuri == null) { + additionalMessage = + com.android.internal.R.string.volume_music_hint_silent_ringtone_selected; + mRingIsSilent = true; + } break; } @@ -208,6 +219,13 @@ public class VolumePanel extends Handler case AudioManager.STREAM_NOTIFICATION: { message = NOTIFICATION_VOLUME_TEXT; setSmallIcon(index); + Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri( + mContext, RingtoneManager.TYPE_NOTIFICATION); + if (ringuri == null) { + additionalMessage = + com.android.internal.R.string.volume_music_hint_silent_ringtone_selected; + mRingIsSilent = true; + } break; } @@ -254,7 +272,6 @@ public class VolumePanel extends Handler mAudioService.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) { sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY); } - } protected void onPlaySound(int streamType, int flags) { @@ -337,17 +354,15 @@ public class VolumePanel extends Handler /** * Makes the ringer icon visible with an icon that is chosen * based on the current ringer mode. - * - * @param index */ - private void setRingerIcon(int index) { + private void setRingerIcon() { mSmallStreamIcon.setVisibility(View.GONE); mLargeStreamIcon.setVisibility(View.VISIBLE); int ringerMode = mAudioService.getRingerMode(); int icon; - if (LOGD) Log.d(TAG, "setRingerIcon(index: " + index+ "), ringerMode: " + ringerMode); + if (LOGD) Log.d(TAG, "setRingerIcon(), ringerMode: " + ringerMode); if (ringerMode == AudioManager.RINGER_MODE_SILENT) { icon = com.android.internal.R.drawable.ic_volume_off; diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 0e84839..549b668 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1709,6 +1709,8 @@ <string name="volume_music">Media volume</string> <!-- Hint shown in the volume toast to inform the user that the media audio is playing through Bluetooth. --> <string name="volume_music_hint_playing_through_bluetooth">Playing through Bluetooth</string> + <!-- Hint shown in the volume toast to inform the user that the current ringtone is the silent ringtone. --> + <string name="volume_music_hint_silent_ringtone_selected">Silent ringtone selected</string> <!-- Title of the dialog where the user is adjusting the phone call volume --> <string name="volume_call">In-call volume</string> <!-- Title of the dialog where the user is adjusting the phone call volume when connected on bluetooth--> diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 44026e4..8481410 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -605,21 +605,6 @@ public class RingtoneManager { Log.e(TAG, "Failed to open ringtone " + ringtoneUri); } - // Ringtone doesn't exist, use the fallback ringtone. - try { - AssetFileDescriptor afd = context.getResources().openRawResourceFd( - com.android.internal.R.raw.fallbackring); - if (afd != null) { - Ringtone r = new Ringtone(context); - r.open(afd); - afd.close(); - return r; - } - } catch (Exception ex) { - } - - // we should never get here - Log.e(TAG, "unable to find a usable ringtone"); return null; } @@ -638,8 +623,8 @@ public class RingtoneManager { public static Uri getActualDefaultRingtoneUri(Context context, int type) { String setting = getSettingForType(type); if (setting == null) return null; - final String uriString = Settings.System.getString(context.getContentResolver(), setting); - return uriString != null ? Uri.parse(uriString) : getValidRingtoneUri(context); + final String uriString = Settings.System.getString(context.getContentResolver(), setting); + return uriString != null ? Uri.parse(uriString) : null; } /** @@ -655,7 +640,8 @@ public class RingtoneManager { public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) { String setting = getSettingForType(type); if (setting == null) return; - Settings.System.putString(context.getContentResolver(), setting, ringtoneUri.toString()); + Settings.System.putString(context.getContentResolver(), setting, + ringtoneUri != null ? ringtoneUri.toString() : null); } private static String getSettingForType(int type) { diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 1451682..9877342 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -24,9 +24,11 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; +import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.ParcelFileDescriptor; @@ -397,12 +399,8 @@ public class SettingsProvider extends ContentProvider { // Get the current value for the default sound Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); - if (soundUri == null) { - // Fallback on any valid ringtone Uri - soundUri = RingtoneManager.getValidRingtoneUri(context); - } - if (soundUri != null) { + if (soundUri != null) { // Only proxy the openFile call to drm or media providers String authority = soundUri.getAuthority(); boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY); @@ -426,4 +424,64 @@ public class SettingsProvider extends ContentProvider { 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 DRM or 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) { + // Only proxy the openFile call to drm or media providers + String authority = soundUri.getAuthority(); + boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY); + if (isDrmAuthority || authority.equals(MediaStore.AUTHORITY)) { + + if (isDrmAuthority) { + try { + // Check DRM access permission here, since once we + // do the below call the DRM will be checking our + // permission, not our caller's permission + DrmStore.enforceAccessDrmPermission(context); + } catch (SecurityException e) { + throw new FileNotFoundException(e.getMessage()); + } + } + + 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); + } } |
