summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilhelm Fitzpatrick <rafial@cyngn.com>2015-12-23 15:58:25 -0800
committerMichael Bestas <mkbestas@lineageos.org>2018-02-11 02:36:11 +0200
commit1bd7a90878d1b580f68f32a4afa7df84b8a7e40c (patch)
treea74eea35178afb2f6c2efd031b2939292f8490f8
parent281ea21da6620b7657d24cb28a5c393bb4e81017 (diff)
downloadandroid_packages_apps_DeskClock-1bd7a90878d1b580f68f32a4afa7df84b8a7e40c.tar.gz
android_packages_apps_DeskClock-1bd7a90878d1b580f68f32a4afa7df84b8a7e40c.tar.bz2
android_packages_apps_DeskClock-1bd7a90878d1b580f68f32a4afa7df84b8a7e40c.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> Dan Pasanen <dan.pasanen@gmail.com> - Android 8.1 port Change-Id: I222b6cd53a95db6f8662e7aef52aa6922d8a5d6a
-rw-r--r--res/values/cm_strings.xml15
-rw-r--r--res/xml/settings.xml18
-rw-r--r--src/com/android/deskclock/alarms/AlarmService.java167
-rw-r--r--src/com/android/deskclock/data/AlarmModel.java8
-rw-r--r--src/com/android/deskclock/data/DataModel.java8
-rw-r--r--src/com/android/deskclock/data/SettingsDAO.java10
-rw-r--r--src/com/android/deskclock/data/SettingsModel.java8
-rw-r--r--src/com/android/deskclock/settings/SettingsActivity.java37
8 files changed, 269 insertions, 2 deletions
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 406988dfd..ebae31669 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2012-2016 The CyanogenMod Project
+ Copyright (C) 2017-2018 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,6 +16,20 @@
limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Setting title for the flip action setting. -->
+ <string name="flip_action_title">Device flip action</string>
+
+ <!-- Setting title for the shake action setting. -->
+ <string name="shake_action_title">Device shake action</string>
+
+ <!-- Entries listed in the setting flip and shake. -->
+ <string-array name="action_setting_entries">
+ <item>Snooze</item>
+ <item>Dismiss</item>
+ <item>Nothing</item>
+ </string-array>
+
<!-- Setting title for accessing the cLock widget settings -->
<string name="menu_item_widget_settings">Widget settings</string>
diff --git a/res/xml/settings.xml b/res/xml/settings.xml
index 73c3359e6..e4e6f32b0 100644
--- a/res/xml/settings.xml
+++ b/res/xml/settings.xml
@@ -87,6 +87,22 @@
android:title="@string/volume_button_setting_title" />
<com.android.deskclock.settings.SimpleMenuPreference
+ android:defaultValue="0"
+ android:dialogTitle="@string/flip_action_title"
+ android:entries="@array/action_setting_entries"
+ android:entryValues="@array/volume_button_setting_values"
+ android:key="flip_action"
+ android:title="@string/flip_action_title" />
+
+ <com.android.deskclock.settings.SimpleMenuPreference
+ android:defaultValue="0"
+ android:dialogTitle="@string/shake_action_title"
+ android:entries="@array/action_setting_entries"
+ android:entryValues="@array/volume_button_setting_values"
+ android:key="shake_action"
+ android:title="@string/shake_action_title" />
+
+ <com.android.deskclock.settings.SimpleMenuPreference
android:dialogTitle="@string/week_start_title"
android:entries="@array/week_start_entries"
android:entryValues="@array/week_start_values"
@@ -115,4 +131,4 @@
android:title="@string/timer_vibrate_title" />
</PreferenceCategory>
-</PreferenceScreen> \ No newline at end of file
+</PreferenceScreen>
diff --git a/src/com/android/deskclock/alarms/AlarmService.java b/src/com/android/deskclock/alarms/AlarmService.java
index b9a97db1b..67ae139be 100644
--- a/src/com/android/deskclock/alarms/AlarmService.java
+++ b/src/com/android/deskclock/alarms/AlarmService.java
@@ -21,6 +21,10 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
@@ -29,6 +33,7 @@ import android.telephony.TelephonyManager;
import com.android.deskclock.AlarmAlertWakeLock;
import com.android.deskclock.LogUtils;
import com.android.deskclock.R;
+import com.android.deskclock.data.DataModel;
import com.android.deskclock.events.Events;
import com.android.deskclock.provider.AlarmInstance;
@@ -62,6 +67,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();
@@ -103,6 +116,9 @@ public class AlarmService extends Service {
private TelephonyManager mTelephonyManager;
private AlarmInstance mCurrentAlarm = null;
+ private SensorManager mSensorManager;
+ private int mFlipAction;
+ private int mShakeAction;
private void startAlarm(AlarmInstance instance) {
LogUtils.v("AlarmService.start with instance: " + instance.mId);
@@ -118,6 +134,7 @@ public class AlarmService extends Service {
mTelephonyManager.listen(mPhoneStateListener.init(), PhoneStateListener.LISTEN_CALL_STATE);
AlarmKlaxon.start(this, mCurrentAlarm);
sendBroadcast(new Intent(ALARM_ALERT_ACTION));
+ attachListeners();
}
private void stopCurrentAlarm() {
@@ -136,6 +153,7 @@ public class AlarmService extends Service {
stopForeground(true /* removeNotification */);
mCurrentAlarm = null;
+ detachListeners();
AlarmAlertWakeLock.releaseCpuLock();
}
@@ -181,6 +199,11 @@ 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);
+ mFlipAction = DataModel.getDataModel().getFlipAction();
+ mShakeAction = DataModel.getDataModel().getShakeAction();
}
@Override
@@ -264,4 +287,148 @@ public class AlarmService extends Service {
}
}
}
+
+ 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
+ startService(AlarmStateManager.createStateChangeIntent(this,
+ AlarmStateManager.ALARM_SNOOZE_TAG, mCurrentAlarm,
+ AlarmInstance.SNOOZE_STATE));
+ break;
+ case ALARM_DISMISS:
+ // Setup Dismiss Action
+ startService(AlarmStateManager.createStateChangeIntent(this,
+ AlarmStateManager.ALARM_DISMISS_TAG, mCurrentAlarm,
+ AlarmInstance.DISMISSED_STATE));
+ break;
+ case ALARM_NO_ACTION:
+ default:
+ break;
+ }
+ }
}
diff --git a/src/com/android/deskclock/data/AlarmModel.java b/src/com/android/deskclock/data/AlarmModel.java
index da50fe550..cc1a42eb1 100644
--- a/src/com/android/deskclock/data/AlarmModel.java
+++ b/src/com/android/deskclock/data/AlarmModel.java
@@ -78,6 +78,14 @@ final class AlarmModel {
return mSettingsModel.getSnoozeLength();
}
+ int getFlipAction() {
+ return mSettingsModel.getFlipAction();
+ }
+
+ int getShakeAction() {
+ return mSettingsModel.getShakeAction();
+ }
+
/**
* This receiver is notified when system settings change. Cached information built on
* those system settings must be cleared.
diff --git a/src/com/android/deskclock/data/DataModel.java b/src/com/android/deskclock/data/DataModel.java
index 2b16ae84f..1be8468a4 100644
--- a/src/com/android/deskclock/data/DataModel.java
+++ b/src/com/android/deskclock/data/DataModel.java
@@ -735,6 +735,14 @@ public final class DataModel {
return mAlarmModel.getSnoozeLength();
}
+ public int getFlipAction() {
+ return mAlarmModel.getFlipAction();
+ }
+
+ public int getShakeAction() {
+ return mAlarmModel.getShakeAction();
+ }
+
//
// Stopwatch
//
diff --git a/src/com/android/deskclock/data/SettingsDAO.java b/src/com/android/deskclock/data/SettingsDAO.java
index 7e9408f3a..3fe7c6b79 100644
--- a/src/com/android/deskclock/data/SettingsDAO.java
+++ b/src/com/android/deskclock/data/SettingsDAO.java
@@ -349,6 +349,16 @@ final class SettingsDAO {
return new TimeZones(tzIds, tzNames);
}
+ static int getFlipAction(SharedPreferences prefs) {
+ final String string = prefs.getString(SettingsActivity.KEY_FLIP_ACTION, "0");
+ return Integer.parseInt(string);
+ }
+
+ static int getShakeAction(SharedPreferences prefs) {
+ final String string = prefs.getString(SettingsActivity.KEY_SHAKE_ACTION, "0");
+ return Integer.parseInt(string);
+ }
+
private static ClockStyle getClockStyle(Context context, SharedPreferences prefs, String key) {
final String defaultStyle = context.getString(R.string.default_clock_style);
final String clockStyle = prefs.getString(key, defaultStyle);
diff --git a/src/com/android/deskclock/data/SettingsModel.java b/src/com/android/deskclock/data/SettingsModel.java
index 103c21046..e41a89338 100644
--- a/src/com/android/deskclock/data/SettingsModel.java
+++ b/src/com/android/deskclock/data/SettingsModel.java
@@ -133,6 +133,14 @@ final class SettingsModel {
return SettingsDAO.getSnoozeLength(mPrefs);
}
+ int getFlipAction() {
+ return SettingsDAO.getFlipAction(mPrefs);
+ }
+
+ int getShakeAction() {
+ return SettingsDAO.getShakeAction(mPrefs);
+ }
+
Uri getDefaultAlarmRingtoneUri() {
return SettingsDAO.getDefaultAlarmRingtoneUri(mPrefs);
}
diff --git a/src/com/android/deskclock/settings/SettingsActivity.java b/src/com/android/deskclock/settings/SettingsActivity.java
index 59a7b7399..d8d739516 100644
--- a/src/com/android/deskclock/settings/SettingsActivity.java
+++ b/src/com/android/deskclock/settings/SettingsActivity.java
@@ -18,6 +18,8 @@ package com.android.deskclock.settings;
import android.content.Context;
import android.content.Intent;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.provider.Settings;
@@ -43,6 +45,8 @@ import com.android.deskclock.data.TimeZones;
import com.android.deskclock.data.Weekdays;
import com.android.deskclock.ringtone.RingtonePickerActivity;
+import java.util.List;
+
/**
* Settings for the Alarm Clock.
*/
@@ -61,6 +65,8 @@ public final class SettingsActivity extends BaseActivity {
public static final String KEY_DATE_TIME = "date_time";
public static final String KEY_VOLUME_BUTTONS = "volume_button_setting";
public static final String KEY_WEEK_START = "week_start";
+ public static final String KEY_FLIP_ACTION = "flip_action";
+ public static final String KEY_SHAKE_ACTION = "shake_action";
public static final String DEFAULT_VOLUME_BEHAVIOR = "0";
public static final String VOLUME_BEHAVIOR_SNOOZE = "1";
@@ -171,6 +177,8 @@ public final class SettingsActivity extends BaseActivity {
case KEY_CLOCK_STYLE:
case KEY_WEEK_START:
case KEY_VOLUME_BUTTONS:
+ case KEY_FLIP_ACTION:
+ case KEY_SHAKE_ACTION:
final SimpleMenuPreference simpleMenuPreference = (SimpleMenuPreference) pref;
final int i = simpleMenuPreference.findIndexOfValue((String) newValue);
pref.setSummary(simpleMenuPreference.getEntries()[i]);
@@ -308,6 +316,33 @@ public final class SettingsActivity extends BaseActivity {
final Preference timerRingtonePref = findPreference(KEY_TIMER_RINGTONE);
timerRingtonePref.setOnPreferenceClickListener(this);
timerRingtonePref.setSummary(DataModel.getDataModel().getTimerRingtoneTitle());
+
+ SensorManager sensorManager = (SensorManager)
+ getActivity().getSystemService(Context.SENSOR_SERVICE);
+
+ final SimpleMenuPreference flipActionPref =
+ (SimpleMenuPreference) 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
+ } else {
+ flipActionPref.setSummary(flipActionPref.getEntry());
+ flipActionPref.setOnPreferenceChangeListener(this);
+ }
+ }
+
+ final SimpleMenuPreference shakeActionPref =
+ (SimpleMenuPreference) 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
+ } else {
+ shakeActionPref.setSummary(shakeActionPref.getEntry());
+ shakeActionPref.setOnPreferenceChangeListener(this);
+ }
+ }
}
private void refreshListPreference(ListPreference preference) {
@@ -325,4 +360,4 @@ public final class SettingsActivity extends BaseActivity {
}
}
}
-} \ No newline at end of file
+}