diff options
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/incallui/AnswerFragment.java | 51 | ||||
-rw-r--r-- | src/com/android/incallui/AnswerPresenter.java | 33 | ||||
-rw-r--r-- | src/com/android/incallui/GlowPadWrapper.java | 12 | ||||
-rw-r--r-- | src/com/android/incallui/TelecomAdapter.java | 9 | ||||
-rw-r--r-- | src/com/android/incallui/widget/multiwaveview/GlowPadView.java | 81 |
5 files changed, 174 insertions, 12 deletions
diff --git a/src/com/android/incallui/AnswerFragment.java b/src/com/android/incallui/AnswerFragment.java index 6ed5e558..2dfba187 100644 --- a/src/com/android/incallui/AnswerFragment.java +++ b/src/com/android/incallui/AnswerFragment.java @@ -21,6 +21,7 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; +import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.text.Editable; import android.text.TextWatcher; @@ -57,6 +58,9 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente public static final int TARGET_SET_FOR_VIDEO_WITHOUT_SMS_WITH_BLOCK = 5; public static final int TARGET_SET_FOR_VIDEO_WITH_SMS = 6; public static final int TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST = 7; + public static final int TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_CALL_WAITING = 8; + public static final int TARGET_SET_FOR_AUDIO_WITH_SMS_AND_CALL_WAITING = 9; + public static final int TARGET_SET_FOR_QTI_VIDEO_WITHOUT_SMS = 1000; public static final int TARGET_SET_FOR_QTI_VIDEO_WITH_SMS = 1001; @@ -71,12 +75,15 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente int targetResourceId; int targetDescriptionsResourceId; int directionDescriptionsResourceId; + int targetDisplayTextResourceId; int handleDrawableResourceId; - public TargetResources(int target, int descs, int directionDescs, int handle) { + public TargetResources(int target, int descs, int directionDescs, int displayText, int + handle) { targetResourceId = target; targetDescriptionsResourceId = descs; directionDescriptionsResourceId = directionDescs; + targetDisplayTextResourceId = displayText; handleDrawableResourceId = handle; } } @@ -87,66 +94,93 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente R.array.incoming_call_widget_audio_without_sms_and_block_targets, R.array.incoming_call_widget_audio_without_sms_and_block_target_descriptions, R.array.incoming_call_widget_audio_without_sms_and_block_direction_descriptions, + R.array.incoming_call_widget_audio_without_sms_and_block_display_text, R.drawable.ic_incall_audio_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_BLOCK, new TargetResources( R.array.incoming_call_widget_audio_without_sms_with_block_targets, R.array.incoming_call_widget_audio_without_sms_with_block_target_descriptions, R.array.incoming_call_widget_audio_without_sms_with_block_direction_descriptions, + R.array.incoming_call_widget_audio_without_sms_with_block_display_text, R.drawable.ic_incall_audio_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_AUDIO_WITH_SMS_WITHOUT_BLOCK, new TargetResources( R.array.incoming_call_widget_audio_with_sms_without_block_targets, R.array.incoming_call_widget_audio_with_sms_without_block_target_descriptions, R.array.incoming_call_widget_audio_with_sms_without_block_direction_descriptions, + R.array.incoming_call_widget_audio_with_sms_without_block_display_text, R.drawable.ic_incall_audio_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_AUDIO_WITH_SMS_AND_BLOCK, new TargetResources( R.array.incoming_call_widget_audio_with_sms_and_block_targets, R.array.incoming_call_widget_audio_with_sms_and_block_target_descriptions, R.array.incoming_call_widget_audio_with_sms_and_block_direction_descriptions, + R.array.incoming_call_widget_audio_with_sms_and_block_display_text, + R.drawable.ic_incall_audio_handle + )); + RESOURCE_LOOKUP.put(TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_CALL_WAITING, new TargetResources( + R.array.incoming_call_widget_audio_without_sms_with_call_waiting_targets, + R.array + .incoming_call_widget_audio_without_sms_with_call_waiting_target_descriptions, + R.array + .incoming_call_widget_audio_without_sms_with_call_waiting_direction_descriptions, + R.array.incoming_call_widget_audio_without_sms_with_call_waiting_display_text, + R.drawable.ic_incall_audio_handle + )); + RESOURCE_LOOKUP.put(TARGET_SET_FOR_AUDIO_WITH_SMS_AND_CALL_WAITING, new TargetResources( + R.array.incoming_call_widget_audio_with_sms_and_call_waiting_targets, + R.array.incoming_call_widget_audio_with_sms_and_call_waiting_target_descriptions, + R.array.incoming_call_widget_audio_with_sms_and_call_waiting_direction_descriptions, + R.array.incoming_call_widget_audio_with_sms_and_call_waiting_display_text, R.drawable.ic_incall_audio_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_VIDEO_WITHOUT_SMS_AND_BLOCK, new TargetResources( R.array.incoming_call_widget_video_without_sms_and_block_targets, R.array.incoming_call_widget_video_without_sms_and_block_target_descriptions, R.array.incoming_call_widget_video_without_sms_and_block_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_VIDEO_WITHOUT_SMS_WITH_BLOCK, new TargetResources( R.array.incoming_call_widget_video_without_sms_targets, R.array.incoming_call_widget_video_without_sms_target_descriptions, R.array.incoming_call_widget_video_without_sms_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_VIDEO_WITH_SMS, new TargetResources( R.array.incoming_call_widget_video_with_sms_targets, R.array.incoming_call_widget_video_with_sms_target_descriptions, R.array.incoming_call_widget_video_with_sms_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST, new TargetResources( R.array.incoming_call_widget_video_request_targets, R.array.incoming_call_widget_video_request_target_descriptions, R.array.incoming_call_widget_video_request_target_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_VIDEO_WITHOUT_SMS, new TargetResources( R.array.qti_incoming_call_widget_video_without_sms_targets, R.array.qti_incoming_call_widget_video_without_sms_target_descriptions, R.array.qti_incoming_call_widget_video_without_sms_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_VIDEO_WITH_SMS, new TargetResources( R.array.qti_incoming_call_widget_video_with_sms_targets, R.array.qti_incoming_call_widget_video_with_sms_target_descriptions, R.array.qti_incoming_call_widget_video_with_sms_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_VIDEO_ACCEPT_REJECT_REQUEST, new TargetResources( R.array.qti_incoming_call_widget_video_request_targets, R.array.qti_incoming_call_widget_video_request_target_descriptions, R.array.qti_incoming_call_widget_video_request_target_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_BIDIRECTIONAL_VIDEO_ACCEPT_REJECT_REQUEST, @@ -154,6 +188,7 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente R.array.qti_incoming_call_widget_bidirectional_video_accept_reject_request_targets, R.array.qti_incoming_call_widget_video_request_target_descriptions, R.array.qti_incoming_call_widget_video_request_target_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_VIDEO_TRANSMIT_ACCEPT_REJECT_REQUEST, @@ -161,6 +196,7 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente R.array.qti_incoming_call_widget_video_transmit_accept_reject_request_targets, R.array.qti_incoming_call_widget_video_transmit_request_target_descriptions, R.array.qti_incoming_call_widget_video_request_target_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_VIDEO_RECEIVE_ACCEPT_REJECT_REQUEST, @@ -168,18 +204,21 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente R.array.qti_incoming_call_widget_video_receive_accept_reject_request_targets, R.array.qti_incoming_call_widget_video_receive_request_target_descriptions, R.array.qti_incoming_call_widget_video_request_target_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_video_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_AUDIO_WITH_SMS, new TargetResources( R.array.qti_incoming_call_widget_audio_with_sms_targets, R.array.qti_incoming_call_widget_audio_with_sms_target_descriptions, R.array.qti_incoming_call_widget_audio_with_sms_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_audio_handle )); RESOURCE_LOOKUP.put(TARGET_SET_FOR_QTI_AUDIO_WITHOUT_SMS, new TargetResources( R.array.qti_incoming_call_widget_audio_without_sms_targets, R.array.qti_incoming_call_widget_audio_without_sms_target_descriptions, R.array.qti_incoming_call_widget_audio_without_sms_direction_descriptions, + R.array.incoming_call_widget_default_target_display_text, R.drawable.ic_incall_audio_handle )); } @@ -275,6 +314,7 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente mGlowpad.setTargetDescriptionsResourceId(res.targetDescriptionsResourceId); mGlowpad.setDirectionDescriptionsResourceId(res.directionDescriptionsResourceId); mGlowpad.setHandleDrawable(res.handleDrawableResourceId); + mGlowpad.setTargetDisplayTextResourceId(res.targetDisplayTextResourceId); mGlowpad.reset(false); } } @@ -442,7 +482,14 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente @Override public void onAnswer(int videoState, Context context) { Log.d(this, "onAnswer videoState=" + videoState + " context=" + context); - getPresenter().onAnswer(videoState, context); + getPresenter().onAnswer(videoState, context, TelecomManager + .CALL_WAITING_RESPONSE_NO_POPUP_END_CALL); + } + + @Override + public void onAnswer(int videoState, Context context, int callWaitingResponseType) { + Log.d(this, "onAnswer videoState=" + videoState + " context=" + context); + getPresenter().onAnswer(videoState, context, callWaitingResponseType); } @Override diff --git a/src/com/android/incallui/AnswerPresenter.java b/src/com/android/incallui/AnswerPresenter.java index 2fdccdb2..ddf6c0dc 100644 --- a/src/com/android/incallui/AnswerPresenter.java +++ b/src/com/android/incallui/AnswerPresenter.java @@ -439,7 +439,7 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi> return phoneId; } - public void onAnswer(int videoState, Context context) { + public void onAnswer(int videoState, Context context, int callWaitingResponseType) { int phoneId = getActivePhoneId(); Log.i(this, "onAnswer mCallId:" + mCallId + "phoneId:" + phoneId); if (mCallId == null || phoneId == -1) { @@ -452,7 +452,8 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi> InCallPresenter.getInstance().acceptUpgradeRequest(videoState, context); } else { Log.d(this, "onAnswer (answerCall) mCallId=" + mCallId + " videoState=" + videoState); - TelecomAdapter.getInstance().answerCall(mCall[phoneId].getId(), videoState); + TelecomAdapter.getInstance().answerCall(mCall[phoneId].getId(), videoState, + callWaitingResponseType); } } @@ -554,6 +555,9 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi> && mHasTextMessages; boolean withBlock = isBlockingEnabled(); + Call activeCall = CallList.getInstance().getActiveCall(); + boolean isCallWaiting = activeCall != null && activeCall != call; + // Only present the user with the option to answer as a video call if the incoming call is // a bi-directional video call. if (call.isVideoCall(getUi().getContext())) { @@ -575,14 +579,25 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi> } } else { if (withSms) { - getUi().showTargets(withBlock - ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_AND_BLOCK - : AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_WITHOUT_BLOCK); - getUi().configureMessageDialog(textMsgs); + if (isCallWaiting) { + getUi().showTargets(AnswerFragment + .TARGET_SET_FOR_AUDIO_WITH_SMS_AND_CALL_WAITING); + getUi().configureMessageDialog(textMsgs); + } else { + getUi().showTargets(withBlock + ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_AND_BLOCK + : AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_WITHOUT_BLOCK); + getUi().configureMessageDialog(textMsgs); + } } else { - getUi().showTargets(withBlock - ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_BLOCK - : AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_AND_BLOCK); + if (isCallWaiting) { + getUi().showTargets(AnswerFragment + .TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_CALL_WAITING); + } else { + getUi().showTargets(withBlock + ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_BLOCK + : AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_AND_BLOCK); + } } } } diff --git a/src/com/android/incallui/GlowPadWrapper.java b/src/com/android/incallui/GlowPadWrapper.java index eff43a1c..369bfe20 100644 --- a/src/com/android/incallui/GlowPadWrapper.java +++ b/src/com/android/incallui/GlowPadWrapper.java @@ -20,6 +20,7 @@ import android.content.Context; import android.os.Handler; import android.os.Message; import android.telecom.VideoProfile; +import android.telecom.TelecomManager; import android.util.AttributeSet; import android.view.View; @@ -149,6 +150,16 @@ public class GlowPadWrapper extends GlowPadView implements GlowPadView.OnTrigger mAnswerListener.onDeflect(getContext()); mTargetTriggered = true; break; + case R.drawable.ic_lockscreen_answer_hold_current: + mAnswerListener.onAnswer(VideoProfile.STATE_AUDIO_ONLY, getContext(), + TelecomManager.CALL_WAITING_RESPONSE_NO_POPUP_HOLD_CALL); + mTargetTriggered = true; + break; + case R.drawable.ic_lockscreen_answer_end_current: + mAnswerListener.onAnswer(VideoProfile.STATE_AUDIO_ONLY, getContext(), + TelecomManager.CALL_WAITING_RESPONSE_NO_POPUP_END_CALL); + mTargetTriggered = true; + break; default: // Code should never reach here. Log.e(this, "Trigger detected on unhandled resource. Skipping."); @@ -180,6 +191,7 @@ public class GlowPadWrapper extends GlowPadView implements GlowPadView.OnTrigger public interface AnswerListener { void onAnswer(int videoState, Context context); + void onAnswer(int videoState, Context context, int callWaitingResponseType); void onDecline(Context context); void onDeclineUpgradeRequest(Context context); void onText(); diff --git a/src/com/android/incallui/TelecomAdapter.java b/src/com/android/incallui/TelecomAdapter.java index 5de28f5f..ce5f75b6 100644 --- a/src/com/android/incallui/TelecomAdapter.java +++ b/src/com/android/incallui/TelecomAdapter.java @@ -68,6 +68,15 @@ final class TelecomAdapter implements InCallServiceListener { } } + void answerCall(String callId, int videoState, int callWaitingResponseType) { + android.telecom.Call call = getTelecommCallById(callId); + if (call != null) { + call.answer(videoState, callWaitingResponseType); + } else { + Log.e(this, "error answerCall, call not in call list: " + callId); + } + } + void rejectCall(String callId, boolean rejectWithMessage, String message) { android.telecom.Call call = getTelecommCallById(callId); if (call != null) { diff --git a/src/com/android/incallui/widget/multiwaveview/GlowPadView.java b/src/com/android/incallui/widget/multiwaveview/GlowPadView.java index 23200279..acbcdba6 100644 --- a/src/com/android/incallui/widget/multiwaveview/GlowPadView.java +++ b/src/com/android/incallui/widget/multiwaveview/GlowPadView.java @@ -29,6 +29,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -37,6 +38,10 @@ import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.widget.ExploreByTouchHelper; +import android.text.DynamicLayout; +import android.text.Layout.Alignment; +import android.text.SpannableStringBuilder; +import android.text.TextPaint; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -137,6 +142,14 @@ public class GlowPadView extends View { private AccessibilityNodeProvider mAccessibilityNodeProvider; private GlowpadExploreByTouchHelper mExploreByTouchHelper; + private ArrayList<String> mTargetDisplayText; + private boolean mShowHintText = false; + private int mTargetDisplayTextResourceId; + private TextPaint mTextPaint; + private DynamicLayout mTextLayout; + private SpannableStringBuilder mDisplayText; + private int mDisplayTextWidth; + private class AnimationBundle extends ArrayList<Tweener> { private static final long serialVersionUID = 0xA84D78726F127468L; private boolean mSuspended; @@ -274,12 +287,36 @@ public class GlowPadView extends View { setDirectionDescriptionsResourceId(resourceId); } + // Read array of display text + if (a.getValue(R.styleable.GlowPadView_targetDisplayText, outValue)) { + final int resourceId = outValue.resourceId; + if (resourceId == 0) { + throw new IllegalStateException("Must specify display text"); + } + setTargetDisplayTextResourceId(resourceId); + } + + mTextPaint = new TextPaint(); + mTextPaint.setColor(getResources().getColor(R.color.incoming_call_display_text)); + + // This SpannableStringBuilder is used as first parameter when creating DynamicLayout. + // DynamicLayout creates instance of internal static class DynamicLayout.ChangeWatcher + // and attaches it to SpannableStringBuilder. As a result, whenever + // SpannableStringBuilder is updated, DynamicLayout receives change notification + mDisplayText = new SpannableStringBuilder(""); + + mDisplayTextWidth = (int) (getRingWidth() - mMaxTargetWidth - getResources() + .getDimensionPixelSize(R.dimen.incoming_call_widget_display_text_side_offset)); + mTextPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen + .incoming_call_display_text_size)); + mTextLayout = new DynamicLayout(mDisplayText, mTextPaint, mDisplayTextWidth, + android.text.Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + // Use gravity attribute from LinearLayout //a = context.obtainStyledAttributes(attrs, R.styleable.LinearLayout); mGravity = a.getInt(R.styleable.GlowPadView_android_gravity, Gravity.TOP); a.recycle(); - setVibrateEnabled(mVibrationDuration > 0); assignDefaultsIfNeeded(); @@ -678,6 +715,18 @@ public class GlowPadView extends View { } /** + * Sets the resource id specifying the target display text + * + * @param resourceId The resource id. + */ + public void setTargetDisplayTextResourceId(int resourceId) { + mTargetDisplayTextResourceId = resourceId; + if (mTargetDisplayText != null) { + mTargetDisplayText.clear(); + } + } + + /** * Gets the resource id specifying the target descriptions for accessibility. * * @return The resource id. @@ -943,9 +992,11 @@ public class GlowPadView extends View { if (activeTarget != -1) { switchToState(STATE_SNAP, x,y); updateGlowPosition(x, y); + mShowHintText = true; } else { switchToState(STATE_TRACKING, x, y); updateGlowPosition(x, y); + mShowHintText = false; } if (mActiveTarget != activeTarget) { @@ -1196,6 +1247,18 @@ public class GlowPadView extends View { target.draw(canvas); } } + if (mShowHintText && mActiveTarget >= 0) { + String displayText = getTargetDisplayText(mActiveTarget); + + if (displayText != null && !TextUtils.equals(displayText, mDisplayText.toString())) { + mDisplayText.replace(0, mDisplayText.length(), displayText); + } + int textHeight = mTextLayout.getHeight(); + canvas.save(); + canvas.translate(mWaveCenterX-mDisplayTextWidth/2, mWaveCenterY-textHeight/2); + mTextLayout.draw(canvas); + canvas.restore(); + } mHandleDrawable.draw(canvas); } @@ -1253,6 +1316,22 @@ public class GlowPadView extends View { return mTargetDescriptions.get(index); } + private String getTargetDisplayText(int index) { + if (mTargetDisplayText == null || mTargetDisplayText.isEmpty()) { + mTargetDisplayText = loadDescriptions(mTargetDisplayTextResourceId); + if (mTargetDrawables.size() > mTargetDisplayText.size()) { + Log.w(TAG, "The number of target drawables must be" + + " less than or equal to the number of target display text."); + return null; + } + } + if (index < mTargetDisplayText.size()) { + return mTargetDisplayText.get(index); + } else { + return null; + } + } + private String getDirectionDescription(int index) { if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) { mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId); |