summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilhelm Fitzpatrick <rafial@cyngn.com>2015-12-15 13:45:06 -0800
committerGerrit Code Review <gerrit@cyanogenmod.org>2015-12-16 17:00:38 -0800
commitaba22b8d30283c159ffcb2e06d894a7bc89d9559 (patch)
treeef6297ba3aece3510ff71190dd5fbe6490dacd5d
parent421038c8924178f951fdcdbfadaa9c778868a3d1 (diff)
downloadandroid_packages_apps_DeskClock-aba22b8d30283c159ffcb2e06d894a7bc89d9559.tar.gz
android_packages_apps_DeskClock-aba22b8d30283c159ffcb2e06d894a7bc89d9559.tar.bz2
android_packages_apps_DeskClock-aba22b8d30283c159ffcb2e06d894a7bc89d9559.zip
DeskClock: add increasing volume option for alarm clocks
Based on CM12 feature: https://github.com/CyanogenMod/android_packages_apps_DeskClock/commit/7fc93e1b93b0e9e56a8426a6201a26c2bfca90ba http://review.cyanogenmod.org/#/c/82967/ Change-Id: I090c76bd773e419f10e1e02bcf3c40ad04d6a988
-rw-r--r--res/layout/alarm_time.xml29
-rw-r--r--res/values/cm_strings.xml3
-rw-r--r--src/com/android/deskclock/AlarmClockFragment.java13
-rw-r--r--src/com/android/deskclock/AsyncRingtonePlayer.java122
-rw-r--r--src/com/android/deskclock/alarms/AlarmKlaxon.java2
5 files changed, 139 insertions, 30 deletions
diff --git a/res/layout/alarm_time.xml b/res/layout/alarm_time.xml
index fb2fe9a11..fee4ccb98 100644
--- a/res/layout/alarm_time.xml
+++ b/res/layout/alarm_time.xml
@@ -74,7 +74,7 @@
<CheckBox
android:id="@+id/repeat_onoff"
android:layout_width="wrap_content"
- android:layout_height="48dip"
+ android:layout_height="@dimen/touch_target_min_size"
android:layout_gravity="center_vertical|start"
android:text="@string/alarm_repeat"
android:textSize="16sp"
@@ -84,7 +84,7 @@
<LinearLayout
android:id="@+id/repeat_days"
android:layout_width="match_parent"
- android:layout_height="48dip"
+ android:layout_height="@dimen/touch_target_min_size"
android:layout_gravity="top"
android:orientation="horizontal"
android:visibility="gone">
@@ -95,18 +95,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
- android:orientation="horizontal" >
+ android:orientation="vertical" >
<TextView
android:id="@+id/choose_ringtone"
- android:layout_width="0dip"
- android:layout_height="48dip"
- android:layout_weight="1"
- android:layout_alignParentStart="true"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/touch_target_min_size"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:paddingStart="4dip"
- android:drawablePadding="16dp"
+ android:drawablePadding="20dp"
android:drawableStart="@drawable/ic_ringtone"
android:ellipsize="marquee"
android:gravity="center_vertical"
@@ -119,11 +117,20 @@
/>
<CheckBox
+ android:id="@+id/increasing_volume_onoff"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/touch_target_min_size"
+ android:includeFontPadding="false"
+ android:text="@string/alarm_increasing_volume"
+ android:paddingStart="16dip"
+ android:textSize="16sp"
+ android:textColor="@color/white"
+ style="@style/body" />
+
+ <CheckBox
android:id="@+id/vibrate_onoff"
android:layout_width="wrap_content"
- android:layout_height="48dip"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
+ android:layout_height="@dimen/touch_target_min_size"
android:includeFontPadding="false"
android:text="@string/alarm_vibrate"
android:paddingStart="16dip"
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index c5fba1c65..067fedd6e 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -20,4 +20,7 @@
<!-- Setting summary for showing/hiding the alarm statusbar icon -->
<string name="show_status_bar_icon_summary">Show an icon in the status bar when an alarm is set</string>
+
+ <!-- Setting labels on Set alarm screen: Increasing volume on or off -->
+ <string name="alarm_increasing_volume">Increasing volume</string>
</resources>
diff --git a/src/com/android/deskclock/AlarmClockFragment.java b/src/com/android/deskclock/AlarmClockFragment.java
index 9cee1af06..14906d870 100644
--- a/src/com/android/deskclock/AlarmClockFragment.java
+++ b/src/com/android/deskclock/AlarmClockFragment.java
@@ -573,6 +573,7 @@ public abstract class AlarmClockFragment extends DeskClockFragment implements
LinearLayout repeatDays;
CompoundButton[] dayButtons = new CompoundButton[7];
CheckBox vibrate;
+ CheckBox increasingVolume;
TextView ringtone;
View hairLine;
View arrow;
@@ -713,6 +714,7 @@ public abstract class AlarmClockFragment extends DeskClockFragment implements
holder.dayButtons[i] = dayButton;
}
holder.vibrate = (CheckBox) view.findViewById(R.id.vibrate_onoff);
+ holder.increasingVolume = (CheckBox) view.findViewById(R.id.increasing_volume_onoff);
holder.ringtone = (TextView) view.findViewById(R.id.choose_ringtone);
view.setTag(holder);
@@ -1052,6 +1054,17 @@ public abstract class AlarmClockFragment extends DeskClockFragment implements
launchRingTonePicker(alarm);
}
});
+
+ itemHolder.increasingVolume.setVisibility(View.VISIBLE);
+ itemHolder.increasingVolume.setChecked(alarm.increasingVolume);
+ itemHolder.increasingVolume.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final boolean checked = ((CheckBox) v).isChecked();
+ alarm.increasingVolume = checked;
+ asyncUpdateAlarm(alarm, false);
+ }
+ });
}
// Sets the alpha of the digital time display. This gives a visual effect
diff --git a/src/com/android/deskclock/AsyncRingtonePlayer.java b/src/com/android/deskclock/AsyncRingtonePlayer.java
index 4416aab79..af98e892e 100644
--- a/src/com/android/deskclock/AsyncRingtonePlayer.java
+++ b/src/com/android/deskclock/AsyncRingtonePlayer.java
@@ -46,9 +46,15 @@ public class AsyncRingtonePlayer {
// Volume suggested by media team for in-call alarms.
private static final float IN_CALL_VOLUME = 0.125f;
+ // Constants for increasing volume alarms
+ private static final long INCREASING_VOLUME_DELAY = 4000;
+ private static final float INCREASING_VOLUME_START = 0.05f;
+ private static final float INCREASING_VOLUME_DELTA = 0.05f;
+
// Message codes used with the ringtone thread.
private static final int EVENT_PLAY = 1;
private static final int EVENT_STOP = 2;
+ private static final int EVENT_INCREASE_VOLUME = 3;
private static final String RINGTONE_URI_KEY = "RINGTONE_URI_KEY";
/** Handler running on the ringtone thread. */
@@ -65,15 +71,15 @@ public class AsyncRingtonePlayer {
}
/** Plays the ringtone. */
- public void play(Uri ringtoneUri) {
+ public void play(Uri ringtoneUri, boolean increasingVolume) {
LogUtils.d(TAG, "Posting play.");
- postMessage(EVENT_PLAY, ringtoneUri);
+ postMessage(EVENT_PLAY, ringtoneUri, increasingVolume);
}
/** Stops playing the ringtone. */
public void stop() {
LogUtils.d(TAG, "Posting stop.");
- postMessage(EVENT_STOP, null);
+ postMessage(EVENT_STOP, null, false);
}
/**
@@ -81,7 +87,7 @@ public class AsyncRingtonePlayer {
*
* @param messageCode The message to post.
*/
- private void postMessage(int messageCode, Uri ringtoneUri) {
+ private void postMessage(int messageCode, Uri ringtoneUri, boolean increasingVolume) {
synchronized (this) {
if (mHandler == null) {
mHandler = getNewHandler();
@@ -93,10 +99,17 @@ public class AsyncRingtonePlayer {
bundle.putParcelable(RINGTONE_URI_KEY, ringtoneUri);
message.setData(bundle);
}
+ message.arg1 = increasingVolume ? 1 : 0;
message.sendToTarget();
}
}
+ private void delayedMessage(int messageCode, long delay) {
+ synchronized (this) {
+ mHandler.sendEmptyMessageDelayed(messageCode, delay);
+ }
+ }
+
/**
* Creates a new ringtone Handler running in its own thread.
*/
@@ -110,18 +123,29 @@ public class AsyncRingtonePlayer {
switch (msg.what) {
case EVENT_PLAY:
final Uri ringtoneUri = msg.getData().getParcelable(RINGTONE_URI_KEY);
- getPlaybackDelegate().play(mContext, ringtoneUri);
+ final boolean increasingVolume = msg.arg1 == 1;
+ getPlaybackDelegate().play(mContext, ringtoneUri, increasingVolume);
+ if (increasingVolume) {
+ delayedMessage(EVENT_INCREASE_VOLUME, INCREASING_VOLUME_DELAY);
+ }
break;
case EVENT_STOP:
+ removeMessages(EVENT_INCREASE_VOLUME);
getPlaybackDelegate().stop(mContext);
break;
+ case EVENT_INCREASE_VOLUME:
+ PlaybackDelegate pd = getPlaybackDelegate();
+ if (pd.isPlaying() && pd.increaseVolume()) {
+ delayedMessage(EVENT_INCREASE_VOLUME, INCREASING_VOLUME_DELAY);
+ }
+ break;
}
}
};
}
/**
- * @return <code>true</code> iff the device is currently in a telephone call
+ * @return <code>true</code> if the device is currently in a telephone call
*/
private static boolean isInTelephoneCall(Context context) {
final TelephonyManager tm = (TelephonyManager)
@@ -169,8 +193,10 @@ public class AsyncRingtonePlayer {
* vs {@link MediaPlayer}.
*/
private interface PlaybackDelegate {
- void play(Context context, Uri ringtoneUri);
+ void play(Context context, Uri ringtoneUri, boolean increasingVolume);
void stop(Context context);
+ boolean isPlaying();
+ boolean increaseVolume();
}
/**
@@ -184,11 +210,14 @@ public class AsyncRingtonePlayer {
/** Non-{@code null} while playing a ringtone; {@code null} otherwise. */
private MediaPlayer mMediaPlayer;
+ private float mMaxVolume;
+ private float mCurrentVolume;
+
/**
* Starts the actual playback of the ringtone. Executes on ringtone-thread.
*/
@Override
- public void play(final Context context, Uri ringtoneUri) {
+ public void play(final Context context, Uri ringtoneUri, boolean increasingVolume) {
if (Looper.getMainLooper() == Looper.myLooper()) {
LogUtils.e(TAG, "Must not be on the main thread!", new IllegalStateException());
}
@@ -217,11 +246,12 @@ public class AsyncRingtonePlayer {
});
try {
+ mMaxVolume = 1f;
// Check if we are in a call. If we are, use the in-call alarm resource at a
// low volume to not disrupt the call.
if (isInTelephoneCall(context)) {
LogUtils.v("Using the in-call alarm");
- mMediaPlayer.setVolume(IN_CALL_VOLUME, IN_CALL_VOLUME);
+ mMaxVolume = IN_CALL_VOLUME;
alarmNoise = getInCallRingtoneUri(context);
}
@@ -230,7 +260,7 @@ public class AsyncRingtonePlayer {
// installation time. M+, this permission can be revoked by the user any time.
mMediaPlayer.setDataSource(context, alarmNoise);
- startAlarm(mMediaPlayer);
+ startAlarm(mMediaPlayer, increasingVolume);
} catch (Throwable t) {
LogUtils.e("Use the fallback ringtone, original was " + alarmNoise, t);
// The alarmNoise may be on the sd card which could be busy right now.
@@ -239,7 +269,7 @@ public class AsyncRingtonePlayer {
// Must reset the media player to clear the error state.
mMediaPlayer.reset();
mMediaPlayer.setDataSource(context, getFallbackRingtoneUri(context));
- startAlarm(mMediaPlayer);
+ startAlarm(mMediaPlayer, increasingVolume);
} catch (Throwable t2) {
// At this point we just don't play anything.
LogUtils.e("Failed to play fallback ringtone", t2);
@@ -250,7 +280,7 @@ public class AsyncRingtonePlayer {
/**
* Do the common stuff when starting the alarm.
*/
- private void startAlarm(MediaPlayer player) throws IOException {
+ private void startAlarm(MediaPlayer player, boolean increasingVolume) throws IOException {
// do not play alarms if stream volume is 0 (typically because ringer mode is silent).
if (mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
if (Utils.isLOrLater()) {
@@ -260,6 +290,8 @@ public class AsyncRingtonePlayer {
.build());
}
+ mCurrentVolume = increasingVolume ? INCREASING_VOLUME_START : mMaxVolume;
+ player.setVolume(mCurrentVolume, mCurrentVolume);
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.setLooping(true);
player.prepare();
@@ -288,6 +320,27 @@ public class AsyncRingtonePlayer {
mMediaPlayer = null;
}
}
+
+ @Override
+ public boolean isPlaying() {
+ return mMediaPlayer != null && mMediaPlayer.isPlaying();
+ }
+
+ /**
+ * @return <code>true</code> if volume should continue to be increased
+ */
+ @Override
+ public boolean increaseVolume() {
+ if (mMediaPlayer != null) {
+ mCurrentVolume += INCREASING_VOLUME_DELTA;
+ if (mCurrentVolume > mMaxVolume) {
+ mCurrentVolume = mMaxVolume;
+ }
+ mMediaPlayer.setVolume(mCurrentVolume, mCurrentVolume);
+ return mCurrentVolume < mMaxVolume;
+ }
+ return false;
+ }
}
/**
@@ -307,6 +360,9 @@ public class AsyncRingtonePlayer {
/** The method to adjust playback looping; cannot be null. */
private Method mSetLoopingMethod;
+ private float mMaxVolume;
+ private float mCurrentVolume;
+
private RingtonePlaybackDelegate() {
try {
mSetVolumeMethod = Ringtone.class.getDeclaredMethod("setVolume", float.class);
@@ -325,7 +381,7 @@ public class AsyncRingtonePlayer {
* Starts the actual playback of the ringtone. Executes on ringtone-thread.
*/
@Override
- public void play(Context context, Uri ringtoneUri) {
+ public void play(Context context, Uri ringtoneUri, boolean increasingVolume) {
if (Looper.getMainLooper() == Looper.myLooper()) {
LogUtils.e(TAG, "Must not be on the main thread!", new IllegalStateException());
}
@@ -374,21 +430,29 @@ public class AsyncRingtonePlayer {
.build());
}
+ mMaxVolume = 1f;
// Attempt to adjust the ringtone volume if the user is in a telephone call.
if (inTelephoneCall) {
LogUtils.v("Using the in-call alarm");
- try {
- mSetVolumeMethod.invoke(mRingtone, IN_CALL_VOLUME);
- } catch (Exception e) {
- LogUtils.e(TAG, "Unable to set in-call volume for android.media.Ringtone", e);
- }
+ mMaxVolume = IN_CALL_VOLUME;
}
+ mCurrentVolume = increasingVolume ? INCREASING_VOLUME_START : mMaxVolume;
+
mAudioManager.requestAudioFocus(null, AudioManager.STREAM_ALARM,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ setVolume(mCurrentVolume);
mRingtone.play();
}
+ private void setVolume(float volume) {
+ try {
+ mSetVolumeMethod.invoke(mRingtone, volume);
+ } catch (Exception e) {
+ LogUtils.e(TAG, "Unable to set in-call volume for android.media.Ringtone", e);
+ }
+ }
+
/**
* Stops the playback of the ringtone. Executes on the ringtone-thread.
*/
@@ -403,12 +467,34 @@ public class AsyncRingtonePlayer {
if (mRingtone != null && mRingtone.isPlaying()) {
LogUtils.d(TAG, "Ringtone.stop() invoked.");
mRingtone.stop();
+ mRingtone = null;
}
if (mAudioManager != null) {
mAudioManager.abandonAudioFocus(null);
}
}
+
+ @Override
+ public boolean isPlaying() {
+ return mRingtone != null && mRingtone.isPlaying();
+ }
+
+ /**
+ * @return <code>true</code> if volume should continue to be increased
+ */
+ @Override
+ public boolean increaseVolume() {
+ if (mRingtone != null && mSetVolumeMethod != null) {
+ mCurrentVolume += INCREASING_VOLUME_DELTA;
+ if (mCurrentVolume > mMaxVolume) {
+ mCurrentVolume = mMaxVolume;
+ }
+ setVolume(mCurrentVolume);
+ return mCurrentVolume < mMaxVolume;
+ }
+ return false;
+ }
}
}
diff --git a/src/com/android/deskclock/alarms/AlarmKlaxon.java b/src/com/android/deskclock/alarms/AlarmKlaxon.java
index c286f459b..8b31cfb72 100644
--- a/src/com/android/deskclock/alarms/AlarmKlaxon.java
+++ b/src/com/android/deskclock/alarms/AlarmKlaxon.java
@@ -52,7 +52,7 @@ public final class AlarmKlaxon {
stop(context);
if (!AlarmInstance.NO_RINGTONE_URI.equals(instance.mRingtone)) {
- getAsyncRingtonePlayer(context).play(instance.mRingtone);
+ getAsyncRingtonePlayer(context).play(instance.mRingtone, instance.mIncreasingVolume);
}
if (instance.mVibrate) {