summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--InCallUI/src/com/android/incallui/AnswerFragment.java97
-rw-r--r--InCallUI/src/com/android/incallui/AnswerPresenter.java27
-rw-r--r--InCallUI/src/com/android/incallui/CallCommandClient.java4
-rw-r--r--InCallUI/src/com/android/incallui/CallHandlerService.java24
-rw-r--r--InCallUI/src/com/android/incallui/CallList.java36
5 files changed, 183 insertions, 5 deletions
diff --git a/InCallUI/src/com/android/incallui/AnswerFragment.java b/InCallUI/src/com/android/incallui/AnswerFragment.java
index a20fdb9ab..196a66bb0 100644
--- a/InCallUI/src/com/android/incallui/AnswerFragment.java
+++ b/InCallUI/src/com/android/incallui/AnswerFragment.java
@@ -16,10 +16,19 @@
package com.android.incallui;
+import com.google.common.base.Preconditions;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.util.ArrayList;
/**
*
@@ -27,6 +36,18 @@ import android.view.ViewGroup;
public class AnswerFragment extends BaseFragment<AnswerPresenter> implements
GlowPadWrapper.AnswerListener, AnswerPresenter.AnswerUi {
+ /**
+ * The popup showing the list of canned responses.
+ *
+ * This is an AlertDialog containing a ListView showing the possible
+ * choices. This may be null if the InCallScreen hasn't ever called
+ * showRespondViaSmsPopup() yet, or if the popup was visible once but
+ * then got dismissed.
+ */
+ private Dialog mCannedResponsePopup = null;
+
+ private ArrayAdapter<String> mTextResponsesAdapter = null;
+
public AnswerFragment() {
}
@@ -53,6 +74,55 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter> implements
}
@Override
+ public void showTextButton(boolean show) {
+ // TODO(klp) Hide the text button when the call does not support reject by text.
+ }
+
+ @Override
+ public boolean isMessageDialogueShowing() {
+ return mCannedResponsePopup != null && mCannedResponsePopup.isShowing();
+ }
+
+ @Override
+ public void showMessageDialogue() {
+ final ListView lv = new ListView(getActivity());
+
+ Preconditions.checkNotNull(mTextResponsesAdapter);
+ lv.setAdapter(mTextResponsesAdapter);
+ lv.setOnItemClickListener(new RespondViaSmsItemClickListener());
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setCancelable(true)
+ .setView(lv);
+ mCannedResponsePopup = builder.create();
+ mCannedResponsePopup.show();
+ }
+
+ /**
+ * Dismiss currently visible popups.
+ *
+ * This is safe to call even if the popup is already dismissed, and
+ * even if you never called showRespondViaSmsPopup() in the first
+ * place.
+ */
+ @Override
+ public void dismissPopup() {
+ if (mCannedResponsePopup != null) {
+ mCannedResponsePopup.dismiss(); // safe even if already dismissed
+ mCannedResponsePopup = null;
+ }
+ }
+
+ @Override
+ public void configureMessageDialogue(ArrayList<String> textResponses) {
+ textResponses.add(getResources().getString(R.string.respond_via_sms_custom_message));
+ mTextResponsesAdapter = new ArrayAdapter<String>(getActivity(),
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ textResponses);
+ }
+
+ @Override
public void onAnswer() {
getPresenter().onAnswer();
}
@@ -66,4 +136,31 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter> implements
public void onText() {
getPresenter().onText();
}
+
+ /**
+ * OnItemClickListener for the "Respond via SMS" popup.
+ */
+ public class RespondViaSmsItemClickListener implements AdapterView.OnItemClickListener {
+ /**
+ * Handles the user selecting an item from the popup.
+ */
+ @Override
+ public void onItemClick(AdapterView<?> parent, // The ListView
+ View view, // The TextView that was clicked
+ int position,
+ long id) {
+ Logger.d(this, "RespondViaSmsItemClickListener.onItemClick(" + position + ")...");
+ final String message = (String) parent.getItemAtPosition(position);
+ Logger.v(this, "- message: '" + message + "'");
+
+ // The "Custom" choice is a special case.
+ // (For now, it's guaranteed to be the last item.)
+ if (position == (parent.getCount() - 1)) {
+ // Take the user to the standard SMS compose UI.
+ getPresenter().rejectCallWithMessage(null);
+ } else {
+ getPresenter().rejectCallWithMessage(message);
+ }
+ }
+ }
}
diff --git a/InCallUI/src/com/android/incallui/AnswerPresenter.java b/InCallUI/src/com/android/incallui/AnswerPresenter.java
index 123fe9ce9..c3a7c13ad 100644
--- a/InCallUI/src/com/android/incallui/AnswerPresenter.java
+++ b/InCallUI/src/com/android/incallui/AnswerPresenter.java
@@ -22,6 +22,8 @@ import com.android.incallui.InCallPresenter.InCallState;
import com.android.incallui.InCallPresenter.InCallStateListener;
import com.android.services.telephony.common.Call;
+import java.util.ArrayList;
+
/**
* Presenter for the Incoming call widget.
*/
@@ -29,6 +31,7 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
implements InCallStateListener {
private Call mCall;
+ private ArrayList<String> mTextResponses;
@Override
public void onUiReady(AnswerUi ui) {
@@ -40,7 +43,13 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
if (state == InCallState.INCOMING) {
getUi().showAnswerUi(true);
mCall = callList.getIncomingCall();
-
+ mTextResponses = callList.getTextResponses(mCall);
+ if (mTextResponses != null) {
+ getUi().showTextButton(true);
+ getUi().configureMessageDialogue(mTextResponses);
+ } else {
+ getUi().showTextButton(false);
+ }
Logger.d(this, "Showing incoming with: " + mCall);
} else {
getUi().showAnswerUi(false);
@@ -59,13 +68,25 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
Preconditions.checkNotNull(mCall);
Logger.d(this, "onDecline " + mCall.getCallId());
- CallCommandClient.getInstance().rejectCall(mCall.getCallId());
+ CallCommandClient.getInstance().rejectCall(mCall.getCallId(), false, null);
}
public void onText() {
+ getUi().showMessageDialogue();
+ }
+
+ public void rejectCallWithMessage(String message) {
+ Logger.d(this, "sendTextToDefaultActivity()...");
+ CallCommandClient.getInstance().rejectCall(mCall.getCallId(), true, message);
+ getUi().dismissPopup();
}
interface AnswerUi extends Ui {
public void showAnswerUi(boolean show);
+ public void showTextButton(boolean show);
+ public boolean isMessageDialogueShowing();
+ public void showMessageDialogue();
+ public void dismissPopup();
+ public void configureMessageDialogue(ArrayList<String> textResponses);
}
-}
+} \ No newline at end of file
diff --git a/InCallUI/src/com/android/incallui/CallCommandClient.java b/InCallUI/src/com/android/incallui/CallCommandClient.java
index 381d8d383..80a9e9e10 100644
--- a/InCallUI/src/com/android/incallui/CallCommandClient.java
+++ b/InCallUI/src/com/android/incallui/CallCommandClient.java
@@ -56,9 +56,9 @@ public class CallCommandClient {
}
}
- public void rejectCall(int callId) {
+ public void rejectCall(int callId, boolean rejectWithMessage, String message) {
try {
- mCommandService.rejectCall(callId);
+ mCommandService.rejectCall(callId, rejectWithMessage, message);
} catch (RemoteException e) {
Logger.e(this, "Error rejecting call.", e);
}
diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java
index dcba7d6f9..173f6a345 100644
--- a/InCallUI/src/com/android/incallui/CallHandlerService.java
+++ b/InCallUI/src/com/android/incallui/CallHandlerService.java
@@ -26,7 +26,10 @@ import com.android.services.telephony.common.Call;
import com.android.services.telephony.common.ICallCommandService;
import com.android.services.telephony.common.ICallHandlerService;
+import java.util.AbstractMap;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* Service used to listen for call state changes.
@@ -35,6 +38,7 @@ public class CallHandlerService extends Service {
private static final int ON_UPDATE_CALL = 1;
private static final int ON_UPDATE_MULTI_CALL = 2;
+ private static final int ON_UPDATE_CALL_WITH_TEXT_RESPONSES = 3;
private CallList mCallList;
private Handler mMainHandler;
@@ -72,10 +76,27 @@ public class CallHandlerService extends Service {
}
@Override
+ public void onIncoming(Call call, List<String> textResponses) {
+ // TODO(klp): Add text responses to the call object.
+ Map.Entry<Call, List<String> > incomingCall = new AbstractMap.SimpleEntry<Call,
+ List<String> >(call, textResponses);
+ mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_CALL_WITH_TEXT_RESPONSES,
+ 0, 0, incomingCall));
+ }
+
+ @Override
public void onUpdate(List<Call> calls, boolean fullUpdate) {
// TODO(klp): Add use of fullUpdate to message
mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_MULTI_CALL, 0, 0, calls));
}
+
+ @Override
+ public void onAudioModeChange(int mode) {
+ }
+
+ @Override
+ public void onAudioModeSupportChange(int modeMask) {
+ }
};
/**
@@ -101,6 +122,9 @@ public class CallHandlerService extends Service {
case ON_UPDATE_MULTI_CALL:
mCallList.onUpdate((List<Call>) msg.obj);
break;
+ case ON_UPDATE_CALL_WITH_TEXT_RESPONSES:
+ mCallList.onUpdate((AbstractMap.SimpleEntry<Call, List<String> >) msg.obj);
+ break;
default:
break;
}
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index c16c53df0..3a90a7e52 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -25,6 +25,8 @@ import com.google.common.collect.ImmutableMap;
import com.android.services.telephony.common.Call;
+import java.util.AbstractMap;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -49,6 +51,8 @@ public class CallList {
private static CallList sInstance;
private final HashMap<Integer, Call> mCallMap = Maps.newHashMap();
+ private final HashMap<Integer, ArrayList<String>> mCallTextReponsesMap =
+ Maps.newHashMap();
private final Set<Listener> mListeners = Sets.newArraySet();
/**
@@ -74,6 +78,19 @@ public class CallList {
Logger.d(this, "onUpdate - " + safeCallString(call));
updateCallInMap(call);
+
+ notifyListenersOfChange();
+ }
+
+ /**
+ * Called when a single call has changed.
+ */
+ public void onUpdate(AbstractMap.SimpleEntry<Call, List<String> > incomingCall) {
+ Logger.d(this, "onUpdate - " + safeCallString(incomingCall.getKey()));
+
+ updateCallInMap(incomingCall.getKey());
+ updateCallTextMap(incomingCall.getKey(), incomingCall.getValue());
+
notifyListenersOfChange();
}
@@ -88,6 +105,7 @@ public class CallList {
Logger.d(this, "\t" + safeCallString(call));
updateCallInMap(call);
+ updateCallTextMap(call, null);
}
notifyListenersOfChange();
@@ -158,6 +176,10 @@ public class CallList {
return false;
}
+ public ArrayList<String> getTextResponses(Call call) {
+ return mCallTextReponsesMap.get(call.getCallId());
+ }
+
/**
* Returns first call found in the call map with the specified state.
*/
@@ -210,6 +232,20 @@ public class CallList {
}
}
+ private void updateCallTextMap(Call call, List<String> textResponses) {
+ Preconditions.checkNotNull(call);
+
+ final Integer id = new Integer(call.getCallId());
+
+ if (!isCallDead(call)) {
+ if (textResponses != null) {
+ mCallTextReponsesMap.put(id, (ArrayList<String>) textResponses);
+ }
+ } else if (mCallMap.containsKey(id)) {
+ mCallTextReponsesMap.remove(id);
+ }
+ }
+
private boolean isCallDead(Call call) {
final int state = call.getState();
return Call.State.IDLE == state || Call.State.INVALID == state;