diff options
-rw-r--r-- | res/color/audio_icon.xml | 20 | ||||
-rw-r--r-- | res/drawable/ring_notif_increasing.xml | 12 | ||||
-rw-r--r-- | res/layout/preference_increasing_ring.xml | 106 | ||||
-rw-r--r-- | res/values/cm_strings.xml | 5 | ||||
-rw-r--r-- | res/xml/notification_settings.xml | 13 | ||||
-rw-r--r-- | src/com/android/settings/notification/IncreasingRingVolumePreference.java | 222 | ||||
-rw-r--r-- | src/com/android/settings/notification/NotificationSettings.java | 37 | ||||
-rw-r--r-- | src/com/android/settings/notification/VolumeSeekBarPreference.java | 1 |
8 files changed, 414 insertions, 2 deletions
diff --git a/res/color/audio_icon.xml b/res/color/audio_icon.xml new file mode 100644 index 0000000..ca93eca --- /dev/null +++ b/res/color/audio_icon.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:color="#24000000" /> + <item android:color="#8a000000" /> +</selector> diff --git a/res/drawable/ring_notif_increasing.xml b/res/drawable/ring_notif_increasing.xml new file mode 100644 index 0000000..45948c5 --- /dev/null +++ b/res/drawable/ring_notif_increasing.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="@color/audio_icon" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="#000" + android:pathData="M12,22c1.105,0,2-0.898,2-2h-4C10,21.102,10.896,22,12,22Z M18.5,16v-5.5c0-3.075-2.135-5.643-5-6.321V3.5 C13.5,2.67,12.828,2,12,2s-1.5,0.67-1.5,1.5v0.679c-2.865,0.678-5,3.246-5,6.321V16l-2,2v1h17v-1L18.5,16z M16.504,14.558H7.561 V13.25l8.943-3.808V14.558z" /> +</vector> diff --git a/res/layout/preference_increasing_ring.xml b/res/layout/preference_increasing_ring.xml new file mode 100644 index 0000000..0227076 --- /dev/null +++ b/res/layout/preference_increasing_ring.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The CyanogenMod Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeight" + android:gravity="center_vertical" + android:paddingEnd="?android:attr/scrollbarSize"> + + <ImageView + android:id="@+android:id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:src="@drawable/ring_notif_increasing" + android:minWidth="48dp" /> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dip" + android:layout_marginEnd="8dip" + android:layout_marginTop="6dip" + android:layout_marginBottom="6dip" + android:layout_weight="1"> + + <TextView android:id="@android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:ellipsize="marquee" + android:fadingEdge="horizontal" /> + + <TextView android:id="@+id/start_volume_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@android:id/title" + android:layout_alignStart="@android:id/title" + android:text="@string/increasing_ring_min_volume_title" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" + android:singleLine="true" /> + + <SeekBar android:id="@+id/start_volume" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/start_volume_label" + android:layout_alignParentEnd="true" + android:max="1000" /> + + <TextView android:id="@+id/ramp_up_time_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/start_volume" + android:layout_alignStart="@android:id/title" + android:text="@string/increasing_ring_ramp_up_time_title" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" + android:singleLine="true" /> + + <TextView android:id="@+id/ramp_up_time_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/start_volume" + android:layout_toEndOf="@id/ramp_up_time_label" + android:layout_alignBaseline="@id/ramp_up_time_label" + android:layout_alignParentEnd="true" + android:gravity="end" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" + android:singleLine="true" /> + + <SeekBar android:id="@+id/ramp_up_time" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/ramp_up_time_label" + android:layout_alignParentEnd="true" + android:max="11" /> + + <TextView android:id="@android:id/summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/ramp_up_time" + android:layout_alignStart="@android:id/title" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" + android:maxLines="4" /> + + </RelativeLayout> + +</LinearLayout> diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 1708090..aaa1ccc 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -543,4 +543,9 @@ <!-- Touchscreen hovering --> <string name="touchscreen_hovering_title">Touchscreen hovering</string> <string name="touchscreen_hovering_summary">Allows you to hover the screen like a mouse in web browsers, remote desktops, etc</string> + + <!-- Increasing ring tone volume --> + <string name="increasing_ring_volume_option_title">Increasing ring volume</string> + <string name="increasing_ring_min_volume_title">Start volume</string> + <string name="increasing_ring_ramp_up_time_title">Ramp-up time</string> </resources> diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml index 114468f..b9d2d42 100644 --- a/res/xml/notification_settings.xml +++ b/res/xml/notification_settings.xml @@ -42,6 +42,17 @@ android:icon="@*android:drawable/ic_audio_ring_notif" android:title="@string/ring_volume_option_title" /> + <!-- Increasing ring --> + <com.android.settings.cyanogenmod.SystemSettingSwitchPreference + android:key="increasing_ring" + android:title="@string/increasing_ring_volume_option_title" /> + + <!-- Increasing ring volume --> + <com.android.settings.notification.IncreasingRingVolumePreference + android:key="increasing_ring_volume" + android:icon="@drawable/ring_notif_increasing" + android:dependency="increasing_ring" /> + <!-- Notification volume --> <com.android.settings.notification.VolumeSeekBarPreference android:key="notification_volume" @@ -72,8 +83,6 @@ <!-- Default notification ringtone --> <com.android.settings.DefaultRingtonePreference android:key="notification_ringtone" - android:title="@string/notification_ringtone_title" - android:dialogTitle="@string/notification_ringtone_title" android:persistent="false" android:ringtoneType="notification" /> diff --git a/src/com/android/settings/notification/IncreasingRingVolumePreference.java b/src/com/android/settings/notification/IncreasingRingVolumePreference.java new file mode 100644 index 0000000..c08a369 --- /dev/null +++ b/src/com/android/settings/notification/IncreasingRingVolumePreference.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2014 CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification; + +import android.content.ContentResolver; +import android.content.Context; +import android.media.AudioManager; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.preference.PreferenceManager; +import android.preference.Preference; +import android.provider.Settings; +import android.text.format.Formatter; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.android.settings.R; + +public class IncreasingRingVolumePreference extends Preference implements + PreferenceManager.OnActivityStopListener, Handler.Callback, + SeekBar.OnSeekBarChangeListener { + private static final String TAG = "IncreasingRingMinVolumePreference"; + + public interface Callback { + void onStartingSample(); + } + + private SeekBar mStartVolumeSeekBar; + private SeekBar mRampUpTimeSeekBar; + private TextView mRampUpTimeValue; + + private Ringtone mRingtone; + private Callback mCallback; + + private Handler mHandler; + private final Handler mMainHandler = new Handler(this); + + private static final int MSG_START_SAMPLE = 1; + private static final int MSG_STOP_SAMPLE = 2; + private static final int MSG_INIT_SAMPLE = 3; + private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000; + + public IncreasingRingVolumePreference(Context context) { + this(context, null); + } + + public IncreasingRingVolumePreference(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public IncreasingRingVolumePreference(Context context, AttributeSet attrs, + int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public IncreasingRingVolumePreference(Context context, AttributeSet attrs, + int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setLayoutResource(R.layout.preference_increasing_ring); + initHandler(); + } + + public void setCallback(Callback callback) { + mCallback = callback; + } + + @Override + public void onActivityStop() { + postStopSample(); + mHandler.getLooper().quitSafely(); + mHandler = null; + } + + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MSG_START_SAMPLE: + onStartSample(); + break; + case MSG_STOP_SAMPLE: + onStopSample(); + break; + case MSG_INIT_SAMPLE: + onInitSample(); + break; + } + return true; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + getPreferenceManager().registerOnActivityStopListener(this); + + initHandler(); + + final SeekBar seekBar = (SeekBar) view.findViewById(R.id.start_volume); + if (seekBar == mStartVolumeSeekBar) return; + + mStartVolumeSeekBar = seekBar; + mRampUpTimeSeekBar = (SeekBar) view.findViewById(R.id.ramp_up_time); + mRampUpTimeValue = (TextView) view.findViewById(R.id.ramp_up_time_value); + + final ContentResolver cr = getContext().getContentResolver(); + float startVolume = Settings.System.getFloat(cr, + Settings.System.INCREASING_RING_START_VOLUME, 0.1f); + int rampUpTime = Settings.System.getInt(cr, + Settings.System.INCREASING_RING_RAMP_UP_TIME, 10); + + mStartVolumeSeekBar.setProgress(Math.round(startVolume * 1000F)); + mStartVolumeSeekBar.setOnSeekBarChangeListener(this); + mRampUpTimeSeekBar.setOnSeekBarChangeListener(this); + mRampUpTimeSeekBar.setProgress((rampUpTime / 5) - 1); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + if (seekBar == mStartVolumeSeekBar && mCallback != null) { + mCallback.onStartingSample(); + } + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + if (seekBar == mStartVolumeSeekBar) { + postStartSample(); + } + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { + ContentResolver cr = getContext().getContentResolver(); + if (fromTouch && seekBar == mStartVolumeSeekBar) { + Settings.System.putFloat(cr, Settings.System.INCREASING_RING_START_VOLUME, + (float) progress / 1000F); + } else if (seekBar == mRampUpTimeSeekBar) { + int seconds = (progress + 1) * 5; + mRampUpTimeValue.setText( + Formatter.formatShortElapsedTime(getContext(), seconds * 1000)); + if (fromTouch) { + Settings.System.putInt(cr, Settings.System.INCREASING_RING_RAMP_UP_TIME, seconds); + } + } + } + + private void initHandler() { + if (mHandler != null) return; + + HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); + thread.start(); + + mHandler = new Handler(thread.getLooper(), this); + mHandler.sendEmptyMessage(MSG_INIT_SAMPLE); + } + + private void onInitSample() { + mRingtone = RingtoneManager.getRingtone(getContext(), + Settings.System.DEFAULT_RINGTONE_URI); + if (mRingtone != null) { + mRingtone.setStreamType(AudioManager.STREAM_RING); + } + } + + private void postStartSample() { + mHandler.removeMessages(MSG_START_SAMPLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE), + isSamplePlaying() ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0); + } + + private void onStartSample() { + if (!isSamplePlaying() && mRingtone != null) { + try { + mRingtone.play(); + } catch (Throwable e) { + Log.w(TAG, "Error playing ringtone", e); + } + mHandler.removeMessages(MSG_STOP_SAMPLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_STOP_SAMPLE), 2000); + } + } + + private boolean isSamplePlaying() { + return mRingtone != null && mRingtone.isPlaying(); + } + + public void stopSample() { + postStopSample(); + } + + private void postStopSample() { + // remove pending delayed start messages + mHandler.removeMessages(MSG_START_SAMPLE); + mHandler.removeMessages(MSG_STOP_SAMPLE); + mHandler.sendEmptyMessage(MSG_STOP_SAMPLE); + } + + private void onStopSample() { + if (mRingtone != null) { + mRingtone.stop(); + } + } +} diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java index e0d5e8c..f513378 100644 --- a/src/com/android/settings/notification/NotificationSettings.java +++ b/src/com/android/settings/notification/NotificationSettings.java @@ -81,6 +81,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private static final String KEY_NOTIFICATION_PULSE = "notification_pulse"; private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications"; private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access"; + private static final String KEY_INCREASING_RING_VOLUME = "increasing_ring_volume"; private static final String KEY_ZEN_ACCESS = "manage_zen_access"; private static final String KEY_ZEN_MODE = "zen_mode"; @@ -96,6 +97,14 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); + private final IncreasingRingVolumePreference.Callback mIncreasingRingVolumeCallback = + new IncreasingRingVolumePreference.Callback() { + @Override + public void onStartingSample() { + mVolumeCallback.stopSample(); + } + }; + private final H mHandler = new H(); private final SettingsObserver mSettingsObserver = new SettingsObserver(); private final Receiver mReceiver = new Receiver(); @@ -108,6 +117,8 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private AudioManager mAudioManager; private VolumeSeekBarPreference mRingOrNotificationPreference; + private TwoStatePreference mIncreasingRing; + private IncreasingRingVolumePreference mIncreasingRingVolume; private Preference mPhoneRingtonePreference; private Preference mNotificationRingtonePreference; private TwoStatePreference mVibrateWhenRinging; @@ -162,6 +173,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements } initRingtones(sound); initVibrateWhenRinging(sound); + initIncreasingRing(sound); final PreferenceCategory notification = (PreferenceCategory) findPreference(KEY_NOTIFICATION); @@ -277,6 +289,9 @@ public class NotificationSettings extends SettingsPreferenceFragment implements if (mCurrent != null && mCurrent != sbv) { mCurrent.stopSample(); } + if (mIncreasingRingVolume != null) { + mIncreasingRingVolume.stopSample(); + } mCurrent = sbv; if (mCurrent != null) { mHandler.removeMessages(H.STOP_SAMPLE); @@ -371,6 +386,28 @@ public class NotificationSettings extends SettingsPreferenceFragment implements return summary; } + // === Increasing ringtone === + + private void initIncreasingRing(PreferenceCategory root) { + mIncreasingRing = (TwoStatePreference) + root.findPreference(Settings.System.INCREASING_RING); + mIncreasingRingVolume = (IncreasingRingVolumePreference) + root.findPreference(KEY_INCREASING_RING_VOLUME); + + if (mIncreasingRing == null || mIncreasingRingVolume == null || !mVoiceCapable) { + if (mIncreasingRing != null) { + root.removePreference(mIncreasingRing); + mIncreasingRing = null; + } + if (mIncreasingRingVolume != null) { + root.removePreference(mIncreasingRingVolume); + mIncreasingRingVolume = null; + } + } else { + mIncreasingRingVolume.setCallback(mIncreasingRingVolumeCallback); + } + } + // === Vibrate when ringing === private void initVibrateWhenRinging(PreferenceCategory root) { diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java index 2603016..cb2fa90 100644 --- a/src/com/android/settings/notification/VolumeSeekBarPreference.java +++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java @@ -90,6 +90,7 @@ public class VolumeSeekBarPreference extends SeekBarPreference mStopped = true; if (mVolumizer != null) { mVolumizer.stop(); + mVolumizer = null; } } |