summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilhelm Fitzpatrick <rafial@cyngn.com>2015-12-23 15:58:25 -0800
committerGerrit Code Review <gerrit@cyanogenmod.org>2016-01-02 02:05:45 -0800
commit91ac9cbe7c721b8d261f798ba9a78a1e5a458cdd (patch)
treee4943bba99b6c7ad3069987314ad433c872ca03b
parent811f84370c21cc3dfeb6785a86b8cd6c3581aaa3 (diff)
downloadandroid_packages_apps_DeskClock-91ac9cbe7c721b8d261f798ba9a78a1e5a458cdd.tar.gz
android_packages_apps_DeskClock-91ac9cbe7c721b8d261f798ba9a78a1e5a458cdd.tar.bz2
android_packages_apps_DeskClock-91ac9cbe7c721b8d261f798ba9a78a1e5a458cdd.zip
DeskClock: Add back flip and shake actions
Allow the alarm to be dismissed/snoozed by flipping or shaking Picked from: http://review.cyanogenmod.org/#/c/29894 http://review.cyanogenmod.org/#/c/80342 http://review.cyanogenmod.org/#/c/81204 http://review.cyanogenmod.org/#/c/94950 Authors/Contributors: Artem Chep <artemchep@gmail.com> Danny Baumann <dannybaumann@web.de> Ronald Ramsay II <ronaldramsayii@gmail.com> Danesh M <daneshm90@gmail.com> Michael Bestas <mikeioannina@gmail.com> Martin Brabham <mbrabham@cyngn.com> Change-Id: I222b6cd53a95db6f8662e7aef52aa6922d8a5d6a
-rw-r--r--res/values/cm_arrays.xml25
-rw-r--r--res/values/cm_strings.xml22
-rw-r--r--res/xml/settings.xml27
-rw-r--r--src/com/android/deskclock/SettingsActivity.java61
-rwxr-xr-xsrc/com/android/deskclock/alarms/AlarmService.java174
5 files changed, 298 insertions, 11 deletions
diff --git a/res/values/cm_arrays.xml b/res/values/cm_arrays.xml
new file mode 100644
index 000000000..e0e92a42f
--- /dev/null
+++ b/res/values/cm_arrays.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012-2015 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.
+-->
+<resources>
+ <!-- Summary texts for shake and flip actions. Must be ordered by numerical
+ value (do nothing = 0, snooze = 1, dismiss = 2) -->
+ <string-array name="action_summary_entries" translatable="false">
+ <item>@string/action_summary_snooze</item>
+ <item>@string/action_summary_dismiss</item>
+ <item>@string/action_summary_do_nothing</item>
+ </string-array>
+</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index aa597101c..a8eaeccba 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -15,6 +15,28 @@
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Settings summary for the volume buttons setting. -->
+ <string name="volume_buttons_summary">Pressing the volume buttons will <xliff:g id="action">%s</xliff:g></string>
+
+ <!-- Setting title for the flip action setting. -->
+ <string name="flip_action_title">Flip action</string>
+
+ <!-- Setting summary for the flip action setting. -->
+ <string name="flip_action_summary" product="tablet">Flipping the tablet down will <xliff:g id="action">%s</xliff:g></string>
+ <string name="flip_action_summary" product="default">Flipping the phone down will <xliff:g id="action">%s</xliff:g></string>
+
+ <!-- Setting title for the shake action setting. -->
+ <string name="shake_action_title">Shake action</string>
+
+ <!-- Setting summary for the shake action setting. -->
+ <string name="shake_action_summary" product="tablet">Shaking the tablet will <xliff:g id="action">%s</xliff:g></string>
+ <string name="shake_action_summary" product="default">Shaking the phone will <xliff:g id="action">%s</xliff:g></string>
+
+ <!-- Summary texts for shake and flip actions -->
+ <string name="action_summary_snooze">snooze the alarm</string>
+ <string name="action_summary_dismiss">dismiss the alarm</string>
+ <string name="action_summary_do_nothing">do nothing</string>
+
<!-- Setting title for accessing the cLock widget settings -->
<string name="menu_item_widget_settings">Widget settings</string>
<string name="activity_not_found">Activity not found!</string>
diff --git a/res/xml/settings.xml b/res/xml/settings.xml
index 77a355a4d..052d4ba77 100644
--- a/res/xml/settings.xml
+++ b/res/xml/settings.xml
@@ -38,6 +38,7 @@
</PreferenceCategory>
<PreferenceCategory
+ android:key="key_alarm_settings"
android:title="@string/alarm_settings">
<ListPreference
android:key="auto_silence"
@@ -57,6 +58,13 @@
android:title="@string/alarm_volume_title" />
<ListPreference
+ android:key="week_start"
+ android:title="@string/week_start_title"
+ android:dialogTitle="@string/week_start_title"
+ android:entries="@array/week_start_entries"
+ android:entryValues="@array/week_start_values" />
+
+ <ListPreference
android:key="volume_button_setting"
android:title="@string/volume_button_setting_title"
android:dialogTitle="@string/volume_button_setting_title"
@@ -65,11 +73,20 @@
android:defaultValue="0" />
<ListPreference
- android:key="week_start"
- android:title="@string/week_start_title"
- android:dialogTitle="@string/week_start_title"
- android:entries="@array/week_start_entries"
- android:entryValues="@array/week_start_values" />
+ android:key="flip_action"
+ android:title="@string/flip_action_title"
+ android:dialogTitle="@string/flip_action_title"
+ android:entries="@array/volume_button_setting_entries"
+ android:entryValues="@array/volume_button_setting_values"
+ android:defaultValue="0" />
+
+ <ListPreference
+ android:key="shake_action"
+ android:title="@string/shake_action_title"
+ android:dialogTitle="@string/shake_action_title"
+ android:entries="@array/volume_button_setting_entries"
+ android:entryValues="@array/volume_button_setting_values"
+ android:defaultValue="0" />
<SwitchPreference
android:key="show_status_bar_icon"
diff --git a/src/com/android/deskclock/SettingsActivity.java b/src/com/android/deskclock/SettingsActivity.java
index 3a4a36175..e376a0f2f 100644
--- a/src/com/android/deskclock/SettingsActivity.java
+++ b/src/com/android/deskclock/SettingsActivity.java
@@ -21,10 +21,13 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
+import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.SwitchPreference;
import android.text.format.DateUtils;
@@ -48,6 +51,8 @@ public class SettingsActivity extends BaseActivity {
public static final String KEY_ALARM_SNOOZE = "snooze_duration";
public static final String KEY_ALARM_VOLUME = "volume_setting";
public static final String KEY_VOLUME_BEHAVIOR = "volume_button_setting";
+ public static final String KEY_FLIP_ACTION = "flip_action";
+ public static final String KEY_SHAKE_ACTION = "shake_action";
public static final String KEY_AUTO_SILENCE = "auto_silence";
public static final String KEY_CLOCK_STYLE = "clock_style";
public static final String KEY_HOME_TZ = "home_time_zone";
@@ -55,6 +60,7 @@ public class SettingsActivity extends BaseActivity {
public static final String KEY_VOLUME_BUTTONS = "volume_button_setting";
public static final String KEY_WEEK_START = "week_start";
public static final String KEY_SHOW_ALARM_ICON = "show_status_bar_icon";
+ public static final String KEY_ALARM_SETTINGS = "key_alarm_settings";
public static final String DEFAULT_VOLUME_BEHAVIOR = "0";
public static final String VOLUME_BEHAVIOR_SNOOZE = "1";
@@ -148,9 +154,14 @@ public class SettingsActivity extends BaseActivity {
homeTimeZonePref.setEnabled(!autoHomeClockEnabled);
notifyHomeTimeZoneChanged();
} else if (KEY_VOLUME_BUTTONS.equals(pref.getKey())) {
- final ListPreference volumeButtonsPref = (ListPreference) pref;
- final int index = volumeButtonsPref.findIndexOfValue((String) newValue);
- volumeButtonsPref.setSummary(volumeButtonsPref.getEntries()[index]);
+ final ListPreference listPref = (ListPreference) pref;
+ updateActionSummary(listPref, (String) newValue, R.string.volume_buttons_summary);
+ } else if (KEY_FLIP_ACTION.equals(pref.getKey())) {
+ final ListPreference listPref = (ListPreference) pref;
+ updateActionSummary(listPref, (String) newValue, R.string.flip_action_summary);
+ } else if (KEY_SHAKE_ACTION.equals(pref.getKey())) {
+ final ListPreference listPref = (ListPreference) pref;
+ updateActionSummary(listPref, (String) newValue, R.string.shake_action_summary);
} else if (KEY_WEEK_START.equals(pref.getKey())) {
final ListPreference weekStartPref = (ListPreference) findPreference(KEY_WEEK_START);
final int idx = weekStartPref.findIndexOfValue((String) newValue);
@@ -234,11 +245,43 @@ public class SettingsActivity extends BaseActivity {
homeTimezonePref.setSummary(homeTimezonePref.getEntry());
homeTimezonePref.setOnPreferenceChangeListener(this);
- final ListPreference volumeButtonsPref =
- (ListPreference) findPreference(KEY_VOLUME_BUTTONS);
- volumeButtonsPref.setSummary(volumeButtonsPref.getEntry());
+ final ListPreference volumeButtonsPref = (ListPreference) findPreference(KEY_VOLUME_BUTTONS);
+ updateActionSummary(volumeButtonsPref, volumeButtonsPref.getValue(), R.string.volume_buttons_summary);
volumeButtonsPref.setOnPreferenceChangeListener(this);
+ SensorManager sensorManager = (SensorManager)
+ getActivity().getSystemService(Context.SENSOR_SERVICE);
+
+ final ListPreference flipActionPref = (ListPreference) findPreference(KEY_FLIP_ACTION);
+ if (flipActionPref != null) {
+ List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
+ if (sensorList.size() < 1) { // This will be true if no orientation sensor
+ flipActionPref.setValue("0"); // Turn it off
+ PreferenceCategory category = (PreferenceCategory) findPreference(KEY_ALARM_SETTINGS);
+ if (category != null) {
+ category.removePreference(flipActionPref);
+ }
+ } else {
+ updateActionSummary(flipActionPref, flipActionPref.getValue(), R.string.flip_action_summary);
+ flipActionPref.setOnPreferenceChangeListener(this);
+ }
+ }
+
+ final ListPreference shakeActionPref = (ListPreference) findPreference(KEY_SHAKE_ACTION);
+ if (shakeActionPref != null) {
+ List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
+ if (sensorList.size() < 1) { // This will be true if no accelerometer sensor
+ shakeActionPref.setValue("0"); // Turn it off
+ PreferenceCategory category = (PreferenceCategory) findPreference(KEY_ALARM_SETTINGS);
+ if (category != null) {
+ category.removePreference(shakeActionPref);
+ }
+ } else {
+ updateActionSummary(shakeActionPref, shakeActionPref.getValue(), R.string.shake_action_summary);
+ shakeActionPref.setOnPreferenceChangeListener(this);
+ }
+ }
+
final Preference volumePref = findPreference(KEY_ALARM_VOLUME);
volumePref.setOnPreferenceClickListener(this);
@@ -275,6 +318,12 @@ public class SettingsActivity extends BaseActivity {
getActivity().sendBroadcast(i);
}
+ private void updateActionSummary(ListPreference listPref, String action, int summaryResId) {
+ int i = listPref.findIndexOfValue(action);
+ listPref.setSummary(getString(summaryResId,
+ getResources().getStringArray(R.array.action_summary_entries)[i]));
+ }
+
private class TimeZoneRow implements Comparable<TimeZoneRow> {
private static final boolean SHOW_DAYLIGHT_SAVINGS_INDICATOR = false;
diff --git a/src/com/android/deskclock/alarms/AlarmService.java b/src/com/android/deskclock/alarms/AlarmService.java
index 50a1d8113..d972b450d 100755
--- a/src/com/android/deskclock/alarms/AlarmService.java
+++ b/src/com/android/deskclock/alarms/AlarmService.java
@@ -15,6 +15,7 @@
*/
package com.android.deskclock.alarms;
+import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -23,11 +24,18 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.IBinder;
+import android.content.SharedPreferences;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import com.android.deskclock.AlarmAlertWakeLock;
import com.android.deskclock.LogUtils;
+import com.android.deskclock.SettingsActivity;
import com.android.deskclock.R;
import com.android.deskclock.events.Events;
import com.android.deskclock.provider.AlarmInstance;
@@ -68,6 +76,14 @@ public class AlarmService extends Service {
/** Private action used to stop an alarm with this service. */
public static final String STOP_ALARM_ACTION = "STOP_ALARM";
+ // constants for no action/snooze/dismiss
+ private static final int ALARM_NO_ACTION = 0;
+ private static final int ALARM_SNOOZE = 1;
+ private static final int ALARM_DISMISS = 2;
+
+ // default action for flip and shake
+ private static final String DEFAULT_ACTION = Integer.toString(ALARM_NO_ACTION);
+
/** Binder given to AlarmActivity */
private final IBinder mBinder = new Binder();
@@ -123,6 +139,9 @@ public class AlarmService extends Service {
private TelephonyManager mTelephonyManager;
private int mInitialCallState;
private AlarmInstance mCurrentAlarm = null;
+ private SensorManager mSensorManager;
+ private int mFlipAction;
+ private int mShakeAction;
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
@@ -192,6 +211,7 @@ public class AlarmService extends Service {
AlarmKlaxon.start(this, mCurrentAlarm);
changeToProfile(this, mCurrentAlarm);
sendBroadcast(new Intent(ALARM_ALERT_ACTION));
+ attachListeners();
}
private void stopCurrentAlarm() {
@@ -206,6 +226,7 @@ public class AlarmService extends Service {
sendBroadcast(new Intent(ALARM_DONE_ACTION));
mCurrentAlarm = null;
+ detachListeners();
AlarmAlertWakeLock.releaseCpuLock();
}
@@ -251,6 +272,14 @@ public class AlarmService extends Service {
filter.addAction(ALARM_DISMISS_ACTION);
registerReceiver(mActionsReceiver, filter);
mIsRegistered = true;
+
+ // set up for flip and shake actions
+ mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ mFlipAction = Integer.parseInt(prefs.getString(
+ SettingsActivity.KEY_FLIP_ACTION, DEFAULT_ACTION));
+ mShakeAction = Integer.parseInt(prefs.getString(
+ SettingsActivity.KEY_SHAKE_ACTION, DEFAULT_ACTION));
}
@Override
@@ -303,4 +332,149 @@ public class AlarmService extends Service {
mIsRegistered = false;
}
}
+
+ private final SensorEventListener mFlipListener = new SensorEventListener() {
+ private static final int FACE_UP_LOWER_LIMIT = -45;
+ private static final int FACE_UP_UPPER_LIMIT = 45;
+ private static final int FACE_DOWN_UPPER_LIMIT = 135;
+ private static final int FACE_DOWN_LOWER_LIMIT = -135;
+ private static final int TILT_UPPER_LIMIT = 45;
+ private static final int TILT_LOWER_LIMIT = -45;
+ private static final int SENSOR_SAMPLES = 3;
+
+ private boolean mWasFaceUp;
+ private boolean[] mSamples = new boolean[SENSOR_SAMPLES];
+ private int mSampleIndex;
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int acc) {
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ // Add a sample overwriting the oldest one. Several samples
+ // are used
+ // to avoid the erroneous values the sensor sometimes
+ // returns.
+ float y = event.values[1];
+ float z = event.values[2];
+
+ if (!mWasFaceUp) {
+ // Check if its face up enough.
+ mSamples[mSampleIndex] = y > FACE_UP_LOWER_LIMIT
+ && y < FACE_UP_UPPER_LIMIT
+ && z > TILT_LOWER_LIMIT && z < TILT_UPPER_LIMIT;
+
+ // The device first needs to be face up.
+ boolean faceUp = true;
+ for (boolean sample : mSamples) {
+ faceUp = faceUp && sample;
+ }
+ if (faceUp) {
+ mWasFaceUp = true;
+ for (int i = 0; i < SENSOR_SAMPLES; i++) {
+ mSamples[i] = false;
+ }
+ }
+ } else {
+ // Check if its face down enough. Note that wanted
+ // values go from FACE_DOWN_UPPER_LIMIT to 180
+ // and from -180 to FACE_DOWN_LOWER_LIMIT
+ mSamples[mSampleIndex] = (y > FACE_DOWN_UPPER_LIMIT || y < FACE_DOWN_LOWER_LIMIT)
+ && z > TILT_LOWER_LIMIT
+ && z < TILT_UPPER_LIMIT;
+
+ boolean faceDown = true;
+ for (boolean sample : mSamples) {
+ faceDown = faceDown && sample;
+ }
+ if (faceDown) {
+ handleAction(mFlipAction);
+ }
+ }
+
+ mSampleIndex = ((mSampleIndex + 1) % SENSOR_SAMPLES);
+ }
+ };
+
+ private final SensorEventListener mShakeListener = new SensorEventListener() {
+ private static final float SENSITIVITY = 16;
+ private static final int BUFFER = 5;
+ private float[] gravity = new float[3];
+ private float average = 0;
+ private int fill = 0;
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int acc) {
+ }
+
+ public void onSensorChanged(SensorEvent event) {
+ final float alpha = 0.8F;
+
+ for (int i = 0; i < 3; i++) {
+ gravity[i] = alpha * gravity[i] + (1 - alpha) * event.values[i];
+ }
+
+ float x = event.values[0] - gravity[0];
+ float y = event.values[1] - gravity[1];
+ float z = event.values[2] - gravity[2];
+
+ if (fill <= BUFFER) {
+ average += Math.abs(x) + Math.abs(y) + Math.abs(z);
+ fill++;
+ } else {
+ if (average / BUFFER >= SENSITIVITY) {
+ handleAction(mShakeAction);
+ }
+ average = 0;
+ fill = 0;
+ }
+ }
+ };
+
+ private void attachListeners() {
+ if (mFlipAction != ALARM_NO_ACTION) {
+ mSensorManager.registerListener(mFlipListener,
+ mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
+ SensorManager.SENSOR_DELAY_NORMAL,
+ 300 * 1000); //batch every 300 milliseconds
+ }
+
+ if (mShakeAction != ALARM_NO_ACTION) {
+ mSensorManager.registerListener(mShakeListener,
+ mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ SensorManager.SENSOR_DELAY_GAME,
+ 50 * 1000); //batch every 50 milliseconds
+ }
+ }
+
+ private void detachListeners() {
+ if (mFlipAction != ALARM_NO_ACTION) {
+ mSensorManager.unregisterListener(mFlipListener);
+ }
+ if (mShakeAction != ALARM_NO_ACTION) {
+ mSensorManager.unregisterListener(mShakeListener);
+ }
+ }
+
+ private void handleAction(int action) {
+ switch (action) {
+ case ALARM_SNOOZE:
+ // Setup Snooze Action
+ Intent snoozeIntent = AlarmStateManager.createStateChangeIntent(this, "SNOOZE_TAG",
+ mCurrentAlarm, AlarmInstance.SNOOZE_STATE);
+ sendBroadcast(snoozeIntent);
+ break;
+ case ALARM_DISMISS:
+ // Setup Dismiss Action
+ Intent dismissIntent = AlarmStateManager.createStateChangeIntent(this, "DISMISS_TAG",
+ mCurrentAlarm, AlarmInstance.DISMISSED_STATE);
+ sendBroadcast(dismissIntent);
+ break;
+ case ALARM_NO_ACTION:
+ default:
+ break;
+ }
+ }
+
}