summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaj Yengisetty <rajesh@cyngn.com>2015-04-02 15:55:58 -0700
committerMatt Garnes <matt@cyngn.com>2015-04-08 00:43:55 +0000
commitf5d80701256e6b66e36f894cfb8ee2a5c74fd0aa (patch)
tree348254498d9510f5dafce43e7ef09c974842f6f4
parente9add2c81cfb17321680d334f022e3f5abcdbf56 (diff)
downloadandroid_packages_apps_DeskClock-caf/cm-12.0.tar.gz
android_packages_apps_DeskClock-caf/cm-12.0.tar.bz2
android_packages_apps_DeskClock-caf/cm-12.0.zip
DeskClock: re-write delayAlarm for intercepting alarms when in-callcaf/cm-12.0
While the previous clean-up was necessary, it no longer meets the spec. This feature needs to trigger the alarm immediately after the call finishes. Change-Id: I71107277926c891f79b1e46fb27878994ac15ce0 (cherry picked from commit b685ff5e8f578101fc52c262d74bbc4f915aa460)
-rwxr-xr-xAndroidManifest.xml6
-rw-r--r--src/com/android/deskclock/AlarmInitReceiver.java2
-rwxr-xr-xsrc/com/android/deskclock/alarms/AlarmStateManager.java150
-rw-r--r--src/com/android/deskclock/alarms/PhoneStateReceiver.java69
4 files changed, 155 insertions, 72 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 77e1d2670..72246f7e0 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -105,6 +105,12 @@
android:exported="false">
</receiver>
+ <receiver android:name=".alarms.PhoneStateReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.PHONE_STATE"/>
+ </intent-filter>
+ </receiver>
+
<service android:name=".alarms.AlarmService"
android:exported="false">
</service>
diff --git a/src/com/android/deskclock/AlarmInitReceiver.java b/src/com/android/deskclock/AlarmInitReceiver.java
index 93d319bcb..26808ea9b 100644
--- a/src/com/android/deskclock/AlarmInitReceiver.java
+++ b/src/com/android/deskclock/AlarmInitReceiver.java
@@ -49,7 +49,7 @@ public class AlarmInitReceiver extends BroadcastReceiver {
// We need to increment the global id out of the async task to prevent
// race conditions
- AlarmStateManager.updateGloablIntentId(context);
+ AlarmStateManager.updateGlobalIntentId(context);
AsyncHandler.post(new Runnable() {
@Override public void run() {
// Remove the snooze alarm after a boot.
diff --git a/src/com/android/deskclock/alarms/AlarmStateManager.java b/src/com/android/deskclock/alarms/AlarmStateManager.java
index 412469e9c..67e0f90d1 100755
--- a/src/com/android/deskclock/alarms/AlarmStateManager.java
+++ b/src/com/android/deskclock/alarms/AlarmStateManager.java
@@ -44,7 +44,9 @@ import com.android.deskclock.provider.Alarm;
import com.android.deskclock.provider.AlarmInstance;
import java.util.Calendar;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* This class handles all the state changes for alarm instances. You need to
@@ -115,6 +117,9 @@ public final class AlarmStateManager extends BroadcastReceiver {
// Extra key to set the global broadcast id.
private static final String ALARM_GLOBAL_ID_EXTRA = "intent.extra.alarm.global.id";
+ // key to to retrieve pending alarm set
+ public static final String ALARM_PENDING_ALARM_KEY = "pending.alarm.key";
+
// Intent category tag used when schedule state change intents in alarm manager.
public static final String ALARM_MANAGER_TAG = "ALARM_MANAGER";
@@ -133,8 +138,17 @@ public final class AlarmStateManager extends BroadcastReceiver {
return prefs.getInt(ALARM_GLOBAL_ID_EXTRA, -1);
}
- public static void updateGloablIntentId(Context context) {
+ public static void updateGlobalIntentId(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // If there are any pending alarms, do not update the global id - pending alarms
+ // will be ignored by the receivers when the user tries to dismiss or snooze
+ Set<String> alarms = prefs.getStringSet(AlarmStateManager.ALARM_PENDING_ALARM_KEY,
+ new HashSet<String>());
+ if (alarms.size() > 0) {
+ return;
+ }
+
int globalId = prefs.getInt(ALARM_GLOBAL_ID_EXTRA, -1) + 1;
prefs.edit().putInt(ALARM_GLOBAL_ID_EXTRA, globalId).commit();
}
@@ -676,7 +690,7 @@ public final class AlarmStateManager extends BroadcastReceiver {
* @param instance to change state on
* @param state to change to
*/
- public void setAlarmState(Context context, AlarmInstance instance, int state) {
+ public static void setAlarmState(Context context, AlarmInstance instance, int state) {
switch(state) {
case AlarmInstance.SILENT_STATE:
setSilentState(context, instance);
@@ -733,49 +747,7 @@ public final class AlarmStateManager extends BroadcastReceiver {
final String action = intent.getAction();
LogUtils.v("AlarmStateManager received intent " + intent);
if (CHANGE_STATE_ACTION.equals(action)) {
- Uri uri = intent.getData();
- AlarmInstance instance = AlarmInstance.getInstance(context.getContentResolver(),
- AlarmInstance.getId(uri));
- if (instance == null) {
- // Not a big deal, but it shouldn't happen
- LogUtils.e("Can not change state for unknown instance: " + uri);
- return;
- }
-
- int globalId = getGlobalIntentId(context);
- int intentId = intent.getIntExtra(ALARM_GLOBAL_ID_EXTRA, -1);
- int alarmState = intent.getIntExtra(ALARM_STATE_EXTRA, -1);
- if (intentId != globalId) {
- LogUtils.i("Ignoring old Intent. IntentId: " + intentId + " GlobalId: " + globalId +
- " AlarmState: " + alarmState);
- return;
- }
-
- // If the phone is busy, keep the alarm snoozing.When the call is ended,
- // the new coming alarm or the alarm which wakes from sooze,will skip the codes here
- // and continue show the alarm as normal.
- if (context.getResources().getBoolean(R.bool.config_delayalarm)) {
- TelephonyManager mTelephonyManager = (TelephonyManager) context
- .getSystemService(Context.TELEPHONY_SERVICE);
- if ((mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE)
- && (alarmState == AlarmInstance.FIRED_STATE)) {
- snooze(context, intent, instance);
- return;
- }
- }
-
- if (alarmState >= 0) {
- setAlarmState(context, instance, alarmState);
- } else {
- // No need to register instance again when alarmState
- // equals POWER_OFF_ALARM_STATE. POWER_OFF_ALARM_STATE
- // is an invalid state for rtc power off alarm.
- if (alarmState == AlarmInstance.POWER_OFF_ALARM_STATE)
- {
- return;
- }
- registerInstance(context, instance, true);
- }
+ handleChangeStateIntent(context, intent);
} else if (SHOW_AND_DISMISS_ALARM_ACTION.equals(action)) {
Uri uri = intent.getData();
AlarmInstance instance = AlarmInstance.getInstance(context.getContentResolver(),
@@ -795,37 +767,73 @@ public final class AlarmStateManager extends BroadcastReceiver {
}
}
- /**
- * Make the alarm snooze based on the snooze interval in settings.
- * If the phone is not busy in call anymore, this method will not be
- * called, and the alarm will wake up based on snooze interval.
- */
- private void snooze(Context context, Intent intent, AlarmInstance instance) {
+ private static void handleChangeStateIntent(Context context, Intent intent) {
Uri uri = intent.getData();
- AlarmInstance newInstance = AlarmInstance.getInstance(context.getContentResolver(),
+ AlarmInstance instance = AlarmInstance.getInstance(context.getContentResolver(),
AlarmInstance.getId(uri));
- if (newInstance == null) {
- // If AlarmInstance is turn to null,return.
+ if (instance == null) {
+ // Not a big deal, but it shouldn't happen
+ LogUtils.e("Can not change state for unknown instance: " + uri);
+ return;
+ }
+
+ int globalId = getGlobalIntentId(context);
+ int intentId = intent.getIntExtra(ALARM_GLOBAL_ID_EXTRA, -1);
+ int alarmState = intent.getIntExtra(ALARM_STATE_EXTRA, -1);
+ if (intentId != globalId) {
+ LogUtils.i("Ignoring old Intent. IntentId: " + intentId + " GlobalId: " + globalId +
+ " AlarmState: " + alarmState);
return;
}
- // Notify the user that the alarm has been snoozed.
- Intent cancelSnooze = createStateChangeIntent(context, ALARM_MANAGER_TAG, newInstance,
- AlarmInstance.DISMISSED_STATE);
- PendingIntent broadcast = PendingIntent.getBroadcast(context, instance.hashCode(),
- cancelSnooze, 0);
- String label = newInstance.getLabelOrDefault(context);
- label = context.getString(R.string.alarm_notify_snooze_label, label);
- NotificationManager nm = (NotificationManager) context
- .getSystemService(Context.NOTIFICATION_SERVICE);
- Notification n = new Notification(R.drawable.stat_notify_alarm, label, 0);
- n.setLatestEventInfo(context, label,
- context.getString(R.string.alarm_notify_snooze_text,
- AlarmUtils.getFormattedTime(context, instance.getAlarmTime())),
- broadcast);
- n.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONGOING_EVENT;
- nm.notify(instance.hashCode(), n);
- setAlarmState(context, instance, AlarmInstance.SNOOZE_STATE);
+ // If the phone is busy, add the alarm to a string set in shared preferenecs that will be
+ // cleared when the call is ended.
+ if (context.getResources().getBoolean(R.bool.config_delayalarm)) {
+ TelephonyManager mTelephonyManager = (TelephonyManager) context
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if ((mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE)
+ && (alarmState == AlarmInstance.FIRED_STATE)) {
+ pendAlarm(context, uri, alarmState);
+ return;
+ }
+ }
+
+ setChangeAlarmState(context, instance, alarmState);
+ }
+
+ public static void setChangeAlarmState(Context context, AlarmInstance instance,
+ int alarmState) {
+
+ if (alarmState >= 0) {
+ setAlarmState(context, instance, alarmState);
+ } else {
+ // No need to register instance again when alarmState
+ // equals POWER_OFF_ALARM_STATE. POWER_OFF_ALARM_STATE
+ // is an invalid state for rtc power off alarm.
+ if (alarmState == AlarmInstance.POWER_OFF_ALARM_STATE) {
+ return;
+ }
+ registerInstance(context, instance, true);
+ }
+ }
+
+ /**
+ * Add the alarm to list of pending Alarms to be fired after the call is complete.
+ */
+ private static void pendAlarm(Context context, Uri uri, int alarmState) {
+ LogUtils.v("Pending alarm: " + uri);
+
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+ Set<String> alarms = sp.getStringSet(ALARM_PENDING_ALARM_KEY, new HashSet<String>());
+
+ // Alarms are stored as "<uri>|<alarmState>"
+ String alarm = uri.toString() + "|" + alarmState;
+
+ HashSet<String> newSet = new HashSet<String>();
+ newSet.addAll(alarms);
+ newSet.add(alarm);
+
+ sp.edit().putStringSet(ALARM_PENDING_ALARM_KEY, newSet).commit();
}
/**
diff --git a/src/com/android/deskclock/alarms/PhoneStateReceiver.java b/src/com/android/deskclock/alarms/PhoneStateReceiver.java
new file mode 100644
index 000000000..2ddcfd3a4
--- /dev/null
+++ b/src/com/android/deskclock/alarms/PhoneStateReceiver.java
@@ -0,0 +1,69 @@
+package com.android.deskclock.alarms;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.preference.PreferenceManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import com.android.deskclock.LogUtils;
+import com.android.deskclock.provider.AlarmInstance;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Watch the phone state to clear any alarms that are waiting for a call to end
+ */
+public class PhoneStateReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ LogUtils.v("PhoneStateReceiver received intent " + intent);
+
+ if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
+ TelephonyManager mTelephonyManager = (TelephonyManager) context
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ if (mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
+ // New call state is idle, update state for any pending alarms
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+ Set<String> alarms = sp.getStringSet(AlarmStateManager.ALARM_PENDING_ALARM_KEY,
+ new HashSet<String>());
+ if (alarms.size() <= 0) {
+ return; // no alarms to fire
+ }
+
+ Iterator<String> iterator = alarms.iterator();
+
+ while (iterator.hasNext()) {
+ String flatAlarm = iterator.next();
+ if (TextUtils.isEmpty(flatAlarm)) {
+ LogUtils.e("Unable to un-flatten alarm for restore");
+ return;
+ }
+
+ String [] items = flatAlarm.split("\\|");
+ if (items.length < 2) {
+ LogUtils.e("Unable to un-flatten alarm for restore");
+ return;
+ }
+
+ Uri uri = Uri.parse(items[0]);
+ AlarmInstance instance = AlarmInstance.getInstance(
+ context.getContentResolver(), AlarmInstance.getId(uri));
+ int alarmState = Integer.parseInt(items[1]);
+
+ AlarmStateManager.setChangeAlarmState(context, instance, alarmState);
+ iterator.remove();
+ }
+
+ // Clear out the pending alarms
+ sp.edit().remove(AlarmStateManager.ALARM_PENDING_ALARM_KEY).commit();
+ }
+ }
+ }
+} \ No newline at end of file