Adding missed call notification.
Adds a MissedCallNotifier class and a TelecommBroadcastReceiver to
receive the pending intents issued by the new notification.
Bug: 13625335
Change-Id: I51b273f3bd4ecb55e2f0e61b789f609d72086deb
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d58c898..142fe6d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,6 +25,7 @@
<uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"></uses-permission>
@@ -164,5 +165,13 @@
<!-- Selects call services to place emergency calls. -->
<service android:name="EmergencyCallServiceSelector" android:exported="false" />
+ <receiver android:name="TelecommBroadcastReceiver" android:exported="false">
+ <intent-filter>
+ <action android:name="com.android.telecomm.ACTION_CALL_BACK_FROM_NOTIFICATION" />
+ <action android:name="com.android.telecomm.ACTION_CALL_BACK_FROM_NOTIFICATION" />
+ <action android:name="com.android.telecomm.ACTION_SEND_SMS_FROM_NOTIFICATION" />
+ </intent-filter>
+ </receiver>
+
</application>
</manifest>
diff --git a/res/drawable-hdpi/ic_text_holo_dark.png b/res/drawable-hdpi/ic_text_holo_dark.png
new file mode 100644
index 0000000..6d21e42
--- /dev/null
+++ b/res/drawable-hdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/stat_sys_phone_call.png b/res/drawable-hdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..7eda84c
--- /dev/null
+++ b/res/drawable-hdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/ic_text_holo_dark.png b/res/drawable-ldrtl-hdpi/ic_text_holo_dark.png
new file mode 100644
index 0000000..b99073e
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/stat_sys_phone_call.png b/res/drawable-ldrtl-hdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..e0f33f8
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/ic_text_holo_dark.png b/res/drawable-ldrtl-mdpi/ic_text_holo_dark.png
new file mode 100644
index 0000000..4106c32
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/stat_sys_phone_call.png b/res/drawable-ldrtl-mdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..d771d87
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/ic_text_holo_dark.png b/res/drawable-ldrtl-xhdpi/ic_text_holo_dark.png
new file mode 100644
index 0000000..99e7e38
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.png b/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..86af9c2
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_text_holo_dark.png b/res/drawable-mdpi/ic_text_holo_dark.png
new file mode 100644
index 0000000..80b95ee
--- /dev/null
+++ b/res/drawable-mdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/stat_sys_phone_call.png b/res/drawable-mdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..70a4bbe
--- /dev/null
+++ b/res/drawable-mdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_text_holo_dark.png b/res/drawable-xhdpi/ic_text_holo_dark.png
new file mode 100644
index 0000000..e80a042
--- /dev/null
+++ b/res/drawable-xhdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/stat_sys_phone_call.png b/res/drawable-xhdpi/stat_sys_phone_call.png
new file mode 100644
index 0000000..1bb4340
--- /dev/null
+++ b/res/drawable-xhdpi/stat_sys_phone_call.png
Binary files differ
diff --git a/res/values/strings.xml b/res/values/strings.xml
index acae2b6..42cda0e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -18,4 +18,26 @@
<!-- Official label of the Telecomm app, as seen in "Manage Applications"
and other settings UIs. -->
<string name="telecommAppLabel" product="default">Telecomm</string>
+
+ <!-- Name for an "unknown" caller. -->
+ <string name="unknown">Unknown</string>
+
+ <!-- Notification strings -->
+ <!-- Missed call notification label, used when there's exactly one missed call -->
+ <string name="notification_missedCallTitle">Missed call</string>
+ <!-- Missed call notification label, used when there are two or more missed calls -->
+ <string name="notification_missedCallsTitle">Missed calls</string>
+ <!-- Missed call notification message used when there are multiple missed calls -->
+ <string name="notification_missedCallsMsg"><xliff:g id="num_missed_calls">%s</xliff:g> missed calls</string>
+ <!-- Missed call notification message used for a single missed call, including
+ the caller-id info from the missed call -->
+ <string name="notification_missedCallTicker">Missed call from <xliff:g id="missed_call_from">%s</xliff:g></string>
+ <!-- Message for "call back" Action, which is displayed in the missed call notificaiton.
+ The user will be able to call back to the person or the phone number.
+ [CHAR LIMIT=60] -->
+ <string name="notification_missedCall_call_back">Call back</string>
+ <!-- Message for "reply via sms" action, which is displayed in the missed call notification.
+ The user will be able to send text messages using the phone number.
+ [CHAR LIMIT=60] -->
+ <string name="notification_missedCall_message">Message</string>
</resources>
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index f79a362..0eef378 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -137,7 +137,7 @@
@Override public String toString() {
return String.format(Locale.US, "[%s, %s, %s]", mState,
mCallService == null ? "<null>" : mCallService.getComponentName(),
- Log.pii(mHandle));
+ Log.piiHandle(mHandle));
}
CallState getState() {
@@ -220,7 +220,7 @@
* @return The "age" of this call object in milliseconds, which typically also represents the
* period since this call was added to the set pending outgoing calls, see mCreationTime.
*/
- long getAgeInMilliseconds() {
+ long getAgeMs() {
return new Date().getTime() - mCreationTime.getTime();
}
@@ -228,7 +228,7 @@
* @return The time when this call object was created and added to the set of pending outgoing
* calls.
*/
- long getCreationTimeInMilliseconds() {
+ long getCreationTimeMs() {
return mCreationTime.getTime();
}
diff --git a/src/com/android/telecomm/CallActivity.java b/src/com/android/telecomm/CallActivity.java
index 77e64bc..2868216 100644
--- a/src/com/android/telecomm/CallActivity.java
+++ b/src/com/android/telecomm/CallActivity.java
@@ -73,6 +73,8 @@
private void processIntent(Intent intent) {
String action = intent.getAction();
+ // TODO: Check for non-voice capable devices before reading any intents.
+
if (Intent.ACTION_CALL.equals(action) ||
Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
Intent.ACTION_CALL_EMERGENCY.equals(action)) {
diff --git a/src/com/android/telecomm/CallLogManager.java b/src/com/android/telecomm/CallLogManager.java
index 99eb845..8bdc150 100644
--- a/src/com/android/telecomm/CallLogManager.java
+++ b/src/com/android/telecomm/CallLogManager.java
@@ -101,8 +101,8 @@
* {@link android.provider.CallLog.Calls#MISSED_TYPE}
*/
private void logCall(Call call, int callLogType) {
- final long creationTime = call.getCreationTimeInMilliseconds();
- final long age = call.getAgeInMilliseconds();
+ final long creationTime = call.getCreationTimeMs();
+ final long age = call.getAgeMs();
final ContactInfo contactInfo = call.getContactInfo(); // May be null.
final String logNumber = getLogNumber(call);
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index b7f7aec..b8724e3 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -92,19 +92,20 @@
* Initializes the required Telecomm components.
*/
private CallsManager() {
- mSwitchboard = new Switchboard(this);
+ TelecommApp app = TelecommApp.getInstance();
+ mSwitchboard = new Switchboard(this);
mCallAudioManager = new CallAudioManager();
InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(mCallAudioManager);
-
- mListeners.add(new CallLogManager(TelecommApp.getInstance()));
+ mListeners.add(new CallLogManager(app));
mListeners.add(new PhoneStateBroadcaster());
mListeners.add(new InCallController());
mListeners.add(new Ringer(mCallAudioManager));
mListeners.add(new RingbackPlayer(this, playerFactory));
mListeners.add(new InCallToneMonitor(playerFactory, this));
mListeners.add(mCallAudioManager);
+ mListeners.add(app.getMissedCallNotifier());
}
static CallsManager getInstance() {
diff --git a/src/com/android/telecomm/Log.java b/src/com/android/telecomm/Log.java
index d63f23c..b25aec1 100644
--- a/src/com/android/telecomm/Log.java
+++ b/src/com/android/telecomm/Log.java
@@ -16,6 +16,9 @@
package com.android.telecomm;
+import android.net.Uri;
+import android.telephony.PhoneNumberUtils;
+
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.IllegalFormatException;
@@ -122,6 +125,34 @@
android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
}
+ public static String piiHandle(Object pii) {
+ if (pii == null || VERBOSE) {
+ return String.valueOf(pii);
+ }
+
+ if (pii instanceof Uri) {
+ Uri uri = (Uri) pii;
+
+ // All Uri's which are not "tel" go through normal pii() method.
+ if (!"tel".equals(uri.getScheme())) {
+ return pii(pii);
+ } else {
+ pii = uri.getSchemeSpecificPart();
+ }
+ }
+
+ String originalString = String.valueOf(pii);
+ StringBuilder stringBuilder = new StringBuilder(originalString.length());
+ for (char c : originalString.toCharArray()) {
+ if (PhoneNumberUtils.isDialable(c)) {
+ stringBuilder.append('*');
+ } else {
+ stringBuilder.append(c);
+ }
+ }
+ return stringBuilder.toString();
+ }
+
/**
* Redact personally identifiable information for production users.
* If we are running in verbose mode, return the original string, otherwise
diff --git a/src/com/android/telecomm/MissedCallNotifier.java b/src/com/android/telecomm/MissedCallNotifier.java
new file mode 100644
index 0000000..8100472
--- /dev/null
+++ b/src/com/android/telecomm/MissedCallNotifier.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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.
+ */
+
+package com.android.telecomm;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.CallLog;
+import android.provider.CallLog.Calls;
+import android.telecomm.CallState;
+import android.telephony.DisconnectCause;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+
+/**
+ * Creates a notification for calls that the user missed (neither answered nor rejected).
+ * TODO(santoscordon): Make TelephonyManager.clearMissedCalls call into this class.
+ * STOPSHIP: Resolve b/13769374 about moving this class to InCall.
+ */
+class MissedCallNotifier extends CallsManagerListenerBase {
+
+ private static final int MISSED_CALL_NOTIFICATION_ID = 1;
+ private static final String SCHEME_SMSTO = "smsto";
+
+ private final Context mContext;
+ private final NotificationManager mNotificationManager;
+
+ // Used to track the number of missed calls.
+ private int mMissedCallCount = 0;
+
+ MissedCallNotifier(Context context) {
+ mContext = context;
+ mNotificationManager =
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onCallStateChanged(Call call, CallState oldState, CallState newState) {
+ if (oldState == CallState.RINGING && newState == CallState.DISCONNECTED &&
+ call.getDisconnectCause() == DisconnectCause.INCOMING_MISSED) {
+ showMissedCallNotification(call);
+ }
+ }
+
+ /** Clears missed call notification and marks the call log's missed calls as read. */
+ void clearMissedCalls() {
+ // Clear the list of new missed calls from the call log.
+ ContentValues values = new ContentValues();
+ values.put(Calls.NEW, 0);
+ values.put(Calls.IS_READ, 1);
+ StringBuilder where = new StringBuilder();
+ where.append(Calls.NEW);
+ where.append(" = 1 AND ");
+ where.append(Calls.TYPE);
+ where.append(" = ?");
+ mContext.getContentResolver().update(Calls.CONTENT_URI, values, where.toString(),
+ new String[]{ Integer.toString(Calls.MISSED_TYPE) });
+
+ cancelMissedCallNotification();
+ }
+
+ /**
+ * Create a system notification for the missed call.
+ *
+ * @param call The missed call.
+ */
+ private void showMissedCallNotification(Call call) {
+ mMissedCallCount++;
+
+ final int titleResId;
+ final String expandedText; // The text in the notification's line 1 and 2.
+
+ // Display the first line of the notification:
+ // 1 missed call: <caller name || handle>
+ // More than 1 missed call: <number of calls> + "missed calls"
+ if (mMissedCallCount == 1) {
+ titleResId = R.string.notification_missedCallTitle;
+ expandedText = getNameForCall(call);
+ } else {
+ titleResId = R.string.notification_missedCallsTitle;
+ expandedText =
+ mContext.getString(R.string.notification_missedCallsMsg, mMissedCallCount);
+ }
+
+ // Create the notification.
+ Notification.Builder builder = new Notification.Builder(mContext);
+ builder.setSmallIcon(android.R.drawable.stat_notify_missed_call)
+ .setWhen(call.getCreationTimeMs())
+ .setContentTitle(mContext.getText(titleResId))
+ .setContentText(expandedText)
+ .setContentIntent(createCallLogPendingIntent())
+ .setAutoCancel(true)
+ .setDeleteIntent(createClearMissedCallsPendingIntent());
+
+ Uri handleUri = call.getHandle();
+ String handle = handleUri.getSchemeSpecificPart();
+
+ // Add additional actions when there is only 1 missed call, like call-back and SMS.
+ if (mMissedCallCount == 1) {
+ Log.d(this, "Add actions with number %s.", Log.piiHandle(handle));
+
+ builder.addAction(R.drawable.stat_sys_phone_call,
+ mContext.getString(R.string.notification_missedCall_call_back),
+ createCallBackPendingIntent(handleUri));
+
+ builder.addAction(R.drawable.ic_text_holo_dark,
+ mContext.getString(R.string.notification_missedCall_message),
+ createSendSmsFromNotificationPendingIntent(handleUri));
+
+ // TODO(santoscordon): Add photo for contact.
+ } else {
+ Log.d(this, "Suppress actions. handle: %s, missedCalls: %s." + Log.piiHandle(handle),
+ mMissedCallCount);
+ }
+
+ Notification notification = builder.build();
+ configureLedOnNotification(notification);
+ mNotificationManager.notify(MISSED_CALL_NOTIFICATION_ID, notification);
+ }
+
+ /** Cancels the "missed call" notification. */
+ private void cancelMissedCallNotification() {
+ // Reset the number of missed calls to 0.
+ mMissedCallCount = 0;
+ mNotificationManager.cancel(MISSED_CALL_NOTIFICATION_ID);
+ }
+
+ /**
+ * Returns the name to use in the missed call notification.
+ */
+ private String getNameForCall(Call call) {
+ // TODO(santoscordon): Get detailed caller information.
+
+ String handle = call.getHandle().getSchemeSpecificPart();
+ if (!TextUtils.isEmpty(handle)) {
+ // A handle should always be displayed LTR using {@link BidiFormatter} regardless of the
+ // content of the rest of the notification.
+ // TODO(santoscordon): Does this apply to SIP addresses?
+ BidiFormatter bidiFormatter = BidiFormatter.getInstance();
+ return bidiFormatter.unicodeWrap(handle, TextDirectionHeuristics.LTR);
+ } else {
+ // Use "unknown" if the call is unidentifiable.
+ return mContext.getString(R.string.unknown);
+ }
+ }
+
+ /**
+ * Creates a new pending intent that sends the user to the call log.
+ *
+ * @return The pending intent.
+ */
+ private PendingIntent createCallLogPendingIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW, null);
+ intent.setType(CallLog.Calls.CONTENT_TYPE);
+
+ TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(mContext);
+ taskStackBuilder.addNextIntent(intent);
+
+ return taskStackBuilder.getPendingIntent(0, 0);
+ }
+
+ /**
+ * Creates an intent to be invoked when the missed call notification is cleared.
+ */
+ private PendingIntent createClearMissedCallsPendingIntent() {
+ return createTelecommPendingIntent(
+ TelecommBroadcastReceiver.ACTION_CLEAR_MISSED_CALLS, null);
+ }
+
+ /**
+ * Creates an intent to be invoked when the user opts to "call back" from the missed call
+ * notification.
+ *
+ * @param handle The handle to call back.
+ */
+ private PendingIntent createCallBackPendingIntent(Uri handle) {
+ return createTelecommPendingIntent(
+ TelecommBroadcastReceiver.ACTION_CALL_BACK_FROM_NOTIFICATION, handle);
+ }
+
+ /**
+ * Creates an intent to be invoked when the user opts to "send sms" from the missed call
+ * notification.
+ */
+ private PendingIntent createSendSmsFromNotificationPendingIntent(Uri handle) {
+ return createTelecommPendingIntent(
+ TelecommBroadcastReceiver.ACTION_SEND_SMS_FROM_NOTIFICATION,
+ Uri.fromParts(SCHEME_SMSTO, handle.getSchemeSpecificPart(), null));
+ }
+
+ /**
+ * Creates generic pending intent from the specified parameters to be received by
+ * {@link TelecommBroadcastReceiver}.
+ *
+ * @param action The intent action.
+ * @param data The intent data.
+ */
+ private PendingIntent createTelecommPendingIntent(String action, Uri data) {
+ Intent intent = new Intent(action, data, mContext, TelecommBroadcastReceiver.class);
+ return PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ }
+
+ /**
+ * Configures a notification to emit the blinky notification light.
+ */
+ private void configureLedOnNotification(Notification notification) {
+ notification.flags |= Notification.FLAG_SHOW_LIGHTS;
+ notification.defaults |= Notification.DEFAULT_LIGHTS;
+ }
+}
diff --git a/src/com/android/telecomm/Switchboard.java b/src/com/android/telecomm/Switchboard.java
index c2df63e..66e1269 100644
--- a/src/com/android/telecomm/Switchboard.java
+++ b/src/com/android/telecomm/Switchboard.java
@@ -363,7 +363,7 @@
Iterator<Call> iterator = calls.iterator();
while (iterator.hasNext()) {
Call call = iterator.next();
- if (call.getAgeInMilliseconds() >= newCallTimeoutMs) {
+ if (call.getAgeMs() >= newCallTimeoutMs) {
Log.d(this, "Call %s timed out.", call);
mOutgoingCallsManager.abort(call);
calls.remove(call);
diff --git a/src/com/android/telecomm/TelecommApp.java b/src/com/android/telecomm/TelecommApp.java
index e0a3bf6..49554da 100644
--- a/src/com/android/telecomm/TelecommApp.java
+++ b/src/com/android/telecomm/TelecommApp.java
@@ -23,13 +23,20 @@
*/
public final class TelecommApp extends Application {
- // Singleton instance of TelecommApp.
+ /** Singleton instance of TelecommApp. */
private static TelecommApp sInstance;
+ /**
+ * Missed call notifier. Exists here so that the instance can be shared with
+ * {@link TelecommBroadcastReceiver}.
+ */
+ private MissedCallNotifier mMissedCallNotifier;
+
/** {@inheritDoc} */
@Override public void onCreate() {
super.onCreate();
sInstance = this;
+ mMissedCallNotifier = new MissedCallNotifier(this);
}
public static TelecommApp getInstance() {
@@ -38,4 +45,8 @@
}
return sInstance;
}
+
+ MissedCallNotifier getMissedCallNotifier() {
+ return mMissedCallNotifier;
+ }
}
diff --git a/src/com/android/telecomm/TelecommBroadcastReceiver.java b/src/com/android/telecomm/TelecommBroadcastReceiver.java
new file mode 100644
index 0000000..1168b89
--- /dev/null
+++ b/src/com/android/telecomm/TelecommBroadcastReceiver.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package com.android.telecomm;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+
+/**
+ * Handles miscellaneous Telecomm broadcast intents. This should be visible from outside, but
+ * should not be in the "exported" state.
+ */
+public final class TelecommBroadcastReceiver extends BroadcastReceiver {
+ /** The action used to send SMS response for the missed call notification. */
+ static final String ACTION_SEND_SMS_FROM_NOTIFICATION =
+ "com.android.telecomm.ACTION_SEND_SMS_FROM_NOTIFICATION";
+
+ /** The action used to call a handle back for the missed call notification. */
+ static final String ACTION_CALL_BACK_FROM_NOTIFICATION =
+ "com.android.telecomm.ACTION_CALL_BACK_FROM_NOTIFICATION";
+
+ /** The action used to clear missed calls. */
+ static final String ACTION_CLEAR_MISSED_CALLS =
+ "com.android.telecomm.ACTION_CLEAR_MISSED_CALLS";
+
+
+ /** {@inheritDoc} */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ Log.v(this, "Action received: %s.", action);
+
+ MissedCallNotifier missedCallNotifier = TelecommApp.getInstance().getMissedCallNotifier();
+
+ // Send an SMS from the missed call notification.
+ if (ACTION_SEND_SMS_FROM_NOTIFICATION.equals(action)) {
+ // Close the notification shade and the notification itself.
+ closeSystemDialogs(context);
+ missedCallNotifier.clearMissedCalls();
+
+ Intent callIntent = new Intent(Intent.ACTION_SENDTO, intent.getData());
+ callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(callIntent);
+
+ // Call back recent caller from the missed call notification.
+ } else if (ACTION_CALL_BACK_FROM_NOTIFICATION.equals(action)) {
+ // Close the notification shade and the notification itself.
+ closeSystemDialogs(context);
+ missedCallNotifier.clearMissedCalls();
+
+ Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData());
+ callIntent.setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ context.startActivity(callIntent);
+
+ // Clear the missed call notification and call log entries.
+ } else if (ACTION_CLEAR_MISSED_CALLS.equals(action)) {
+ missedCallNotifier.clearMissedCalls();
+ }
+ }
+
+ /**
+ * Closes open system dialogs and the notification shade.
+ */
+ private void closeSystemDialogs(Context context) {
+ Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ context.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+}