summaryrefslogtreecommitdiff
path: root/InCallUI/src/com/android/incallui
diff options
context:
space:
mode:
Diffstat (limited to 'InCallUI/src/com/android/incallui')
-rw-r--r--InCallUI/src/com/android/incallui/AccelerometerListener.java5
-rw-r--r--InCallUI/src/com/android/incallui/AnswerFragment.java12
-rw-r--r--InCallUI/src/com/android/incallui/AnswerPresenter.java109
-rw-r--r--InCallUI/src/com/android/incallui/AudioModeProvider.java2
-rw-r--r--InCallUI/src/com/android/incallui/BaseFragment.java13
-rw-r--r--InCallUI/src/com/android/incallui/Call.java51
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonFragment.java6
-rw-r--r--InCallUI/src/com/android/incallui/CallCardFragment.java136
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java12
-rw-r--r--InCallUI/src/com/android/incallui/CallList.java12
-rw-r--r--InCallUI/src/com/android/incallui/CircularRevealActivity.java169
-rw-r--r--InCallUI/src/com/android/incallui/CircularRevealFragment.java164
-rw-r--r--InCallUI/src/com/android/incallui/ConferenceManagerFragment.java32
-rw-r--r--InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java1
-rw-r--r--InCallUI/src/com/android/incallui/ConferenceParticipantListAdapter.java2
-rw-r--r--InCallUI/src/com/android/incallui/DialpadFragment.java33
-rw-r--r--InCallUI/src/com/android/incallui/FragmentDisplayManager.java23
-rw-r--r--InCallUI/src/com/android/incallui/InCallActivity.java310
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java261
-rw-r--r--InCallUI/src/com/android/incallui/InCallServiceImpl.java9
-rw-r--r--InCallUI/src/com/android/incallui/InCallUIMaterialColorMapUtils.java4
-rw-r--r--InCallUI/src/com/android/incallui/InCallVideoCallListener.java6
-rw-r--r--InCallUI/src/com/android/incallui/PostCharDialogFragment.java1
-rw-r--r--InCallUI/src/com/android/incallui/SmallerHitTargetTouchListener.java114
-rw-r--r--InCallUI/src/com/android/incallui/StatusBarNotifier.java3
-rw-r--r--InCallUI/src/com/android/incallui/TelecomAdapter.java2
-rw-r--r--InCallUI/src/com/android/incallui/VideoCallFragment.java70
-rw-r--r--InCallUI/src/com/android/incallui/VideoCallPresenter.java4
-rw-r--r--InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java2
-rw-r--r--InCallUI/src/com/android/incallui/widget/multiwaveview/PointCloud.java15
30 files changed, 808 insertions, 775 deletions
diff --git a/InCallUI/src/com/android/incallui/AccelerometerListener.java b/InCallUI/src/com/android/incallui/AccelerometerListener.java
index 1a7077866..ca8e7d0a4 100644
--- a/InCallUI/src/com/android/incallui/AccelerometerListener.java
+++ b/InCallUI/src/com/android/incallui/AccelerometerListener.java
@@ -120,7 +120,7 @@ public final class AccelerometerListener {
if (x == 0.0 || y == 0.0 || z == 0.0) return;
// magnitude of the acceleration vector projected onto XY plane
- final double xy = Math.sqrt(x*x + y*y);
+ final double xy = Math.hypot(x, y);
// compute the vertical angle
double angle = Math.atan2(xy, z);
// convert to degrees
@@ -131,16 +131,19 @@ public final class AccelerometerListener {
}
SensorEventListener mSensorListener = new SensorEventListener() {
+ @Override
public void onSensorChanged(SensorEvent event) {
onSensorEvent(event.values[0], event.values[1], event.values[2]);
}
+ @Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
};
Handler mHandler = new Handler() {
+ @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case ORIENTATION_CHANGED:
diff --git a/InCallUI/src/com/android/incallui/AnswerFragment.java b/InCallUI/src/com/android/incallui/AnswerFragment.java
index a066396c9..d1636371c 100644
--- a/InCallUI/src/com/android/incallui/AnswerFragment.java
+++ b/InCallUI/src/com/android/incallui/AnswerFragment.java
@@ -79,7 +79,7 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente
@Override
public AnswerPresenter createPresenter() {
- return new AnswerPresenter();
+ return InCallPresenter.getInstance().getAnswerPresenter();
}
@Override
@@ -111,11 +111,9 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente
}
@Override
- public void showAnswerUi(boolean show) {
- getView().setVisibility(show ? View.VISIBLE : View.GONE);
-
- Log.d(this, "Show answer UI: " + show);
- if (show) {
+ public void onShowAnswerUi(boolean shown) {
+ Log.d(this, "Show answer UI: " + shown);
+ if (shown) {
mGlowpad.startPing();
} else {
mGlowpad.stopPing();
@@ -277,7 +275,7 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresente
}
}
- public void dismissPendingDialogues() {
+ public void dismissPendingDialogs() {
if (isCannedResponsePopupShowing()) {
dismissCannedResponsePopup();
}
diff --git a/InCallUI/src/com/android/incallui/AnswerPresenter.java b/InCallUI/src/com/android/incallui/AnswerPresenter.java
index 208532572..32c7b9a18 100644
--- a/InCallUI/src/com/android/incallui/AnswerPresenter.java
+++ b/InCallUI/src/com/android/incallui/AnswerPresenter.java
@@ -17,16 +17,25 @@
package com.android.incallui;
import android.content.Context;
+
+import com.android.incallui.InCallPresenter.InCallState;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import java.util.List;
/**
- * Presenter for the Incoming call widget.
+ * Presenter for the Incoming call widget. The {@link AnswerPresenter} handles the logic during
+ * incoming calls. It is also in charge of responding to incoming calls, so there needs to be
+ * an instance alive so that it can receive onIncomingCall callbacks.
+ *
+ * An instance of {@link AnswerPresenter} is created by InCallPresenter at startup, registers
+ * for callbacks via InCallPresenter, and shows/hides the {@link AnswerFragment} via IncallActivity.
+ *
*/
public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
- implements CallList.CallUpdateListener, CallList.Listener {
+ implements CallList.CallUpdateListener, InCallPresenter.InCallUiListener,
+ InCallPresenter.IncomingCallListener {
private static final String TAG = AnswerPresenter.class.getSimpleName();
@@ -35,48 +44,38 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
private boolean mHasTextMessages = false;
@Override
- public void onUiReady(AnswerUi ui) {
- Log.d(this, "onUiReady ui=" + ui);
- super.onUiReady(ui);
-
- final CallList calls = CallList.getInstance();
- Call call;
- call = calls.getIncomingCall();
- if (call != null) {
- processIncomingCall(call);
- }
-
- Call videoCall = calls.getVideoUpgradeRequestCall();
- Log.d(this, "getVideoUpgradeRequestCall call =" + call);
-
- if (videoCall != null && call == null) {
- processVideoUpgradeRequestCall(videoCall);
+ public void onUiShowing(boolean showing) {
+ if (showing) {
+ final CallList calls = CallList.getInstance();
+ Call call;
+ call = calls.getIncomingCall();
+ if (call != null) {
+ processIncomingCall(call);
+ }
+ call = calls.getVideoUpgradeRequestCall();
+ Log.d(this, "getVideoUpgradeRequestCall call =" + call);
+ if (videoCall != null && call == null) {
+ processVideoUpgradeRequestCall(call);
+ }
+ } else {
+ // This is necessary because the activity can be destroyed while an incoming call exists.
+ // This happens when back button is pressed while incoming call is still being shown.
+ if (mCallId != null) {
+ CallList.getInstance().removeCallUpdateListener(mCallId, this);
+ }
}
-
- // Listen for incoming calls.
- calls.addListener(this);
}
@Override
- public void onUiUnready(AnswerUi ui) {
- super.onUiUnready(ui);
-
- CallList.getInstance().removeListener(this);
-
- // This is necessary because the activity can be destroyed while an incoming call exists.
- // This happens when back button is pressed while incoming call is still being shown.
- if (mCallId != null) {
- CallList.getInstance().removeCallUpdateListener(mCallId, this);
+ public void onIncomingCall(InCallState oldState, InCallState newState, Call call) {
+ Log.d(this, "onIncomingCall: " + this);
+ if (!call.getId().equals(mCallId)) {
+ // A new call is coming in.
+ processIncomingCall(call);
}
}
@Override
- public void onCallListChange(CallList callList) {
- Log.d(this, "onCallListChange callList=" + callList);
- // no-op
- }
-
- @Override
public void onDisconnect(Call call) {
// no-op
}
@@ -98,6 +97,7 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
// A new call is coming in.
processIncomingCall(call);
}
+>>>>>>> 8bef461
}
}
@@ -134,9 +134,20 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
CallList.getInstance().addCallUpdateListener(mCallId, this);
Log.d(TAG, "Showing incoming for call id: " + mCallId + " " + this);
- final List<String> textMsgs = CallList.getInstance().getTextResponses(call.getId());
- getUi().showAnswerUi(true);
- configureAnswerTargetsForSms(call, textMsgs);
+ if (showAnswerUi(true)) {
+ final List<String> textMsgs = CallList.getInstance().getTextResponses(call.getId());
+ configureAnswerTargetsForSms(call, textMsgs);
+ }
+ }
+
+ private boolean showAnswerUi(boolean show) {
+ final InCallActivity activity = InCallPresenter.getInstance().getActivity();
+ if (activity != null) {
+ activity.showAnswerFragment(show);
+ return true;
+ } else {
+ return false;
+ }
}
private void processVideoUpgradeRequestCall(Call call) {
@@ -155,14 +166,8 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
return;
}
- AnswerUi ui = getUi();
-
- if (ui == null) {
- Log.e(this, "Ui is null. Can't process upgrade request");
- return;
- }
- ui.showAnswerUi(true);
- ui.showTargets(getUiTarget(currentVideoState, modifyToVideoState));
+ showAnswerUi(true);
+ getUi().showTargets(getUiTarget(currentVideoState, modifyToVideoState));
}
@@ -200,9 +205,9 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
final Call incall = CallList.getInstance().getIncomingCall();
if (incall != null || isUpgradePending) {
- getUi().showAnswerUi(true);
+ showAnswerUi(true);
} else {
- getUi().showAnswerUi(false);
+ showAnswerUi(false);
}
mHasTextMessages = false;
@@ -261,6 +266,10 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
}
private void configureAnswerTargetsForSms(Call call, List<String> textMsgs) {
+ if (getUi() == null) {
+ return;
+ }
+
final Context context = getUi().getContext();
mHasTextMessages = textMsgs != null;
@@ -285,7 +294,7 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
}
interface AnswerUi extends Ui {
- public void showAnswerUi(boolean show);
+ public void onShowAnswerUi(boolean shown);
public void showTargets(int targetSet);
public void showMessageDialog();
public void configureMessageDialog(List<String> textResponses);
diff --git a/InCallUI/src/com/android/incallui/AudioModeProvider.java b/InCallUI/src/com/android/incallui/AudioModeProvider.java
index c823fda3c..a26766126 100644
--- a/InCallUI/src/com/android/incallui/AudioModeProvider.java
+++ b/InCallUI/src/com/android/incallui/AudioModeProvider.java
@@ -26,7 +26,7 @@ import java.util.List;
/**
* Proxy class for getting and setting the audio mode.
*/
-/* package */ class AudioModeProvider implements InCallPhoneListener {
+public class AudioModeProvider implements InCallPhoneListener {
static final int AUDIO_MODE_INVALID = 0;
diff --git a/InCallUI/src/com/android/incallui/BaseFragment.java b/InCallUI/src/com/android/incallui/BaseFragment.java
index 1ef3b1513..037c2455f 100644
--- a/InCallUI/src/com/android/incallui/BaseFragment.java
+++ b/InCallUI/src/com/android/incallui/BaseFragment.java
@@ -16,6 +16,7 @@
package com.android.incallui;
+import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
@@ -24,6 +25,8 @@ import android.os.Bundle;
*/
public abstract class BaseFragment<T extends Presenter<U>, U extends Ui> extends Fragment {
+ private static final String KEY_FRAGMENT_HIDDEN = "key_fragment_hidden";
+
private T mPresenter;
abstract T createPresenter();
@@ -54,6 +57,9 @@ public abstract class BaseFragment<T extends Presenter<U>, U extends Ui> extends
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mPresenter.onRestoreInstanceState(savedInstanceState);
+ if (savedInstanceState.getBoolean(KEY_FRAGMENT_HIDDEN)) {
+ getFragmentManager().beginTransaction().hide(this).commit();
+ }
}
}
@@ -67,5 +73,12 @@ public abstract class BaseFragment<T extends Presenter<U>, U extends Ui> extends
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mPresenter.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_FRAGMENT_HIDDEN, isHidden());
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ ((FragmentDisplayManager) activity).onFragmentAttached(this);
}
}
diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java
index 3d6f2032e..4ed7a49cf 100644
--- a/InCallUI/src/com/android/incallui/Call.java
+++ b/InCallUI/src/com/android/incallui/Call.java
@@ -17,11 +17,14 @@
package com.android.incallui;
import com.android.contacts.common.CallUtil;
+import com.android.contacts.common.testing.NeededForTesting;
import com.android.incallui.CallList.Listener;
import android.content.Context;
import android.hardware.camera2.CameraCharacteristics;
import android.net.Uri;
+import android.os.Bundle;
+import android.os.Trace;
import android.telecom.CallProperties;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
@@ -36,7 +39,8 @@ import java.util.Locale;
/**
* Describes a single call and its state.
*/
-public final class Call {
+@NeededForTesting
+public class Call {
/* Defines different states of this call */
public static class State {
public static final int INVALID = 0;
@@ -236,7 +240,7 @@ public final class Call {
}
};
- private final android.telecom.Call mTelecommCall;
+ private android.telecom.Call mTelecommCall;
private final String mId;
private int mState = State.INVALID;
private DisconnectCause mDisconnectCause;
@@ -250,6 +254,16 @@ public final class Call {
private InCallVideoCallListener mVideoCallListener;
+ /**
+ * Used only to create mock calls for testing
+ */
+ @NeededForTesting
+ Call(int state) {
+ mTelecommCall = null;
+ mId = ID_PREFIX + Integer.toString(sIdCounter++);
+ setState(state);
+ }
+
public Call(android.telecom.Call telecommCall) {
mTelecommCall = telecommCall;
mId = ID_PREFIX + Integer.toString(sIdCounter++);
@@ -270,6 +284,7 @@ public final class Call {
}
private void update() {
+ Trace.beginSection("Update");
int oldState = getState();
updateFromTelecommCall();
if (oldState != getState() && getState() == Call.State.DISCONNECTED) {
@@ -277,6 +292,7 @@ public final class Call {
} else {
CallList.getInstance().onUpdate(this);
}
+ Trace.endSection();
}
private void updateFromTelecommCall() {
@@ -329,6 +345,9 @@ public final class Call {
}
public String getNumber() {
+ if (mTelecommCall == null) {
+ return null;
+ }
if (mTelecommCall.getDetails().getGatewayInfo() != null) {
return mTelecommCall.getDetails().getGatewayInfo()
.getOriginalAddress().getSchemeSpecificPart();
@@ -337,11 +356,11 @@ public final class Call {
}
public Uri getHandle() {
- return mTelecommCall.getDetails().getHandle();
+ return mTelecommCall == null ? null : mTelecommCall.getDetails().getHandle();
}
public int getState() {
- if (mTelecommCall.getParent() != null) {
+ if (mTelecommCall != null && mTelecommCall.getParent() != null) {
return State.CONFERENCED;
} else {
return mState;
@@ -353,15 +372,21 @@ public final class Call {
}
public int getNumberPresentation() {
- return getTelecommCall().getDetails().getHandlePresentation();
+ return mTelecommCall == null ? null : mTelecommCall.getDetails().getHandlePresentation();
}
public int getCnapNamePresentation() {
- return getTelecommCall().getDetails().getCallerDisplayNamePresentation();
+ return mTelecommCall == null ? null
+ : mTelecommCall.getDetails().getCallerDisplayNamePresentation();
}
public String getCnapName() {
- return getTelecommCall().getDetails().getCallerDisplayName();
+ return mTelecommCall == null ? null
+ : getTelecommCall().getDetails().getCallerDisplayName();
+ }
+
+ public Bundle getExtras() {
+ return mTelecommCall == null ? null : mTelecommCall.getDetails().getExtras();
}
/** Returns call disconnect cause, defined by {@link DisconnectCause}. */
@@ -414,15 +439,15 @@ public final class Call {
}
public GatewayInfo getGatewayInfo() {
- return mTelecommCall.getDetails().getGatewayInfo();
+ return mTelecommCall == null ? null : mTelecommCall.getDetails().getGatewayInfo();
}
public PhoneAccountHandle getAccountHandle() {
- return mTelecommCall.getDetails().getAccountHandle();
+ return mTelecommCall == null ? null : mTelecommCall.getDetails().getAccountHandle();
}
public VideoCall getVideoCall() {
- return mTelecommCall.getVideoCall();
+ return mTelecommCall == null ? null : mTelecommCall.getVideoCall();
}
public List<String> getChildCallIds() {
@@ -521,6 +546,12 @@ public final class Call {
@Override
public String toString() {
+ if (mTelecommCall == null) {
+ // This should happen only in testing since otherwise we would never have a null
+ // Telecom call.
+ return String.valueOf(mId);
+ }
+
return String.format(Locale.US, "[%s, %s, %s, children:%s, parent:%s, conferenceable:%s, " +
"videoState:%d, callSubState:%d, mSessionModificationState:%d, VideoSettings:%s]",
mId,
diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java
index 8682d65e5..a9fafae18 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -327,10 +327,6 @@ public class CallButtonFragment
@Override
public void setEnabled(boolean isEnabled) {
mIsEnabled = isEnabled;
- View view = getView();
- if (view.getVisibility() != View.VISIBLE) {
- view.setVisibility(View.VISIBLE);
- }
mAudioButton.setEnabled(isEnabled);
mChangeToVoiceButton.setEnabled(isEnabled);
@@ -877,7 +873,7 @@ public class CallButtonFragment
public void displayDialpad(boolean value, boolean animate) {
mShowDialpadButton.setSelected(value);
if (getActivity() != null && getActivity() instanceof InCallActivity) {
- ((InCallActivity) getActivity()).displayDialpad(value, animate);
+ ((InCallActivity) getActivity()).showDialpadFragment(value, animate);
}
}
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 9f43502e0..7420ba90e 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -21,23 +21,23 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Point;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Trace;
import android.telecom.DisconnectCause;
import android.telecom.VideoProfile;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.text.format.DateUtils;
-import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
-import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
@@ -51,7 +51,6 @@ import android.widget.TextView;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.contacts.common.widget.FloatingActionButtonController;
-import com.android.incallui.service.PhoneNumberService;
import com.android.phone.common.animation.AnimUtils;
import java.util.List;
@@ -61,9 +60,9 @@ import java.util.List;
*/
public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPresenter.CallCardUi>
implements CallCardPresenter.CallCardUi {
+ private static final String TAG = "CallCardFragment";
private AnimatorSet mAnimatorSet;
- private int mRevealAnimationDuration;
private int mShrinkAnimationDuration;
private int mFabNormalDiameter;
private int mFabSmallDiameter;
@@ -109,13 +108,12 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
private ImageButton mFloatingActionButton;
private int mFloatingActionButtonVerticalOffset;
- // Cached DisplayMetrics density.
- private float mDensity;
-
private float mTranslationOffset;
private Animation mPulseAnimation;
private int mVideoAnimationDuration;
+ // Whether or not the call card is currently in the process of an animation
+ private boolean mIsAnimating;
private MaterialPalette mCurrentThemeColors;
@@ -133,7 +131,6 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mRevealAnimationDuration = getResources().getInteger(R.integer.reveal_animation_duration);
mShrinkAnimationDuration = getResources().getInteger(R.integer.shrink_animation_duration);
mVideoAnimationDuration = getResources().getInteger(R.integer.video_animation_duration);
mFloatingActionButtonVerticalOffset = getResources().getDimensionPixelOffset(
@@ -144,7 +141,6 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
R.dimen.end_call_floating_action_button_small_diameter);
}
-
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -157,13 +153,12 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- super.onCreateView(inflater, container, savedInstanceState);
-
- mDensity = getResources().getDisplayMetrics().density;
+ Trace.beginSection(TAG + " onCreate");
mTranslationOffset =
getResources().getDimensionPixelSize(R.dimen.call_card_anim_translate_y_offset);
-
- return inflater.inflate(R.layout.call_card_content, container, false);
+ final View view = inflater.inflate(R.layout.call_card_fragment, container, false);
+ Trace.endSection();
+ return view;
}
@Override
@@ -226,12 +221,15 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
@Override
public void onClick(View v) {
InCallActivity activity = (InCallActivity) getActivity();
- activity.showConferenceCallManager(true);
+ activity.showConferenceFragment(true);
}
});
mPrimaryName.setElegantTextHeight(false);
mCallStateLabel.setElegantTextHeight(false);
+
+ final LayoutTransition transition = mPrimaryCallInfo.getLayoutTransition();
+ transition.enableTransitionType(LayoutTransition.CHANGING);
}
@Override
@@ -370,7 +368,17 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
if (mIsLandscape) {
return getView().getWidth() - mPrimaryCallCardContainer.getWidth();
} else {
- return getView().getHeight() - mPrimaryCallCardContainer.getHeight();
+ final int callCardHeight;
+ // Retrieve the actual height of the call card, independent of whether or not the
+ // outgoing call animation is in progress. The animation does not run in landscape mode
+ // so this only needs to be done for portrait.
+ if (mPrimaryCallCardContainer.getTag(R.id.view_tag_callcard_actual_height) != null) {
+ callCardHeight = (int) mPrimaryCallCardContainer.getTag(
+ R.id.view_tag_callcard_actual_height);
+ } else {
+ callCardHeight = mPrimaryCallCardContainer.getHeight();
+ }
+ return getView().getHeight() - callCardHeight;
}
}
@@ -380,7 +388,7 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
mPrimaryName.setText(null);
} else {
mPrimaryName.setText(nameIsNumber
- ? PhoneNumberUtils.ttsSpanAsPhoneNumber(name)
+ ? PhoneNumberUtils.getPhoneTtsSpannable(name)
: name);
// Set direction of the name field
@@ -406,7 +414,7 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
mPhoneNumber.setText(null);
mPhoneNumber.setVisibility(View.GONE);
} else {
- mPhoneNumber.setText(PhoneNumberUtils.ttsSpanAsPhoneNumber(number));
+ mPhoneNumber.setText(PhoneNumberUtils.getPhoneTtsSpannable(number));
mPhoneNumber.setVisibility(View.VISIBLE);
mPhoneNumber.setTextDirection(View.TEXT_DIRECTION_LTR);
}
@@ -427,7 +435,6 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
public void setPrimary(String number, String name, boolean nameIsNumber, String label,
Drawable photo, boolean isSipCall) {
Log.d(this, "Setting primary call");
-
// set the name field.
setPrimaryName(name, nameIsNumber);
@@ -464,7 +471,7 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
mSecondaryCallConferenceCallIcon.setVisibility(isConference ? View.VISIBLE : View.GONE);
mSecondaryCallName.setText(nameIsNumber
- ? PhoneNumberUtils.ttsSpanAsPhoneNumber(name)
+ ? PhoneNumberUtils.getPhoneTtsSpannable(name)
: name);
if (hasProvider) {
mSecondaryCallProviderLabel.setText(providerLabel);
@@ -598,6 +605,10 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
mInCallMessageLabel.setVisibility(View.VISIBLE);
}
+ public boolean isAnimating() {
+ return mIsAnimating;
+ }
+
private void showInternetCallLabel(boolean show) {
if (show) {
final String label = getView().getContext().getString(
@@ -855,13 +866,16 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
}
}
- public void animateForNewOutgoingCall(final Point touchPoint,
- final boolean showCircularReveal) {
+ @Override
+ public void animateForNewOutgoingCall() {
final ViewGroup parent = (ViewGroup) mPrimaryCallCardContainer.getParent();
final ViewTreeObserver observer = getView().getViewTreeObserver();
- mPrimaryCallInfo.getLayoutTransition().disableTransitionType(LayoutTransition.CHANGING);
+ final LayoutTransition transition = mPrimaryCallInfo.getLayoutTransition();
+ transition.disableTransitionType(LayoutTransition.CHANGING);
+
+ mIsAnimating = true;
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
@@ -875,26 +889,39 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
final LayoutIgnoringListener listener = new LayoutIgnoringListener();
mPrimaryCallCardContainer.addOnLayoutChangeListener(listener);
- // Prepare the state of views before the circular reveal animation
+ // Prepare the state of views before the slide animation
final int originalHeight = mPrimaryCallCardContainer.getHeight();
+ mPrimaryCallCardContainer.setTag(R.id.view_tag_callcard_actual_height,
+ originalHeight);
mPrimaryCallCardContainer.setBottom(parent.getHeight());
// Set up FAB.
mFloatingActionButtonContainer.setVisibility(View.GONE);
mFloatingActionButtonController.setScreenWidth(parent.getWidth());
+
mCallButtonsContainer.setAlpha(0);
mCallStateLabel.setAlpha(0);
mPrimaryName.setAlpha(0);
mCallTypeLabel.setAlpha(0);
mCallNumberAndLabel.setAlpha(0);
- final Animator animator = getOutgoingCallAnimator(touchPoint,
- parent.getHeight(), originalHeight, showCircularReveal);
+ assignTranslateAnimation(mCallStateLabel, 1);
+ assignTranslateAnimation(mCallStateIcon, 1);
+ assignTranslateAnimation(mPrimaryName, 2);
+ assignTranslateAnimation(mCallNumberAndLabel, 3);
+ assignTranslateAnimation(mCallTypeLabel, 4);
+ assignTranslateAnimation(mCallButtonsContainer, 5);
+
+ final Animator animator = getShrinkAnimator(parent.getHeight(), originalHeight);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ mPrimaryCallCardContainer.setTag(R.id.view_tag_callcard_actual_height,
+ null);
setViewStatePostAnimation(listener);
+ mIsAnimating = false;
+ InCallPresenter.getInstance().onShrinkAnimationComplete();
}
});
animator.start();
@@ -902,7 +929,7 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
});
}
- public void onDialpadVisiblityChange(boolean isShown) {
+ public void onDialpadVisibilityChange(boolean isShown) {
mIsDialpadShowing = isShown;
updateFabPosition();
}
@@ -972,7 +999,7 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
}
observer.removeOnGlobalLayoutListener(this);
- onDialpadVisiblityChange(mIsDialpadShowing);
+ onDialpadVisibilityChange(mIsDialpadShowing);
}
});
}
@@ -983,19 +1010,12 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
* and then translated upwards together with the scrim.
*/
private Animator getShrinkAnimator(int startHeight, int endHeight) {
- final Animator shrinkAnimator =
+ final ObjectAnimator shrinkAnimator =
ObjectAnimator.ofInt(mPrimaryCallCardContainer, "bottom", startHeight, endHeight);
shrinkAnimator.setDuration(mShrinkAnimationDuration);
shrinkAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- assignTranslateAnimation(mCallStateLabel, 1);
- assignTranslateAnimation(mCallStateIcon, 1);
- assignTranslateAnimation(mPrimaryName, 2);
- assignTranslateAnimation(mCallNumberAndLabel, 3);
- assignTranslateAnimation(mCallTypeLabel, 4);
- assignTranslateAnimation(mCallButtonsContainer, 5);
-
mFloatingActionButton.setEnabled(true);
}
});
@@ -1003,42 +1023,9 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
return shrinkAnimator;
}
- private Animator getRevealAnimator(Point touchPoint) {
- final Activity activity = getActivity();
- final View view = activity.getWindow().getDecorView();
- final Display display = activity.getWindowManager().getDefaultDisplay();
- final Point size = new Point();
- display.getSize(size);
-
- int startX = size.x / 2;
- int startY = size.y / 2;
- if (touchPoint != null) {
- startX = touchPoint.x;
- startY = touchPoint.y;
- }
-
- final Animator valueAnimator = ViewAnimationUtils.createCircularReveal(view,
- startX, startY, 0, Math.max(size.x, size.y));
- valueAnimator.setDuration(mRevealAnimationDuration);
- return valueAnimator;
- }
-
- private Animator getOutgoingCallAnimator(Point touchPoint, int startHeight, int endHeight,
- boolean showCircularReveal) {
-
- final Animator shrinkAnimator = getShrinkAnimator(startHeight, endHeight);
-
- if (!showCircularReveal) {
- return shrinkAnimator;
- }
-
- final Animator revealAnimator = getRevealAnimator(touchPoint);
- final AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playSequentially(revealAnimator, shrinkAnimator);
- return animatorSet;
- }
-
private void assignTranslateAnimation(View view, int offset) {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ view.buildLayer();
view.setTranslationY(mTranslationOffset * offset);
view.animate().translationY(0).alpha(1).withLayer()
.setDuration(mShrinkAnimationDuration).setInterpolator(AnimUtils.EASE_IN);
@@ -1058,7 +1045,10 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
setViewStatePostAnimation(mCallStateIcon);
mPrimaryCallCardContainer.removeOnLayoutChangeListener(layoutChangeListener);
- mPrimaryCallInfo.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
+
+ final LayoutTransition transition = mPrimaryCallInfo.getLayoutTransition();
+ transition.enableTransitionType(LayoutTransition.CHANGING);
+
mFloatingActionButtonController.scaleIn(AnimUtils.NO_DELAY);
}
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index 7eae5c602..bd3694339 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -17,6 +17,8 @@
package com.android.incallui;
import android.Manifest;
+import android.app.Activity;
+import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -35,6 +37,7 @@ import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import com.android.incallui.CircularRevealFragment.OnCircularRevealCompleteListener;
import com.android.incallui.ContactInfoCache.ContactCacheEntry;
import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
import com.android.incallui.InCallPresenter.InCallDetailsListener;
@@ -119,6 +122,8 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
updateContactEntry(null, true);
}
}
+
+ onStateChange(null, InCallPresenter.getInstance().getInCallState(), CallList.getInstance());
}
@Override
@@ -250,7 +255,8 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
maybeShowManageConferenceCallButton();
- final boolean enableEndCallButton = Call.State.isConnectingOrConnected(callState) &&
+ final boolean enableEndCallButton = (Call.State.isConnectingOrConnected(callState)
+ || callState == Call.State.DISCONNECTING) &&
callState != Call.State.INCOMING && mPrimary != null;
// Hide the end call button instantly if we're receiving an incoming call.
getUi().setEndCallButtonEnabled(
@@ -678,9 +684,10 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
}
Log.i(this, "Disconnecting call: " + mPrimary);
+ final String callId = mPrimary.getId();
mPrimary.setState(Call.State.DISCONNECTING);
CallList.getInstance().onUpdate(mPrimary);
- TelecomAdapter.getInstance().disconnectCall(mPrimary.getId());
+ TelecomAdapter.getInstance().disconnectCall(callId);
}
private String getNumberFromHandle(Uri handle) {
@@ -750,5 +757,6 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
void showHdAudioIndicator(boolean visible);
void showManageConferenceCallButton(boolean visible);
boolean isManageConferenceVisible();
+ void animateForNewOutgoingCall();
}
}
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index f2d04cf11..9868aef50 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -16,11 +16,13 @@
package com.android.incallui;
+import com.android.contacts.common.testing.NeededForTesting;
import com.google.common.collect.Maps;
import com.google.common.base.Preconditions;
import android.os.Handler;
import android.os.Message;
+import android.os.Trace;
import android.telecom.DisconnectCause;
import android.telecom.Phone;
@@ -71,6 +73,7 @@ public class CallList implements InCallPhoneListener {
private Phone.Listener mPhoneListener = new Phone.Listener() {
@Override
public void onCallAdded(Phone phone, android.telecom.Call telecommCall) {
+ Trace.beginSection("onCallAdded");
Call call = new Call(telecommCall);
Log.d(this, "onCallAdded: callState=" + call.getState());
if (call.getState() == Call.State.INCOMING ||
@@ -79,6 +82,7 @@ public class CallList implements InCallPhoneListener {
} else {
onUpdate(call);
}
+ Trace.endSection();
}
@Override
public void onCallRemoved(Phone phone, android.telecom.Call telecommCall) {
@@ -93,9 +97,11 @@ public class CallList implements InCallPhoneListener {
};
/**
- * Private constructor. Instance should only be acquired through getInstance().
+ * USED ONLY FOR TESTING
+ * Testing-only constructor. Instance should only be acquired through getInstance().
*/
- private CallList() {
+ @NeededForTesting
+ CallList() {
}
@Override
@@ -147,8 +153,10 @@ public class CallList implements InCallPhoneListener {
* Called when a single call has changed.
*/
public void onUpdate(Call call) {
+ Trace.beginSection("onUpdate");
onUpdateCall(call);
notifyGenericListeners();
+ Trace.endSection();
}
public void notifyCallUpdateListeners(Call call) {
diff --git a/InCallUI/src/com/android/incallui/CircularRevealActivity.java b/InCallUI/src/com/android/incallui/CircularRevealActivity.java
deleted file mode 100644
index 7a9b7ccbf..000000000
--- a/InCallUI/src/com/android/incallui/CircularRevealActivity.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.incallui;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Outline;
-import android.graphics.Point;
-import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
-import android.view.Display;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.ViewOutlineProvider;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnPreDrawListener;
-
-import com.android.contacts.common.interactions.TouchPointManager;
-import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
-
-/**
- * Lightweight activity used to display a circular reveal while InCallActivity is starting up.
- * A BroadcastReceiver is used to listen to broadcasts from a LocalBroadcastManager to finish
- * the activity at suitable times.
- */
-public class CircularRevealActivity extends Activity {
- private static final int REVEAL_DURATION = 333;
- public static final String EXTRA_THEME_COLORS = "extra_theme_colors";
- public static final String ACTION_CLEAR_DISPLAY = "action_clear_display";
-
- final BroadcastReceiver mClearDisplayReceiver = new BroadcastReceiver( ) {
- @Override
- public void onReceive(Context context, Intent intent) {
- clearDisplay();
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- overridePendingTransition(0, 0);
- setContentView(R.layout.outgoing_call_animation);
- final Point touchPoint = getIntent().getParcelableExtra(TouchPointManager.TOUCH_POINT);
- final MaterialPalette palette = getIntent().getParcelableExtra(EXTRA_THEME_COLORS);
- setupDecorView(touchPoint, palette);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- if (!InCallPresenter.getInstance().isServiceBound()) {
- clearDisplay();
- }
- final IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_CLEAR_DISPLAY);
- LocalBroadcastManager.getInstance(this).registerReceiver(mClearDisplayReceiver, filter);
- }
-
- @Override
- protected void onStop() {
- LocalBroadcastManager.getInstance(this).unregisterReceiver(mClearDisplayReceiver);
- super.onStop();
- }
-
- private void setupDecorView(final Point touchPoint, MaterialPalette palette) {
- final View view = getWindow().getDecorView();
-
- // The circle starts from an initial size of 0 so clip it such that it is invisible. When
- // the animation later starts, this clip will be clobbered by the circular reveal clip.
- // See ViewAnimationUtils.createCircularReveal.
- view.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- // Using (0, 0, 0, 0) will not work since the outline will simply be treated as
- // an empty outline.
- outline.setOval(-1, -1, 0, 0);
- }
- });
- view.setClipToOutline(true);
-
- if (palette != null) {
- view.findViewById(R.id.outgoing_call_animation_circle).setBackgroundColor(
- palette.mPrimaryColor);
- getWindow().setStatusBarColor(palette.mSecondaryColor);
- }
-
- view.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- final ViewTreeObserver vto = view.getViewTreeObserver();
- if (vto.isAlive()) {
- vto.removeOnPreDrawListener(this);
- }
- final Animator animator = getRevealAnimator(touchPoint);
- // Since this animator is a RenderNodeAnimator (native animator), add an arbitary
- // start delay to force the onAnimationStart callback to happen later on the UI
- // thread. Otherwise it would happen right away inside animator.start()
- animator.setStartDelay(5);
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- InCallPresenter.getInstance().onCircularRevealStarted(
- CircularRevealActivity.this);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- view.setClipToOutline(false);
- super.onAnimationEnd(animation);
- }
- });
- animator.start();
- return false;
- }
- });
- }
-
- private void clearDisplay() {
- getWindow().getDecorView().setVisibility(View.INVISIBLE);
- finish();
- }
-
- @Override
- public void onBackPressed() {
- return;
- }
-
- public static void sendClearDisplayBroadcast(Context context) {
- LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(ACTION_CLEAR_DISPLAY));
- }
-
- private Animator getRevealAnimator(Point touchPoint) {
- final View view = getWindow().getDecorView();
- final Display display = getWindowManager().getDefaultDisplay();
- final Point size = new Point();
- display.getSize(size);
-
- int startX = size.x / 2;
- int startY = size.y / 2;
- if (touchPoint != null) {
- startX = touchPoint.x;
- startY = touchPoint.y;
- }
-
- final Animator valueAnimator = ViewAnimationUtils.createCircularReveal(view,
- startX, startY, 0, Math.max(size.x, size.y));
- valueAnimator.setDuration(REVEAL_DURATION);
- return valueAnimator;
- }
-}
diff --git a/InCallUI/src/com/android/incallui/CircularRevealFragment.java b/InCallUI/src/com/android/incallui/CircularRevealFragment.java
new file mode 100644
index 000000000..f8cc424fe
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/CircularRevealFragment.java
@@ -0,0 +1,164 @@
+/*
+ * 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.incallui;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.graphics.Outline;
+import android.graphics.Point;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+
+import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
+
+public class CircularRevealFragment extends Fragment {
+ static final String TAG = "CircularRevealFragment";
+
+ private Point mTouchPoint;
+ private OnCircularRevealCompleteListener mListener;
+ private boolean mAnimationStarted;
+
+ interface OnCircularRevealCompleteListener {
+ public void onCircularRevealComplete(FragmentManager fm);
+ }
+
+ public static void startCircularReveal(FragmentManager fm, Point touchPoint,
+ OnCircularRevealCompleteListener listener) {
+ if (fm.findFragmentByTag(TAG) == null) {
+ fm.beginTransaction().add(R.id.main,
+ new CircularRevealFragment(touchPoint, listener), TAG)
+ .commitAllowingStateLoss();
+ } else {
+ Log.w(TAG, "An instance of CircularRevealFragment already exists");
+ }
+ }
+
+ public static void endCircularReveal(FragmentManager fm) {
+ final Fragment fragment = fm.findFragmentByTag(TAG);
+ if (fragment != null) {
+ fm.beginTransaction().remove(fragment).commitAllowingStateLoss();
+ }
+ }
+
+ /**
+ * Empty constructor used only by the {@link FragmentManager}.
+ */
+ public CircularRevealFragment() {}
+
+ public CircularRevealFragment(Point touchPoint, OnCircularRevealCompleteListener listener) {
+ mTouchPoint = touchPoint;
+ mListener = listener;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (!mAnimationStarted) {
+ // Only run the animation once for each instance of the fragment
+ startOutgoingAnimation(InCallPresenter.getInstance().getThemeColors());
+ }
+ mAnimationStarted = true;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.outgoing_call_animation, container, false);
+ }
+
+ public void startOutgoingAnimation(MaterialPalette palette) {
+ final Activity activity = getActivity();
+ if (activity == null) {
+ Log.w(this, "Asked to do outgoing call animation when not attached");
+ return;
+ }
+
+ final View view = activity.getWindow().getDecorView();
+
+ // The circle starts from an initial size of 0 so clip it such that it is invisible.
+ // Otherwise the first frame is drawn with a fully opaque screen which causes jank. When
+ // the animation later starts, this clip will be clobbered by the circular reveal clip.
+ // See ViewAnimationUtils.createCircularReveal.
+ view.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ // Using (0, 0, 0, 0) will not work since the outline will simply be treated as
+ // an empty outline.
+ outline.setOval(-1, -1, 0, 0);
+ }
+ });
+ view.setClipToOutline(true);
+
+ if (palette != null) {
+ view.findViewById(R.id.outgoing_call_animation_circle).setBackgroundColor(
+ palette.mPrimaryColor);
+ activity.getWindow().setStatusBarColor(palette.mSecondaryColor);
+ }
+
+ view.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ final ViewTreeObserver vto = view.getViewTreeObserver();
+ if (vto.isAlive()) {
+ vto.removeOnPreDrawListener(this);
+ }
+ final Animator animator = getRevealAnimator(mTouchPoint);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ view.setClipToOutline(false);
+ if (mListener != null) {
+ mListener.onCircularRevealComplete(getFragmentManager());
+ }
+ }
+ });
+ animator.start();
+ return false;
+ }
+ });
+ }
+
+ private Animator getRevealAnimator(Point touchPoint) {
+ final Activity activity = getActivity();
+ final View view = activity.getWindow().getDecorView();
+ final Display display = activity.getWindowManager().getDefaultDisplay();
+ final Point size = new Point();
+ display.getSize(size);
+
+ int startX = size.x / 2;
+ int startY = size.y / 2;
+ if (touchPoint != null) {
+ startX = touchPoint.x;
+ startY = touchPoint.y;
+ }
+
+ final Animator valueAnimator = ViewAnimationUtils.createCircularReveal(view,
+ startX, startY, 0, Math.max(size.x, size.y));
+ valueAnimator.setDuration(getResources().getInteger(R.integer.reveal_animation_duration));
+ return valueAnimator;
+ }
+}
diff --git a/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java b/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java
index 163954b2d..6b232c934 100644
--- a/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java
+++ b/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java
@@ -29,22 +29,25 @@ import com.android.contacts.common.ContactPhotoManager;
import java.util.List;
/**
- * Fragment for call control buttons
+ * Fragment that allows the user to manage a conference call.
*/
public class ConferenceManagerFragment
extends BaseFragment<ConferenceManagerPresenter,
ConferenceManagerPresenter.ConferenceManagerUi>
implements ConferenceManagerPresenter.ConferenceManagerUi {
+ private static final String KEY_IS_VISIBLE = "key_conference_is_visible";
+
private ListView mConferenceParticipantList;
private int mActionBarElevation;
private ContactPhotoManager mContactPhotoManager;
private LayoutInflater mInflater;
private ConferenceParticipantListAdapter mConferenceParticipantListAdapter;
+ private boolean mIsVisible;
+ private boolean mIsRecreating;
@Override
ConferenceManagerPresenter createPresenter() {
- // having a singleton instance.
return new ConferenceManagerPresenter();
}
@@ -56,6 +59,10 @@ public class ConferenceManagerFragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (savedInstanceState != null) {
+ mIsRecreating = true;
+ mIsVisible = savedInstanceState.getBoolean(KEY_IS_VISIBLE);
+ }
}
@Override
@@ -75,15 +82,23 @@ public class ConferenceManagerFragment
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
+ public void onResume() {
+ super.onResume();
+ if (mIsRecreating) {
+ onVisibilityChanged(mIsVisible);
+ }
}
@Override
- public void setVisible(boolean on) {
- ActionBar actionBar = getActivity().getActionBar();
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putBoolean(KEY_IS_VISIBLE, mIsVisible);
+ super.onSaveInstanceState(outState);
+ }
- if (on) {
+ public void onVisibilityChanged(boolean isVisible) {
+ mIsVisible = isVisible;
+ ActionBar actionBar = getActivity().getActionBar();
+ if (isVisible) {
actionBar.setTitle(R.string.manageConferenceLabel);
actionBar.setElevation(mActionBarElevation);
actionBar.setHideOffset(0);
@@ -91,13 +106,10 @@ public class ConferenceManagerFragment
final CallList calls = CallList.getInstance();
getPresenter().init(getActivity(), calls);
- getView().setVisibility(View.VISIBLE);
// Request focus on the list of participants for accessibility purposes. This ensures
// that once the list of participants is shown, the first participant is announced.
mConferenceParticipantList.requestFocus();
} else {
- getView().setVisibility(View.GONE);
-
actionBar.setElevation(0);
actionBar.setHideOffset(actionBar.getHeight());
}
diff --git a/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java b/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java
index 86fc18ff3..6fb6e5dda 100644
--- a/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java
+++ b/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java
@@ -137,7 +137,6 @@ public class ConferenceManagerPresenter
}
public interface ConferenceManagerUi extends Ui {
- void setVisible(boolean on);
boolean isFragmentVisible();
void update(Context context, List<Call> participants, boolean parentCanSeparate);
void refreshCall(Call call);
diff --git a/InCallUI/src/com/android/incallui/ConferenceParticipantListAdapter.java b/InCallUI/src/com/android/incallui/ConferenceParticipantListAdapter.java
index 7825dc1ad..62c1214c7 100644
--- a/InCallUI/src/com/android/incallui/ConferenceParticipantListAdapter.java
+++ b/InCallUI/src/com/android/incallui/ConferenceParticipantListAdapter.java
@@ -418,7 +418,7 @@ public class ConferenceParticipantListAdapter extends BaseAdapter {
numberTypeTextView.setVisibility(View.GONE);
} else {
numberTextView.setVisibility(View.VISIBLE);
- numberTextView.setText(PhoneNumberUtils.ttsSpanAsPhoneNumber(callerNumber));
+ numberTextView.setText(PhoneNumberUtils.getPhoneTtsSpannable(callerNumber));
numberTypeTextView.setVisibility(View.VISIBLE);
numberTypeTextView.setText(callerNumberType);
}
diff --git a/InCallUI/src/com/android/incallui/DialpadFragment.java b/InCallUI/src/com/android/incallui/DialpadFragment.java
index da3f0cb74..5a02b8b0e 100644
--- a/InCallUI/src/com/android/incallui/DialpadFragment.java
+++ b/InCallUI/src/com/android/incallui/DialpadFragment.java
@@ -29,13 +29,11 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.phone.common.dialpad.DialpadKeyButton;
import com.android.phone.common.dialpad.DialpadView;
@@ -83,30 +81,6 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadPrese
}
}
- /**
- * LinearLayout that always returns true for onHoverEvent callbacks, to fix
- * problems with accessibility due to the dialpad overlaying other fragments.
- */
- public static class HoverIgnoringLinearLayout extends LinearLayout {
-
- public HoverIgnoringLinearLayout(Context context) {
- super(context);
- }
-
- public HoverIgnoringLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public HoverIgnoringLinearLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- return true;
- }
- }
-
private EditText mDtmfDialerField;
/** Hash Map to map a view id to a character*/
@@ -445,11 +419,6 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadPrese
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View parent = inflater.inflate(
@@ -514,7 +483,7 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadPrese
* @param text Text to set Dialpad EditText to.
*/
public void setDtmfText(String text) {
- mDtmfDialerField.setText(PhoneNumberUtils.ttsSpanAsPhoneNumber(text));
+ mDtmfDialerField.setText(PhoneNumberUtils.getPhoneTtsSpannable(text));
}
@Override
diff --git a/InCallUI/src/com/android/incallui/FragmentDisplayManager.java b/InCallUI/src/com/android/incallui/FragmentDisplayManager.java
new file mode 100644
index 000000000..045d999a0
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/FragmentDisplayManager.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 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.incallui;
+
+import android.app.Fragment;
+
+interface FragmentDisplayManager {
+ public void onFragmentAttached(Fragment fragment);
+}
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 873c288a4..1283177d6 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -18,7 +18,10 @@ package com.android.incallui;
import android.app.ActionBar;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlertDialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
@@ -27,14 +30,11 @@ import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Point;
-import android.net.Uri;
import android.os.Bundle;
+import android.os.Trace;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
-import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.animation.Animation;
@@ -48,8 +48,6 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.phone.common.animation.AnimUtils;
import com.android.phone.common.animation.AnimationListenerAdapter;
import com.android.contacts.common.interactions.TouchPointManager;
-import com.android.contacts.common.util.MaterialColorMapUtils;
-import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment.SelectPhoneAccountListener;
import com.android.incallui.Call.State;
@@ -59,14 +57,21 @@ import java.util.List;
import java.util.Locale;
/**
- * Phone app "in call" screen.
+ * Main activity that the user interacts with while in a live call.
*/
-public class InCallActivity extends Activity {
+public class InCallActivity extends Activity implements FragmentDisplayManager {
+
+ public static final String TAG = InCallActivity.class.getSimpleName();
public static final String SHOW_DIALPAD_EXTRA = "InCallActivity.show_dialpad";
public static final String DIALPAD_TEXT_EXTRA = "InCallActivity.dialpad_text";
public static final String NEW_OUTGOING_CALL_EXTRA = "InCallActivity.new_outgoing_call";
- public static final String SHOW_CIRCULAR_REVEAL_EXTRA = "InCallActivity.show_circular_reveal";
+
+ private static final String TAG_DIALPAD_FRAGMENT = "tag_dialpad_fragment";
+ private static final String TAG_CONFERENCE_FRAGMENT = "tag_conference_manager_fragment";
+ private static final String TAG_CALLCARD_FRAGMENT = "tag_callcard_fragment";
+ private static final String TAG_ANSWER_FRAGMENT = "tag_answer_fragment";
+ private static final String TAG_SELECT_ACCT_FRAGMENT = "tag_select_acct_fragment";
private CallButtonFragment mCallButtonFragment;
private CallCardFragment mCallCardFragment;
@@ -100,7 +105,20 @@ public class InCallActivity extends Activity {
AnimationListenerAdapter mSlideOutListener = new AnimationListenerAdapter() {
@Override
public void onAnimationEnd(Animation animation) {
- showDialpad(false);
+ showFragment(TAG_DIALPAD_FRAGMENT, false, true);
+ }
+ };
+
+ private SelectPhoneAccountListener mSelectAcctListener = new SelectPhoneAccountListener() {
+ @Override
+ public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle,
+ boolean setDefault) {
+ InCallPresenter.getInstance().handleAccountSelection(selectedAccountHandle,
+ setDefault);
+ }
+ @Override
+ public void onDialogDismissed() {
+ InCallPresenter.getInstance().cancelAccountSelection();
}
};
@@ -135,11 +153,8 @@ public class InCallActivity extends Activity {
// TODO(klp): Do we need to add this back when prox sensor is not available?
// lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
- // Inflate everything in incall_screen.xml and add it to the screen.
setContentView(R.layout.incall_screen);
- initializeInCall();
-
internalResolveIntent(getIntent());
mIsLandscape = getResources().getConfiguration().orientation ==
@@ -171,13 +186,21 @@ public class InCallActivity extends Activity {
mShowDialpadRequested = icicle.getBoolean(SHOW_DIALPAD_EXTRA);
mAnimateDialpadOnShow = false;
mDtmfText = icicle.getString(DIALPAD_TEXT_EXTRA);
+
+ SelectPhoneAccountDialogFragment dialogFragment = (SelectPhoneAccountDialogFragment)
+ getFragmentManager().findFragmentByTag(TAG_SELECT_ACCT_FRAGMENT);
+ if (dialogFragment != null) {
+ dialogFragment.setListener(mSelectAcctListener);
+ }
}
Log.d(this, "onCreate(): exit");
}
@Override
protected void onSaveInstanceState(Bundle out) {
- out.putBoolean(SHOW_DIALPAD_EXTRA, mCallButtonFragment.isDialpadVisible());
+ // TODO: The dialpad fragment should handle this as part of its own state
+ out.putBoolean(SHOW_DIALPAD_EXTRA,
+ mCallButtonFragment != null && mCallButtonFragment.isDialpadVisible());
if (mDialpadFragment != null) {
out.putString(DIALPAD_TEXT_EXTRA, mDialpadFragment.getDtmfText());
}
@@ -262,37 +285,45 @@ public class InCallActivity extends Activity {
}
/**
+ * When fragments have a parent fragment, onAttachFragment is not called on the parent
+ * activity. To fix this, register our own callback instead that is always called for
+ * all fragments.
+ *
+ * @see {@link BaseFragment#onAttach(Activity)}
+ */
+ @Override
+ public void onFragmentAttached(Fragment fragment) {
+ if (fragment instanceof DialpadFragment) {
+ mDialpadFragment = (DialpadFragment) fragment;
+ } else if (fragment instanceof AnswerFragment) {
+ mAnswerFragment = (AnswerFragment) fragment;
+ } else if (fragment instanceof CallCardFragment) {
+ mCallCardFragment = (CallCardFragment) fragment;
+ mChildFragmentManager = mCallCardFragment.getChildFragmentManager();
+ } else if (fragment instanceof ConferenceManagerFragment) {
+ mConferenceManagerFragment = (ConferenceManagerFragment) fragment;
+ } else if (fragment instanceof CallButtonFragment) {
+ mCallButtonFragment = (CallButtonFragment) fragment;
+ }
+ }
+
+ /**
* Returns true when theActivity is in foreground (between onResume and onPause).
*/
/* package */ boolean isForegroundActivity() {
return mIsForegroundActivity;
}
- private boolean hasPendingErrorDialog() {
- return mDialog != null;
+ private boolean hasPendingDialogs() {
+ return mDialog != null || (mAnswerFragment != null && mAnswerFragment.hasPendingDialogs());
}
- /**
- * Dismisses the in-call screen.
- *
- * We never *really* finish() the InCallActivity, since we don't want to get destroyed and then
- * have to be re-created from scratch for the next call. Instead, we just move ourselves to the
- * back of the activity stack.
- *
- * This also means that we'll no longer be reachable via the BACK button (since moveTaskToBack()
- * puts us behind the Home app, but the home app doesn't allow the BACK key to move you any
- * farther down in the history stack.)
- *
- * (Since the Phone app itself is never killed, this basically means that we'll keep a single
- * InCallActivity instance around for the entire uptime of the device. This noticeably improves
- * the UI responsiveness for incoming calls.)
- */
@Override
public void finish() {
Log.i(this, "finish(). Dialog showing: " + (mDialog != null));
// skip finish if we are still showing a dialog.
- if (!hasPendingErrorDialog() && !mAnswerFragment.hasPendingDialogs()) {
+ if (!hasPendingDialogs()) {
super.finish();
}
}
@@ -325,22 +356,23 @@ public class InCallActivity extends Activity {
// BACK is also used to exit out of any "special modes" of the
// in-call UI:
- if (!mConferenceManagerFragment.isVisible() && !mCallCardFragment.isVisible()) {
+ if ((mConferenceManagerFragment == null || !mConferenceManagerFragment.isVisible())
+ && !mCallCardFragment.isVisible()) {
return;
}
if (mDialpadFragment != null && mDialpadFragment.isVisible()) {
mCallButtonFragment.displayDialpad(false /* show */, true /* animate */);
return;
- } else if (mConferenceManagerFragment.isVisible()) {
- showConferenceCallManager(false);
+ } else if (mConferenceManagerFragment != null && mConferenceManagerFragment.isVisible()) {
+ showConferenceFragment(false);
return;
}
// Always disable the Back key while an incoming call is ringing
final Call call = CallList.getInstance().getIncomingCall();
if (call != null) {
- Log.d(this, "Consume Back press for an incoming call");
+ Log.i(this, "Consume Back press for an incoming call");
return;
}
@@ -436,13 +468,6 @@ public class InCallActivity extends Activity {
// key events to the DTMFDialer's onDialerKeyDown.
if (mDialpadFragment != null && mDialpadFragment.isVisible()) {
return mDialpadFragment.onDialerKeyDown(event);
-
- // TODO: If the dialpad isn't currently visible, maybe
- // consider automatically bringing it up right now?
- // (Just to make sure the user sees the digits widget...)
- // But this probably isn't too critical since it's awkward to
- // use the hard keyboard while in-call in the first place,
- // especially now that the in-call UI is portrait-only...
}
return false;
@@ -479,10 +504,13 @@ public class InCallActivity extends Activity {
return mCallCardFragment;
}
+ public AnswerFragment getAnswerFragment() {
+ return mAnswerFragment;
+ }
+
private void internalResolveIntent(Intent intent) {
final String action = intent.getAction();
-
- if (action.equals(intent.ACTION_MAIN)) {
+ if (action.equals(Intent.ACTION_MAIN)) {
// This action is the normal way to bring up the in-call UI.
//
// But we do check here for one extra that can come along with the
@@ -499,6 +527,7 @@ public class InCallActivity extends Activity {
relaunchedFromDialer(showDialpad);
}
+ boolean newOutgoingCall = false;
if (intent.getBooleanExtra(NEW_OUTGOING_CALL_EXTRA, false)) {
intent.removeExtra(NEW_OUTGOING_CALL_EXTRA);
Call call = CallList.getInstance().getOutgoingCall();
@@ -526,12 +555,9 @@ public class InCallActivity extends Activity {
}
}
- // This is only true in the case where an outgoing call is initiated by tapping
- // on the "Select account dialog", in which case we skip the initial animation. In
- // most other cases the circular reveal is done by OutgoingCallAnimationActivity.
- final boolean showCircularReveal =
- intent.getBooleanExtra(SHOW_CIRCULAR_REVEAL_EXTRA, false);
- mCallCardFragment.animateForNewOutgoingCall(touchPoint, showCircularReveal);
+ // Start animation for new outgoing call
+ CircularRevealFragment.startCircularReveal(getFragmentManager(), touchPoint,
+ InCallPresenter.getInstance());
// InCallActivity is responsible for disconnecting a new outgoing call if there
// is no way of making it (i.e. no valid call capable accounts)
@@ -540,11 +566,12 @@ public class InCallActivity extends Activity {
}
dismissKeyguard(true);
+ newOutgoingCall = true;
}
Call pendingAccountSelectionCall = CallList.getInstance().getWaitingForAccountCall();
if (pendingAccountSelectionCall != null) {
- mCallCardFragment.setVisible(false);
+ showCallCardFragment(false);
Bundle extras = pendingAccountSelectionCall
.getTelecommCall().getDetails().getExtras();
@@ -556,24 +583,12 @@ public class InCallActivity extends Activity {
phoneAccountHandles = new ArrayList<>();
}
- SelectPhoneAccountListener listener = new SelectPhoneAccountListener() {
- @Override
- public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle,
- boolean setDefault) {
- InCallPresenter.getInstance().handleAccountSelection(selectedAccountHandle,
- setDefault);
- }
- @Override
- public void onDialogDismissed() {
- InCallPresenter.getInstance().cancelAccountSelection();
- }
- };
-
- SelectPhoneAccountDialogFragment.showAccountDialog(getFragmentManager(),
+ DialogFragment dialogFragment = SelectPhoneAccountDialogFragment.newInstance(
R.string.select_phone_account_for_calls, true, phoneAccountHandles,
- listener);
- } else {
- mCallCardFragment.setVisible(true);
+ mSelectAcctListener);
+ dialogFragment.show(getFragmentManager(), TAG_SELECT_ACCT_FRAGMENT);
+ } else if (!newOutgoingCall) {
+ showCallCardFragment(true);
}
return;
@@ -594,40 +609,6 @@ public class InCallActivity extends Activity {
}
}
- private void initializeInCall() {
- if (mCallCardFragment == null) {
- mCallCardFragment = (CallCardFragment) getFragmentManager()
- .findFragmentById(R.id.callCardFragment);
- }
-
- mChildFragmentManager = mCallCardFragment.getChildFragmentManager();
-
- if (mCallButtonFragment == null) {
- mCallButtonFragment = (CallButtonFragment) mChildFragmentManager
- .findFragmentById(R.id.callButtonFragment);
- mCallButtonFragment.getView().setVisibility(View.INVISIBLE);
- }
-
- if (mAnswerFragment == null) {
- mAnswerFragment = (AnswerFragment) mChildFragmentManager
- .findFragmentById(R.id.answerFragment);
- }
-
- if (mConferenceManagerFragment == null) {
- mConferenceManagerFragment = (ConferenceManagerFragment) getFragmentManager()
- .findFragmentById(R.id.conferenceManagerFragment);
- mConferenceManagerFragment.getView().setVisibility(View.INVISIBLE);
- }
- }
-
- /**
- * Simulates a user click to hide the dialpad. This will update the UI to show the call card,
- * update the checked state of the dialpad button, and update the proximity sensor state.
- */
- public void hideDialpadForDisconnect() {
- mCallButtonFragment.displayDialpad(false /* show */, true /* animate */);
- }
-
public void dismissKeyguard(boolean dismiss) {
if (mDismissKeyguard == dismiss) {
return;
@@ -640,67 +621,134 @@ public class InCallActivity extends Activity {
}
}
- private void showDialpad(boolean showDialpad) {
- // If the dialpad is being shown and it has not already been loaded, replace the dialpad
- // placeholder with the actual fragment before continuing.
- if (mDialpadFragment == null && showDialpad) {
- final FragmentTransaction loadTransaction = mChildFragmentManager.beginTransaction();
- View fragmentContainer = findViewById(R.id.dialpadFragmentContainer);
- mDialpadFragment = new DialpadFragment();
- loadTransaction.replace(fragmentContainer.getId(), mDialpadFragment,
- DialpadFragment.class.getName());
- loadTransaction.commitAllowingStateLoss();
- mChildFragmentManager.executePendingTransactions();
+ private void showFragment(String tag, boolean show, boolean executeImmediately) {
+ Trace.beginSection("showFragment - " + tag);
+ final FragmentManager fm = getFragmentManagerForTag(tag);
+
+ if (fm == null) {
+ Log.w(TAG, "Fragment manager is null for : " + tag);
+ return;
+ }
+
+ Fragment fragment = fm.findFragmentByTag(tag);
+ if (!show && fragment == null) {
+ // Nothing to show, so bail early.
+ return;
}
- final FragmentTransaction ft = mChildFragmentManager.beginTransaction();
- if (showDialpad) {
- ft.show(mDialpadFragment);
+ final FragmentTransaction transaction = fm.beginTransaction();
+ if (show) {
+ if (fragment == null) {
+ fragment = createNewFragmentForTag(tag);
+ transaction.add(getContainerIdForFragment(tag), fragment, tag);
+ } else {
+ transaction.show(fragment);
+ }
} else {
- ft.hide(mDialpadFragment);
+ transaction.hide(fragment);
+ }
+
+ transaction.commitAllowingStateLoss();
+ if (executeImmediately) {
+ fm.executePendingTransactions();
}
- ft.commitAllowingStateLoss();
+ Trace.endSection();
}
- public void displayDialpad(boolean showDialpad, boolean animate) {
+ private Fragment createNewFragmentForTag(String tag) {
+ if (TAG_DIALPAD_FRAGMENT.equals(tag)) {
+ mDialpadFragment = new DialpadFragment();
+ return mDialpadFragment;
+ } else if (TAG_ANSWER_FRAGMENT.equals(tag)) {
+ mAnswerFragment = new AnswerFragment();
+ return mAnswerFragment;
+ } else if (TAG_CONFERENCE_FRAGMENT.equals(tag)) {
+ mConferenceManagerFragment = new ConferenceManagerFragment();
+ return mConferenceManagerFragment;
+ } else if (TAG_CALLCARD_FRAGMENT.equals(tag)) {
+ mCallCardFragment = new CallCardFragment();
+ return mCallCardFragment;
+ }
+ throw new IllegalStateException("Unexpected fragment: " + tag);
+ }
+
+ private FragmentManager getFragmentManagerForTag(String tag) {
+ if (TAG_DIALPAD_FRAGMENT.equals(tag)) {
+ return mChildFragmentManager;
+ } else if (TAG_ANSWER_FRAGMENT.equals(tag)) {
+ return mChildFragmentManager;
+ } else if (TAG_CONFERENCE_FRAGMENT.equals(tag)) {
+ return getFragmentManager();
+ } else if (TAG_CALLCARD_FRAGMENT.equals(tag)) {
+ return getFragmentManager();
+ }
+ throw new IllegalStateException("Unexpected fragment: " + tag);
+ }
+
+ private int getContainerIdForFragment(String tag) {
+ if (TAG_DIALPAD_FRAGMENT.equals(tag)) {
+ return R.id.answer_and_dialpad_container;
+ } else if (TAG_ANSWER_FRAGMENT.equals(tag)) {
+ return R.id.answer_and_dialpad_container;
+ } else if (TAG_CONFERENCE_FRAGMENT.equals(tag)) {
+ return R.id.main;
+ } else if (TAG_CALLCARD_FRAGMENT.equals(tag)) {
+ return R.id.main;
+ }
+ throw new IllegalStateException("Unexpected fragment: " + tag);
+ }
+
+ public void showDialpadFragment(boolean show, boolean animate) {
// If the dialpad is already visible, don't animate in. If it's gone, don't animate out.
- if ((showDialpad && isDialpadVisible()) || (!showDialpad && !isDialpadVisible())) {
+ if ((show && isDialpadVisible()) || (!show && !isDialpadVisible())) {
return;
}
// We don't do a FragmentTransaction on the hide case because it will be dealt with when
// the listener is fired after an animation finishes.
if (!animate) {
- showDialpad(showDialpad);
+ showFragment(TAG_DIALPAD_FRAGMENT, show, true);
} else {
- if (showDialpad) {
- showDialpad(true);
+ if (show) {
+ showFragment(TAG_DIALPAD_FRAGMENT, true, true);
mDialpadFragment.animateShowDialpad();
}
- mCallCardFragment.onDialpadVisiblityChange(showDialpad);
- mDialpadFragment.getView().startAnimation(showDialpad ? mSlideIn : mSlideOut);
+ mCallCardFragment.onDialpadVisibilityChange(show);
+ mDialpadFragment.getView().startAnimation(show ? mSlideIn : mSlideOut);
}
- InCallPresenter.getInstance().getProximitySensor().onDialpadVisible(showDialpad);
+ final ProximitySensor sensor = InCallPresenter.getInstance().getProximitySensor();
+ if (sensor != null) {
+ sensor.onDialpadVisible(show);
+ }
}
public boolean isDialpadVisible() {
return mDialpadFragment != null && mDialpadFragment.isVisible();
}
+ public void showCallCardFragment(boolean show) {
+ showFragment(TAG_CALLCARD_FRAGMENT, show, true);
+ }
+
/**
* Hides or shows the conference manager fragment.
*
* @param show {@code true} if the conference manager should be shown, {@code false} if it
* should be hidden.
*/
- public void showConferenceCallManager(boolean show) {
- mConferenceManagerFragment.setVisible(show);
+ public void showConferenceFragment(boolean show) {
+ showFragment(TAG_CONFERENCE_FRAGMENT, show, true);
+ mConferenceManagerFragment.onVisibilityChanged(show);
// Need to hide the call card fragment to ensure that accessibility service does not try to
// give focus to the call card when the conference manager is visible.
mCallCardFragment.getView().setVisibility(show ? View.GONE : View.VISIBLE);
}
+ public void showAnswerFragment(boolean show) {
+ showFragment(TAG_ANSWER_FRAGMENT, show, true);
+ }
+
public void showPostCharWaitDialog(String callId, String chars) {
if (isForegroundActivity()) {
final PostCharDialogFragment fragment = new PostCharDialogFragment(callId, chars);
@@ -739,7 +787,9 @@ public class InCallActivity extends Activity {
mDialog.dismiss();
mDialog = null;
}
- mAnswerFragment.dismissPendingDialogues();
+ if (mAnswerFragment != null) {
+ mAnswerFragment.dismissPendingDialogs();
+ }
}
/**
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 74c85db8a..fdf193318 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -16,14 +16,13 @@
package com.android.incallui;
-import android.app.Activity;
+import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.Phone;
@@ -40,6 +39,7 @@ import android.view.WindowManager;
import com.google.common.base.Preconditions;
import com.android.contacts.common.interactions.TouchPointManager;
+import com.android.contacts.common.testing.NeededForTesting;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
import com.android.incalluibind.ObjectFactory;
@@ -59,7 +59,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
* that want to listen in on the in-call state changes.
* TODO: This class has become more of a state machine at this point. Consider renaming.
*/
-public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
+public class InCallPresenter implements CallList.Listener, InCallPhoneListener,
+ CircularRevealFragment.OnCircularRevealCompleteListener {
private static final String EXTRA_FIRST_TIME_SHOWN =
"com.android.incallui.intent.extra.FIRST_TIME_SHOWN";
@@ -98,6 +99,17 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
private boolean mServiceConnected = false;
private boolean mAccountSelectionCancelled = false;
private InCallCameraManager mInCallCameraManager = null;
+ private AnswerPresenter mAnswerPresenter = new AnswerPresenter();
+
+ /**
+ * Whether or not we are currently bound and waiting for Telecom to send us a new call.
+ */
+ private boolean mBoundAndWaitingForOutgoingCall;
+ /**
+ * If there is no actual call currently in the call list, this will be used as a fallback
+ * to determine the theme color for InCallUI.
+ */
+ private PhoneAccountHandle mPendingPhoneAccountHandle;
private final Phone.Listener mPhoneListener = new Phone.Listener() {
@Override
@@ -107,6 +119,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
@Override
public void onCallAdded(Phone phone, android.telecom.Call call) {
+ // Since a call has been added we are no longer waiting for Telecom to send us a
+ // call.
+ setBoundAndWaitingForOutgoingCall(false, null);
call.addListener(mCallListener);
}
@Override
@@ -125,8 +140,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
new android.telecom.Call.Listener() {
@Override
public void onPostDialWait(android.telecom.Call call, String remainingPostDialSequence) {
- onPostDialCharWait(
- CallList.getInstance().getCallByTelecommCall(call).getId(),
+ onPostDialCharWait(mCallList.getCallByTelecommCall(call).getId(),
remainingPostDialSequence);
}
@@ -134,7 +148,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
public void onDetailsChanged(android.telecom.Call call,
android.telecom.Call.Details details) {
for (InCallDetailsListener listener : mDetailsListeners) {
- listener.onDetailsChanged(CallList.getInstance().getCallByTelecommCall(call),
+ listener.onDetailsChanged(mCallList.getCallByTelecommCall(call),
details);
}
}
@@ -144,7 +158,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
android.telecom.Call call, List<android.telecom.Call> conferenceableCalls) {
Log.i(this, "onConferenceableCallsChanged: " + call);
for (InCallDetailsListener listener : mDetailsListeners) {
- listener.onDetailsChanged(CallList.getInstance().getCallByTelecommCall(call),
+ listener.onDetailsChanged(mCallList.getCallByTelecommCall(call),
call.getDetails());
}
}
@@ -159,19 +173,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
private boolean mIsActivityPreviouslyStarted = false;
/**
- * Whether or not to wait for the circular reveal animation to be started, to avoid stopping
- * the circular reveal animation activity before the animation is initiated.
- */
- private boolean mWaitForRevealAnimationStart = false;
-
- /**
- * Whether or not the CircularRevealAnimationActivity has started.
- */
- private boolean mCircularRevealActivityStarted = false;
-
- private boolean mShowDialpadOnStart = false;
-
- /**
* Whether or not InCallService is bound to Telecom.
*/
private boolean mServiceBound = false;
@@ -186,8 +187,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
private Phone mPhone;
- private Handler mHandler = new Handler();
-
/** Display colors for the UI. Consists of a primary color and secondary (darker) color */
private MaterialPalette mThemeColors;
@@ -200,6 +199,11 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return sInCallPresenter;
}
+ @NeededForTesting
+ static synchronized void setInstance(InCallPresenter inCallPresenter) {
+ sInCallPresenter = inCallPresenter;
+ }
+
@Override
public void setPhone(Phone phone) {
mPhone = phone;
@@ -220,7 +224,12 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return mCallList;
}
- public void setUp(Context context, CallList callList, AudioModeProvider audioModeProvider) {
+ public void setUp(Context context,
+ CallList callList,
+ AudioModeProvider audioModeProvider,
+ StatusBarNotifier statusBarNotifier,
+ ContactInfoCache contactInfoCache,
+ ProximitySensor proximitySensor) {
if (mServiceConnected) {
Log.i(this, "New service connection replacing existing one.");
// retain the current resources, no need to create new ones.
@@ -233,14 +242,14 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
Preconditions.checkNotNull(context);
mContext = context;
- mContactInfoCache = ContactInfoCache.getInstance(context);
+ mContactInfoCache = contactInfoCache;
- mStatusBarNotifier = new StatusBarNotifier(context, mContactInfoCache);
+ mStatusBarNotifier = statusBarNotifier;
addListener(mStatusBarNotifier);
mAudioModeProvider = audioModeProvider;
- mProximitySensor = new ProximitySensor(context, mAudioModeProvider);
+ mProximitySensor = proximitySensor;
addListener(mProximitySensor);
mCallList = callList;
@@ -274,13 +283,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
private void attemptFinishActivity() {
- mWaitForRevealAnimationStart = false;
-
- Context context = mContext != null ? mContext : mInCallActivity;
- if (context != null) {
- CircularRevealActivity.sendClearDisplayBroadcast(context);
- }
-
final boolean doFinish = (mInCallActivity != null && isActivityStarted());
Log.i(this, "Hide in call UI: " + doFinish);
if (doFinish) {
@@ -400,6 +402,8 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
}
+ private boolean mAwaitingCallListUpdate = false;
+
/**
* Called when there is a change to the call list.
* Sets the In-Call state for the entire in-call app based on the information it gets from
@@ -408,10 +412,17 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
@Override
public void onCallListChange(CallList callList) {
+ if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null &&
+ mInCallActivity.getCallCardFragment().isAnimating()) {
+ mAwaitingCallListUpdate = true;
+ return;
+ }
if (callList == null) {
return;
}
- Log.d(this, "onCallListChange callList=" + callList.toString() );
+
+ mAwaitingCallListUpdate = false;
+
InCallState newState = getPotentialStateFromCallList(callList);
InCallState oldState = mInCallState;
Log.d(this, "onCallListChange oldState= " + oldState + " newState=" + newState);
@@ -463,11 +474,10 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
@Override
public void onDisconnect(Call call) {
- hideDialpadForDisconnect();
maybeShowErrorDialogOnDisconnect(call);
// We need to do the run the same code as onCallListChange.
- onCallListChange(CallList.getInstance());
+ onCallListChange(mCallList);
if (isActivityStarted()) {
mInCallActivity.dismissKeyguard(false);
@@ -477,7 +487,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
/**
* Given the call list, return the state in which the in-call screen should be.
*/
- public static InCallState getPotentialStateFromCallList(CallList callList) {
+ public InCallState getPotentialStateFromCallList(CallList callList) {
InCallState newState = InCallState.NO_CALLS;
@@ -499,9 +509,47 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
newState = InCallState.INCALL;
}
+ if (newState == InCallState.NO_CALLS) {
+ if (mBoundAndWaitingForOutgoingCall) {
+ return InCallState.OUTGOING;
+ }
+ }
+
return newState;
}
+ public boolean isBoundAndWaitingForOutgoingCall() {
+ return mBoundAndWaitingForOutgoingCall;
+ }
+
+ public void setBoundAndWaitingForOutgoingCall(boolean isBound, PhoneAccountHandle handle) {
+ // NOTE: It is possible for there to be a race and have handle become null before
+ // the circular reveal starts. This should not cause any problems because CallCardFragment
+ // should fallback to the actual call in the CallList at that point in time to determine
+ // the theme color.
+ Log.i(this, "setBoundAndWaitingForOutgoingCall: " + isBound);
+ mBoundAndWaitingForOutgoingCall = isBound;
+ mPendingPhoneAccountHandle = handle;
+ if (isBound && mInCallState == InCallState.NO_CALLS) {
+ mInCallState = InCallState.OUTGOING;
+ }
+ }
+
+ @Override
+ public void onCircularRevealComplete(FragmentManager fm) {
+ if (mInCallActivity != null) {
+ mInCallActivity.showCallCardFragment(true);
+ mInCallActivity.getCallCardFragment().animateForNewOutgoingCall();
+ CircularRevealFragment.endCircularReveal(mInCallActivity.getFragmentManager());
+ }
+ }
+
+ public void onShrinkAnimationComplete() {
+ if (mAwaitingCallListUpdate) {
+ onCallListChange(mCallList);
+ }
+ }
+
public void addIncomingCallListener(IncomingCallListener listener) {
Preconditions.checkNotNull(listener);
mIncomingCallListeners.add(listener);
@@ -573,19 +621,23 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public void handleAccountSelection(PhoneAccountHandle accountHandle, boolean setDefault) {
- Call call = mCallList.getWaitingForAccountCall();
- if (call != null) {
- String callId = call.getId();
- TelecomAdapter.getInstance().phoneAccountSelected(callId, accountHandle, setDefault);
+ if (mCallList != null) {
+ Call call = mCallList.getWaitingForAccountCall();
+ if (call != null) {
+ String callId = call.getId();
+ TelecomAdapter.getInstance().phoneAccountSelected(callId, accountHandle, setDefault);
+ }
}
}
public void cancelAccountSelection() {
mAccountSelectionCancelled = true;
- Call call = mCallList.getWaitingForAccountCall();
- if (call != null) {
- String callId = call.getId();
- TelecomAdapter.getInstance().disconnectCall(callId);
+ if (mCallList != null) {
+ Call call = mCallList.getWaitingForAccountCall();
+ if (call != null) {
+ String callId = call.getId();
+ TelecomAdapter.getInstance().disconnectCall(callId);
+ }
}
}
@@ -752,7 +804,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
if (showing) {
mIsActivityPreviouslyStarted = true;
} else {
- CircularRevealActivity.sendClearDisplayBroadcast(mContext);
updateIsChangingConfigurations();
}
@@ -825,7 +876,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
/**
* INCOMING CALL
*/
- final CallList calls = CallList.getInstance();
+ final CallList calls = mCallList;
final Call incomingCall = calls.getIncomingCall();
Log.v(this, "incomingCall: " + incomingCall);
@@ -922,15 +973,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
/**
- * Hides the dialpad. Called when a call is disconnected (Requires hiding dialpad).
- */
- private void hideDialpadForDisconnect() {
- if (isActivityStarted()) {
- mInCallActivity.hideDialpadForDisconnect();
- }
- }
-
- /**
* When the state of in-call changes, this is the first method to get called. It determines if
* the UI needs to be started or finished depending on the new state and does it.
*/
@@ -968,8 +1010,9 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
// [ AND NOW YOU'RE IN THE CALL. voila! ]
//
// Our app is started using a fullScreen notification. We need to do this whenever
- // we get an incoming call.
- final boolean startStartupSequence = (InCallState.INCOMING == newState);
+ // we get an incoming call. Depending on the current context of the device, either a
+ // incoming call HUN or the actual InCallActivity will be shown.
+ final boolean startIncomingCallSequence = (InCallState.INCOMING == newState);
// A dialog to show on top of the InCallUI to select a PhoneAccount
final boolean showAccountPicker = (InCallState.WAITING_FOR_ACCOUNT == newState);
@@ -1002,7 +1045,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
// machine. Telecom should also be the component responsible for disconnecting a call
// with no valid accounts.
showCallUi |= InCallState.PENDING_OUTGOING == newState && mainUiNotVisible
- && isCallWithNoValidAccounts(CallList.getInstance().getPendingOutgoingCall());
+ && isCallWithNoValidAccounts(mCallList.getPendingOutgoingCall());
// The only time that we have an instance of mInCallActivity and it isn't started is
// when it is being destroyed. In that case, lets avoid bringing up another instance of
@@ -1017,7 +1060,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
if (showCallUi || showAccountPicker) {
Log.i(this, "Start in call UI");
showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);
- } else if (startStartupSequence) {
+ } else if (startIncomingCallSequence) {
Log.i(this, "Start Full Screen in call UI");
// We're about the bring up the in-call UI for an incoming call. If we still have
@@ -1051,7 +1094,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
public static boolean isCallWithNoValidAccounts(Call call) {
if (call != null && !isEmergencyCall(call)) {
- Bundle extras = call.getTelecommCall().getDetails().getExtras();
+ Bundle extras = call.getExtras();
if (extras == null) {
extras = EMPTY_EXTRAS;
@@ -1188,41 +1231,8 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public void showInCall(final boolean showDialpad, final boolean newOutgoingCall) {
- if (mCircularRevealActivityStarted) {
- mWaitForRevealAnimationStart = true;
- mShowDialpadOnStart = showDialpad;
- Log.i(this, "Waiting for circular reveal completion to show InCallActivity");
- } else {
- Log.i(this, "Showing InCallActivity immediately");
- mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall,
- newOutgoingCall /* showCircularReveal */));
- }
- }
-
- public void onCircularRevealStarted(final Activity activity) {
- mCircularRevealActivityStarted = false;
- if (mWaitForRevealAnimationStart) {
- mWaitForRevealAnimationStart = false;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mContext == null) {
- Log.e(this, "Setup did not occur before showing the InCallActivity.");
- activity.finish();
- return;
- }
-
- Log.i(this, "Showing InCallActivity after circular reveal");
- final Intent intent =
- getInCallIntent(mShowDialpadOnStart, true, false, false);
- activity.startActivity(intent);
- mShowDialpadOnStart = false;
- }
- });
- } else if (!mServiceBound) {
- CircularRevealActivity.sendClearDisplayBroadcast(mContext);
- return;
- }
+ Log.i(this, "Showing InCallActivity");
+ mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall));
}
public void onServiceBind() {
@@ -1230,6 +1240,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public void onServiceUnbind() {
+ InCallPresenter.getInstance().setBoundAndWaitingForOutgoingCall(false, null);
mServiceBound = false;
}
@@ -1254,43 +1265,26 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
final PhoneAccountHandle accountHandle =
intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
- final MaterialPalette colors = getColorsFromPhoneAccountHandle(accountHandle);
final Point touchPoint = extras.getParcelable(TouchPointManager.TOUCH_POINT);
- mCircularRevealActivityStarted = true;
- mContext.startActivity(getAnimationIntent(touchPoint, colors));
- }
+ InCallPresenter.getInstance().setBoundAndWaitingForOutgoingCall(true, accountHandle);
- private Intent getAnimationIntent(Point touchPoint, MaterialPalette palette) {
- final Intent intent = new Intent(mContext, CircularRevealActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- intent.putExtra(TouchPointManager.TOUCH_POINT, touchPoint);
- intent.putExtra(CircularRevealActivity.EXTRA_THEME_COLORS, palette);
- return intent;
+ final Intent incallIntent = getInCallIntent(false, true);
+ incallIntent.putExtra(TouchPointManager.TOUCH_POINT, touchPoint);
+ mContext.startActivity(incallIntent);
}
- public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall,
- boolean showCircularReveal) {
- return getInCallIntent(showDialpad, newOutgoingCall, showCircularReveal, true);
- }
-
- public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall,
- boolean showCircularReveal, boolean newTask) {
+ public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall) {
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
- if (newTask) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- }
+ | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(mContext, InCallActivity.class);
if (showDialpad) {
intent.putExtra(InCallActivity.SHOW_DIALPAD_EXTRA, true);
}
intent.putExtra(InCallActivity.NEW_OUTGOING_CALL_EXTRA, newOutgoingCall);
- intent.putExtra(InCallActivity.SHOW_CIRCULAR_REVEAL_EXTRA, showCircularReveal);
return intent;
}
@@ -1400,7 +1394,10 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
* @return The space beside the call card.
*/
public float getSpaceBesideCallCard() {
- return mInCallActivity.getCallCardFragment().getSpaceBesideCallCard();
+ if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null) {
+ return mInCallActivity.getCallCardFragment().getSpaceBesideCallCard();
+ }
+ return 0;
}
/**
@@ -1409,7 +1406,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
* @return True if the call card fragment is visible.
*/
public boolean getCallCardFragmentVisible() {
- if (mInCallActivity != null) {
+ if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null) {
return mInCallActivity.getCallCardFragment().isVisible();
}
return false;
@@ -1426,7 +1423,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return;
}
- mInCallActivity.showConferenceCallManager(show);
+ mInCallActivity.showConferenceFragment(show);
}
/**
@@ -1443,7 +1440,7 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
*/
public void setThemeColors() {
// This method will set the background to default if the color is PhoneAccount.NO_COLOR.
- mThemeColors = getColorsFromCall(CallList.getInstance().getFirstCall());
+ mThemeColors = getColorsFromCall(mCallList.getFirstCall());
if (mInCallActivity == null) {
return;
@@ -1460,7 +1457,11 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
private MaterialPalette getColorsFromCall(Call call) {
- return getColorsFromPhoneAccountHandle(call == null ? null : call.getAccountHandle());
+ if (call == null) {
+ return getColorsFromPhoneAccountHandle(mPendingPhoneAccountHandle);
+ } else {
+ return getColorsFromPhoneAccountHandle(call.getAccountHandle());
+ }
}
private MaterialPalette getColorsFromPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
@@ -1492,10 +1493,20 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
return mTelecomManager;
}
+ InCallActivity getActivity() {
+ return mInCallActivity;
+ }
+
+ AnswerPresenter getAnswerPresenter() {
+ return mAnswerPresenter;
+ }
+
/**
* Private constructor. Must use getInstance() to get this singleton.
*/
private InCallPresenter() {
+ addIncomingCallListener(mAnswerPresenter);
+ addInCallUiListener(mAnswerPresenter);
}
/**
diff --git a/InCallUI/src/com/android/incallui/InCallServiceImpl.java b/InCallUI/src/com/android/incallui/InCallServiceImpl.java
index 17f4e174d..adb069784 100644
--- a/InCallUI/src/com/android/incallui/InCallServiceImpl.java
+++ b/InCallUI/src/com/android/incallui/InCallServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.incallui;
+import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.telecom.InCallService;
@@ -53,10 +54,16 @@ public class InCallServiceImpl extends InCallService {
@Override
public IBinder onBind(Intent intent) {
+ final Context context = getApplicationContext();
+ final ContactInfoCache contactInfoCache = ContactInfoCache.getInstance(context);
InCallPresenter.getInstance().setUp(
getApplicationContext(),
CallList.getInstance(),
- AudioModeProvider.getInstance());
+ AudioModeProvider.getInstance(),
+ new StatusBarNotifier(context, contactInfoCache),
+ contactInfoCache,
+ new ProximitySensor(context, AudioModeProvider.getInstance())
+ );
InCallPresenter.getInstance().onServiceBind();
InCallPresenter.getInstance().maybeStartRevealAnimation(intent);
return super.onBind(intent);
diff --git a/InCallUI/src/com/android/incallui/InCallUIMaterialColorMapUtils.java b/InCallUI/src/com/android/incallui/InCallUIMaterialColorMapUtils.java
index 1f61070ed..d65580efe 100644
--- a/InCallUI/src/com/android/incallui/InCallUIMaterialColorMapUtils.java
+++ b/InCallUI/src/com/android/incallui/InCallUIMaterialColorMapUtils.java
@@ -45,8 +45,8 @@ public class InCallUIMaterialColorMapUtils extends MaterialColorMapUtils {
}
public static MaterialPalette getDefaultPrimaryAndSecondaryColors(Resources resources) {
- final int primaryColor = resources.getColor(R.color.dialer_theme_color);
- final int secondaryColor = resources.getColor(R.color.dialer_theme_color_dark);
+ final int primaryColor = resources.getColor(R.color.dialer_theme_color, null);
+ final int secondaryColor = resources.getColor(R.color.dialer_theme_color_dark, null);
return new MaterialPalette(primaryColor, secondaryColor);
}
} \ No newline at end of file
diff --git a/InCallUI/src/com/android/incallui/InCallVideoCallListener.java b/InCallUI/src/com/android/incallui/InCallVideoCallListener.java
index cf2b859e0..df9dfdce7 100644
--- a/InCallUI/src/com/android/incallui/InCallVideoCallListener.java
+++ b/InCallUI/src/com/android/incallui/InCallVideoCallListener.java
@@ -146,7 +146,9 @@ public class InCallVideoCallListener extends VideoCall.Listener {
*/
@Override
public void onCameraCapabilitiesChanged(CameraCapabilities cameraCapabilities) {
- InCallVideoCallListenerNotifier.getInstance().cameraDimensionsChanged(
- mCall, cameraCapabilities.getWidth(), cameraCapabilities.getHeight());
+ if (cameraCapabilities != null) {
+ InCallVideoCallListenerNotifier.getInstance().cameraDimensionsChanged(
+ mCall, cameraCapabilities.getWidth(), cameraCapabilities.getHeight());
+ }
}
}
diff --git a/InCallUI/src/com/android/incallui/PostCharDialogFragment.java b/InCallUI/src/com/android/incallui/PostCharDialogFragment.java
index e1edbc75b..09b626a92 100644
--- a/InCallUI/src/com/android/incallui/PostCharDialogFragment.java
+++ b/InCallUI/src/com/android/incallui/PostCharDialogFragment.java
@@ -62,7 +62,6 @@ public class PostCharDialogFragment extends DialogFragment {
});
final AlertDialog dialog = builder.create();
- dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
return dialog;
}
diff --git a/InCallUI/src/com/android/incallui/SmallerHitTargetTouchListener.java b/InCallUI/src/com/android/incallui/SmallerHitTargetTouchListener.java
deleted file mode 100644
index 83feaf54a..000000000
--- a/InCallUI/src/com/android/incallui/SmallerHitTargetTouchListener.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2012 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.incallui;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * OnTouchListener used to shrink the "hit target" of some onscreen buttons.
- *
- * We do this for a few specific buttons which are vulnerable to
- * "false touches" because either (1) they're near the edge of the
- * screen and might be unintentionally touched while holding the
- * device in your hand, (2) they're in the upper corners and might
- * be touched by the user's ear before the prox sensor has a chance to
- * kick in, or (3) they are close to other buttons.
- */
-public class SmallerHitTargetTouchListener implements View.OnTouchListener {
- private static final String TAG = "SmallerHitTargetTouchListener";
-
- /**
- * Edge dimensions where a touch does not register an action (in DIP).
- */
- private static final int HIT_TARGET_EDGE_IGNORE_DP_X = 30;
- private static final int HIT_TARGET_EDGE_IGNORE_DP_Y = 10;
- private static final int HIT_TARGET_MIN_SIZE_DP_X = HIT_TARGET_EDGE_IGNORE_DP_X * 3;
- private static final int HIT_TARGET_MIN_SIZE_DP_Y = HIT_TARGET_EDGE_IGNORE_DP_Y * 3;
-
- // True if the most recent DOWN event was a "hit".
- boolean mDownEventHit;
-
- /**
- * Called when a touch event is dispatched to a view. This allows listeners to
- * get a chance to respond before the target view.
- *
- * @return True if the listener has consumed the event, false otherwise.
- * (In other words, we return true when the touch is *outside*
- * the "smaller hit target", which will prevent the actual
- * button from handling these events.)
- */
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- // if (DBG) log("SmallerHitTargetTouchListener: " + v + ", event " + event);
-
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- // Note that event.getX() and event.getY() are already
- // translated into the View's coordinates. (In other words,
- // "0,0" is a touch on the upper-left-most corner of the view.)
- final int touchX = (int) event.getX();
- final int touchY = (int) event.getY();
-
- final int viewWidth = v.getWidth();
- final int viewHeight = v.getHeight();
-
- final float pixelDensity = v.getResources().getDisplayMetrics().density;
- final int targetMinSizeX = (int) (HIT_TARGET_MIN_SIZE_DP_X * pixelDensity);
- final int targetMinSizeY = (int) (HIT_TARGET_MIN_SIZE_DP_Y * pixelDensity);
-
- int edgeIgnoreX = (int) (HIT_TARGET_EDGE_IGNORE_DP_X * pixelDensity);
- int edgeIgnoreY = (int) (HIT_TARGET_EDGE_IGNORE_DP_Y * pixelDensity);
-
- // If we are dealing with smaller buttons where the dead zone defined by
- // HIT_TARGET_EDGE_IGNORE_DP_[X|Y] is too large.
- if (viewWidth < targetMinSizeX || viewHeight < targetMinSizeY) {
- // This really should not happen given our two use cases (as of this writing)
- // in the call edge button and secondary calling card. However, we leave
- // this is as a precautionary measure.
- Log.w(TAG, "onTouch: view is too small for SmallerHitTargetTouchListener");
- edgeIgnoreX = 0;
- edgeIgnoreY = 0;
- }
-
- final int minTouchX = edgeIgnoreX;
- final int maxTouchX = viewWidth - edgeIgnoreX;
- final int minTouchY = edgeIgnoreY;
- final int maxTouchY = viewHeight - edgeIgnoreY;
-
- if (touchX < minTouchX || touchX > maxTouchX ||
- touchY < minTouchY || touchY > maxTouchY) {
- // Missed!
- // if (DBG) log(" -> MISSED!");
- mDownEventHit = false;
- return true; // Consume this event; don't let the button see it
- } else {
- // Hit!
- // if (DBG) log(" -> HIT!");
- mDownEventHit = true;
- return false; // Let this event through to the actual button
- }
- } else {
- // This is a MOVE, UP or CANCEL event.
- //
- // We only do the "smaller hit target" check on DOWN events.
- // For the subsequent MOVE/UP/CANCEL events, we let them
- // through to the actual button IFF the previous DOWN event
- // got through to the actual button (i.e. it was a "hit".)
- return !mDownEventHit;
- }
- }
-}
diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
index 006339ce1..c5a0b7f4c 100644
--- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java
+++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
@@ -641,8 +641,7 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener {
private PendingIntent createLaunchPendingIntent() {
final Intent intent = InCallPresenter.getInstance().getInCallIntent(
- false /* showDialpad */, false /* newOutgoingCall */,
- false /* showCircularReveal */);
+ false /* showDialpad */, false /* newOutgoingCall */);
// PendingIntent that can be used to launch the InCallActivity. The
// system fires off this intent if the user pulls down the windowshade
diff --git a/InCallUI/src/com/android/incallui/TelecomAdapter.java b/InCallUI/src/com/android/incallui/TelecomAdapter.java
index 373bd7874..25813f28f 100644
--- a/InCallUI/src/com/android/incallui/TelecomAdapter.java
+++ b/InCallUI/src/com/android/incallui/TelecomAdapter.java
@@ -20,7 +20,6 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.Looper;
-import android.telecom.InCallAdapter;
import android.telecom.Phone;
import android.telecom.PhoneAccountHandle;
@@ -28,7 +27,6 @@ import com.google.common.base.Preconditions;
import java.util.List;
-/** Wrapper around {@link InCallAdapter} that only forwards calls to the adapter when it's valid. */
final class TelecomAdapter implements InCallPhoneListener {
private static final String ADD_CALL_MODE_KEY = "add_call_mode";
diff --git a/InCallUI/src/com/android/incallui/VideoCallFragment.java b/InCallUI/src/com/android/incallui/VideoCallFragment.java
index c4d10c569..233ff92a1 100644
--- a/InCallUI/src/com/android/incallui/VideoCallFragment.java
+++ b/InCallUI/src/com/android/incallui/VideoCallFragment.java
@@ -41,6 +41,8 @@ import com.google.common.base.Objects;
*/
public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
VideoCallPresenter.VideoCallUi> implements VideoCallPresenter.VideoCallUi {
+ private static final String TAG = VideoCallFragment.class.getSimpleName();
+ private static final boolean DEBUG = false;
/**
* Used to indicate that the surface dimensions are not set.
@@ -156,6 +158,14 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
* @param view The {@link TextureView}.
*/
public void recreateView(TextureView view) {
+ if (DEBUG) {
+ Log.i(TAG, "recreateView: " + view);
+ }
+
+ if (mTextureView == view) {
+ return;
+ }
+
mTextureView = view;
mTextureView.setSurfaceTextureListener(this);
mTextureView.setOnClickListener(this);
@@ -191,6 +201,9 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
int height) {
boolean surfaceCreated;
+ if (DEBUG) {
+ Log.i(TAG, "onSurfaceTextureAvailable: " + surfaceTexture);
+ }
// Where there is no saved {@link SurfaceTexture} available, use the newly created one.
// If a saved {@link SurfaceTexture} is available, we are re-creating after an
// orientation change.
@@ -281,6 +294,19 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
// Not Handled
}
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (DEBUG) {
+ Log.i(TAG, "OnViewAttachedToWindow");
+ }
+ if (mSavedSurfaceTexture != null) {
+ mTextureView.setSurfaceTexture(mSavedSurfaceTexture);
+ }
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {}
+
/**
* Retrieves the current {@link TextureView}.
*
@@ -413,33 +439,10 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
-
super.onCreateView(inflater, container, savedInstanceState);
final View view = inflater.inflate(R.layout.video_call_fragment, container, false);
- // Attempt to center the incoming video view, if it is in the layout.
- final ViewTreeObserver observer = view.getViewTreeObserver();
- observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- // Check if the layout includes the incoming video surface -- this will only be the
- // case for a video call.
- View displayVideo = view.findViewById(R.id.incomingVideo);
- if (displayVideo != null) {
- centerDisplayView(displayVideo);
- }
-
- mIsLayoutComplete = true;
-
- // Remove the listener so we don't continually re-layout.
- ViewTreeObserver observer = view.getViewTreeObserver();
- if (observer.isAlive()) {
- observer.removeOnGlobalLayoutListener(this);
- }
- }
- });
-
return view;
}
@@ -912,6 +915,27 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
sPreviewSurface.recreateView((TextureView) mVideoViews.findViewById(
R.id.previewVideo));
}
+
+ // Attempt to center the incoming video view, if it is in the layout.
+ final ViewTreeObserver observer = mVideoViews.getViewTreeObserver();
+ observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ // Check if the layout includes the incoming video surface -- this will only be the
+ // case for a video call.
+ View displayVideo = mVideoViews.findViewById(R.id.incomingVideo);
+ if (displayVideo != null) {
+ centerDisplayView(displayVideo);
+ }
+ mIsLayoutComplete = true;
+
+ // Remove the listener so we don't continually re-layout.
+ ViewTreeObserver observer = mVideoViews.getViewTreeObserver();
+ if (observer.isAlive()) {
+ observer.removeOnGlobalLayoutListener(this);
+ }
+ }
+ });
}
}
diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
index 486a38da3..e4a5db97a 100644
--- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
@@ -71,6 +71,10 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
InCallVideoCallListenerNotifier.SessionModificationListener {
public static final String TAG = "VideoCallPresenter";
+ private static final String TAG = VideoCallPresenter.class.getSimpleName();
+
+ public static final boolean DEBUG = false;
+
/**
* Determines the device orientation (portrait/lanscape).
*/
diff --git a/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java b/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java
index fe008f3df..812e883c0 100644
--- a/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java
+++ b/InCallUI/src/com/android/incallui/widget/multiwaveview/GlowPadView.java
@@ -881,7 +881,7 @@ public class GlowPadView extends View {
// tx and ty are relative to wave center
float tx = eventX - mWaveCenterX;
float ty = eventY - mWaveCenterY;
- float touchRadius = (float) Math.sqrt(dist2(tx, ty));
+ float touchRadius = (float) Math.hypot(tx, ty);
final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
float limitX = tx * scale;
float limitY = ty * scale;
diff --git a/InCallUI/src/com/android/incallui/widget/multiwaveview/PointCloud.java b/InCallUI/src/com/android/incallui/widget/multiwaveview/PointCloud.java
index 77aac2bda..07a2cb964 100644
--- a/InCallUI/src/com/android/incallui/widget/multiwaveview/PointCloud.java
+++ b/InCallUI/src/com/android/incallui/widget/multiwaveview/PointCloud.java
@@ -20,7 +20,6 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
-import android.util.FloatMath;
import android.util.Log;
import java.util.ArrayList;
@@ -151,8 +150,8 @@ public class PointCloud {
float eta = PI/2.0f;
float dEta = 2.0f * PI / pointsInBand;
for (int i = 0; i < pointsInBand; i++) {
- float x = r * FloatMath.cos(eta);
- float y = r * FloatMath.sin(eta);
+ float x = r * (float) Math.cos(eta);
+ float y = r * (float) Math.sin(eta);
eta += dEta;
mPointCloud.add(new Point(x, y, r));
}
@@ -168,7 +167,7 @@ public class PointCloud {
}
private static float hypot(float x, float y) {
- return FloatMath.sqrt(x*x + y*y);
+ return (float) Math.hypot(x, y);
}
private static float max(float a, float b) {
@@ -181,8 +180,8 @@ public class PointCloud {
float glowAlpha = 0.0f;
if (glowDistance < glowManager.radius) {
- float cosf = FloatMath.cos(PI * 0.25f * glowDistance / glowManager.radius);
- glowAlpha = glowManager.alpha * max(0.0f, (float) Math.pow(cosf, 10.0f));
+ double cos = Math.cos(Math.PI * 0.25d * glowDistance / glowManager.radius);
+ glowAlpha = glowManager.alpha * max(0.0f, (float) Math.pow(cos, 10.0d));
}
// Compute contribution from Wave
@@ -190,8 +189,8 @@ public class PointCloud {
float distanceToWaveRing = (radius - waveManager.radius);
float waveAlpha = 0.0f;
if (distanceToWaveRing < waveManager.width * 0.5f && distanceToWaveRing < 0.0f) {
- float cosf = FloatMath.cos(PI * 0.25f * distanceToWaveRing / waveManager.width);
- waveAlpha = waveManager.alpha * max(0.0f, (float) Math.pow(cosf, 20.0f));
+ double cos = Math.cos(Math.PI * 0.25d * distanceToWaveRing / waveManager.width);
+ waveAlpha = waveManager.alpha * max(0.0f, (float) Math.pow(cos, 20.0d));
}
return (int) (max(glowAlpha, waveAlpha) * 255);