Update Dialer source from latest green build.
* Refactor voicemail component
* Add new enriched calling components
Test: treehugger, manual aosp testing
Change-Id: I521a0f86327d4b42e14d93927c7d613044ed5942
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index bd8f006..15a0233 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -24,6 +24,7 @@
import android.os.Bundle;
import android.os.Trace;
import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.telecom.Call;
import android.telecom.Call.Details;
@@ -47,10 +48,15 @@
import com.android.dialer.common.Assert;
import com.android.dialer.common.ConfigProviderBindings;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.logging.nano.ContactLookupResult;
-import com.android.dialer.util.CallUtil;
import com.android.incallui.latencyreport.LatencyReport;
import com.android.incallui.util.TelecomCallUtil;
+import com.android.incallui.videotech.VideoTech;
+import com.android.incallui.videotech.VideoTech.VideoTechListener;
+import com.android.incallui.videotech.empty.EmptyVideoTech;
+import com.android.incallui.videotech.ims.ImsVideoTech;
+import com.android.incallui.videotech.rcs.RcsVideoShare;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -62,11 +68,16 @@
import java.util.concurrent.TimeUnit;
/** Describes a single call and its state. */
-public class DialerCall {
+public class DialerCall implements VideoTechListener {
public static final int CALL_HISTORY_STATUS_UNKNOWN = 0;
public static final int CALL_HISTORY_STATUS_PRESENT = 1;
public static final int CALL_HISTORY_STATUS_NOT_PRESENT = 2;
+
+ // Hard coded property for {@code Call}. Upstreamed change from Motorola.
+ // TODO(b/35359461): Move it to Telecom in framework.
+ public static final int PROPERTY_CODEC_KNOWN = 0x04000000;
+
private static final String ID_PREFIX = "DialerCall_";
private static final String CONFIG_EMERGENCY_CALLBACK_WINDOW_MILLIS =
"emergency_callback_window_millis";
@@ -82,13 +93,13 @@
private final LatencyReport mLatencyReport;
private final String mId;
private final List<String> mChildCallIds = new ArrayList<>();
- private final VideoSettings mVideoSettings = new VideoSettings();
private final LogState mLogState = new LogState();
private final Context mContext;
private final DialerCallDelegate mDialerCallDelegate;
private final List<DialerCallListener> mListeners = new CopyOnWriteArrayList<>();
private final List<CannedTextResponsesLoadedListener> mCannedTextResponsesLoadedListeners =
new CopyOnWriteArrayList<>();
+ private final VideoTechManager mVideoTechManager;
private boolean mIsEmergencyCall;
private Uri mHandle;
@@ -98,13 +109,6 @@
private boolean hasShownWiFiToLteHandoverToast;
private boolean doNotShowDialogForHandoffToWifiFailure;
- @SessionModificationState private int mSessionModificationState;
- private int mVideoState;
- /** mRequestedVideoState is used to store requested upgrade / downgrade video state */
- private int mRequestedVideoState = VideoProfile.STATE_AUDIO_ONLY;
-
- private InCallVideoCallCallback mVideoCallCallback;
- private boolean mIsVideoCallCallbackRegistered;
private String mChildNumber;
private String mLastForwardedNumber;
private String mCallSubject;
@@ -118,6 +122,7 @@
private boolean didShowCameraPermission;
private String callProviderLabel;
private String callbackNumber;
+ private int mCameraDirection = CameraDirection.CAMERA_DIRECTION_UNKNOWN;
public static String getNumberFromHandle(Uri handle) {
return handle == null ? "" : handle.getSchemeSpecificPart();
@@ -125,7 +130,7 @@
/**
* Whether the call is put on hold by remote party. This is different than the {@link
- * State.ONHOLD} state which indicates that the call is being held locally on the device.
+ * State#ONHOLD} state which indicates that the call is being held locally on the device.
*/
private boolean isRemotelyHeld;
@@ -189,7 +194,7 @@
@Override
public void onCallDestroyed(Call call) {
LogUtil.v("TelecomCallCallback.onStateChanged", "call=" + call);
- call.unregisterCallback(this);
+ unregisterCallback();
}
@Override
@@ -248,7 +253,10 @@
mLatencyReport = latencyReport;
mId = ID_PREFIX + Integer.toString(sIdCounter++);
- updateFromTelecomCall(registerCallback);
+ // Must be after assigning mTelecomCall
+ mVideoTechManager = new VideoTechManager(this);
+
+ updateFromTelecomCall();
if (registerCallback) {
mTelecomCall.registerCallback(mTelecomCallCallback);
@@ -348,19 +356,24 @@
return mTelecomCall.getDetails().getStatusHints();
}
- /**
- * @return video settings of the call, null if the call is not a video call.
- * @see VideoProfile
- */
- public VideoSettings getVideoSettings() {
- return mVideoSettings;
+ public int getCameraDir() {
+ return mCameraDirection;
+ }
+
+ public void setCameraDir(int cameraDir) {
+ if (cameraDir == CameraDirection.CAMERA_DIRECTION_FRONT_FACING
+ || cameraDir == CameraDirection.CAMERA_DIRECTION_BACK_FACING) {
+ mCameraDirection = cameraDir;
+ } else {
+ mCameraDirection = CameraDirection.CAMERA_DIRECTION_UNKNOWN;
+ }
}
private void update() {
Trace.beginSection("Update");
int oldState = getState();
// We want to potentially register a video call callback here.
- updateFromTelecomCall(true /* registerCallback */);
+ updateFromTelecomCall();
if (oldState != getState() && getState() == DialerCall.State.DISCONNECTED) {
for (DialerCallListener listener : mListeners) {
listener.onDialerCallDisconnect();
@@ -373,21 +386,15 @@
Trace.endSection();
}
- private void updateFromTelecomCall(boolean registerCallback) {
+ private void updateFromTelecomCall() {
LogUtil.v("DialerCall.updateFromTelecomCall", mTelecomCall.toString());
+
+ mVideoTechManager.dispatchCallStateChanged(mTelecomCall.getState());
+
final int translatedState = translateState(mTelecomCall.getState());
if (mState != State.BLOCKED) {
setState(translatedState);
setDisconnectCause(mTelecomCall.getDetails().getDisconnectCause());
- maybeCancelVideoUpgrade(mTelecomCall.getDetails().getVideoState());
- }
-
- if (registerCallback && mTelecomCall.getVideoCall() != null) {
- if (mVideoCallCallback == null) {
- mVideoCallCallback = new InCallVideoCallCallback(this);
- }
- mTelecomCall.getVideoCall().registerCallback(mVideoCallCallback);
- mIsVideoCallCallbackRegistered = true;
}
mChildCallIds.clear();
@@ -428,19 +435,6 @@
}
}
}
-
- if (mSessionModificationState
- == DialerCall.SESSION_MODIFICATION_STATE_WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE
- && isVideoCall()) {
- // We find out in {@link InCallVideoCallCallback.onSessionModifyResponseReceived}
- // whether the video upgrade request was accepted. We don't clear the session modification
- // state right away though to avoid having the UI switch from video to voice to video.
- // Once the underlying telecom call updates to video mode it's safe to clear the state.
- LogUtil.i(
- "DialerCall.updateFromTelecomCall",
- "upgraded to video, clearing session modification state");
- setSessionModificationState(DialerCall.SESSION_MODIFICATION_STATE_NO_REQUEST);
- }
}
/**
@@ -518,25 +512,6 @@
}
}
- /**
- * Determines if a received upgrade to video request should be cancelled. This can happen if
- * another InCall UI responds to the upgrade to video request.
- *
- * @param newVideoState The new video state.
- */
- private void maybeCancelVideoUpgrade(int newVideoState) {
- boolean isVideoStateChanged = mVideoState != newVideoState;
-
- if (mSessionModificationState
- == DialerCall.SESSION_MODIFICATION_STATE_RECEIVED_UPGRADE_TO_VIDEO_REQUEST
- && isVideoStateChanged) {
-
- LogUtil.i("DialerCall.maybeCancelVideoUpgrade", "cancelling upgrade notification");
- setSessionModificationState(DialerCall.SESSION_MODIFICATION_STATE_NO_REQUEST);
- }
- mVideoState = newVideoState;
- }
-
public String getId() {
return mId;
}
@@ -710,6 +685,7 @@
return mTelecomCall.getDetails().hasProperty(property);
}
+ @NonNull
public String getUniqueCallId() {
return uniqueCallId;
}
@@ -733,15 +709,9 @@
return mTelecomCall == null ? null : mTelecomCall.getDetails().getAccountHandle();
}
- /**
- * @return The {@link VideoCall} instance associated with the {@link Call}. Will return {@code
- * null} until {@link #updateFromTelecomCall(boolean)} has registered a valid callback on the
- * {@link VideoCall}.
- */
+ /** @return The {@link VideoCall} instance associated with the {@link Call}. */
public VideoCall getVideoCall() {
- return mTelecomCall == null || !mIsVideoCallCallbackRegistered
- ? null
- : mTelecomCall.getVideoCall();
+ return mTelecomCall == null ? null : mTelecomCall.getVideoCall();
}
public List<String> getChildCallIds() {
@@ -761,7 +731,15 @@
}
public boolean isVideoCall() {
- return CallUtil.isVideoEnabled(mContext) && VideoUtils.isVideoCall(getVideoState());
+ return getVideoTech().isTransmittingOrReceiving();
+ }
+
+ public boolean hasReceivedVideoUpgradeRequest() {
+ return VideoUtils.hasReceivedVideoUpgradeRequest(getVideoTech().getSessionModificationState());
+ }
+
+ public boolean hasSentVideoUpgradeRequest() {
+ return VideoUtils.hasSentVideoUpgradeRequest(getVideoTech().getSessionModificationState());
}
/**
@@ -772,76 +750,6 @@
mIsEmergencyCall = TelecomCallUtil.isEmergencyCall(mTelecomCall);
}
- /**
- * Gets the video state which was requested via a session modification request.
- *
- * @return The video state.
- */
- public int getRequestedVideoState() {
- return mRequestedVideoState;
- }
-
- /**
- * Handles incoming session modification requests. Stores the pending video request and sets the
- * session modification state to {@link
- * DialerCall#SESSION_MODIFICATION_STATE_RECEIVED_UPGRADE_TO_VIDEO_REQUEST} so that we can keep
- * track of the fact the request was received. Only upgrade requests require user confirmation and
- * will be handled by this method. The remote user can turn off their own camera without
- * confirmation.
- *
- * @param videoState The requested video state.
- */
- public void setRequestedVideoState(int videoState) {
- LogUtil.v("DialerCall.setRequestedVideoState", "videoState: " + videoState);
- if (videoState == getVideoState()) {
- LogUtil.e("DialerCall.setRequestedVideoState", "clearing session modification state");
- setSessionModificationState(DialerCall.SESSION_MODIFICATION_STATE_NO_REQUEST);
- return;
- }
-
- mRequestedVideoState = videoState;
- setSessionModificationState(
- DialerCall.SESSION_MODIFICATION_STATE_RECEIVED_UPGRADE_TO_VIDEO_REQUEST);
- for (DialerCallListener listener : mListeners) {
- listener.onDialerCallUpgradeToVideo();
- }
-
- LogUtil.i(
- "DialerCall.setRequestedVideoState",
- "mSessionModificationState: %d, videoState: %d",
- mSessionModificationState,
- videoState);
- update();
- }
-
- /**
- * Gets the current video session modification state.
- *
- * @return The session modification state.
- */
- @SessionModificationState
- public int getSessionModificationState() {
- return mSessionModificationState;
- }
-
- /**
- * Set the session modification state. Used to keep track of pending video session modification
- * operations and to inform listeners of these changes.
- *
- * @param state the new session modification state.
- */
- public void setSessionModificationState(@SessionModificationState int state) {
- boolean hasChanged = mSessionModificationState != state;
- if (hasChanged) {
- LogUtil.i(
- "DialerCall.setSessionModificationState", "%d -> %d", mSessionModificationState, state);
- mSessionModificationState = state;
- for (DialerCallListener listener : mListeners) {
- listener.onDialerCallSessionModificationStateChange(state);
- }
- }
- }
-
public LogState getLogState() {
return mLogState;
}
@@ -862,24 +770,6 @@
}
/**
- * Determines if the external call is pullable.
- *
- * <p>An external call is one which does not exist locally for the {@link
- * android.telecom.ConnectionService} it is associated with. An external call may be "pullable",
- * which means that the user can request it be transferred to the current device.
- *
- * <p>External calls are only supported in N and higher.
- *
- * @return {@code true} if the call is an external call, {@code false} otherwise.
- */
- public boolean isPullableExternalCall() {
- return VERSION.SDK_INT >= VERSION_CODES.N
- && (mTelecomCall.getDetails().getCallCapabilities()
- & CallCompat.Details.CAPABILITY_CAN_PULL_CALL)
- == CallCompat.Details.CAPABILITY_CAN_PULL_CALL;
- }
-
- /**
* Determines if answering this call will cause an ongoing video call to be dropped.
*
* @return {@code true} if answering this call will drop an ongoing video call, {@code false}
@@ -922,7 +812,7 @@
return String.format(
Locale.US,
"[%s, %s, %s, %s, children:%s, parent:%s, "
- + "conferenceable:%s, videoState:%s, mSessionModificationState:%d, VideoSettings:%s]",
+ + "conferenceable:%s, videoState:%s, mSessionModificationState:%d, CameraDir:%s]",
mId,
State.toString(getState()),
Details.capabilitiesToString(mTelecomCall.getDetails().getCallCapabilities()),
@@ -931,8 +821,8 @@
getParentId(),
this.mTelecomCall.getConferenceableCalls(),
VideoProfile.videoStateToString(mTelecomCall.getDetails().getVideoState()),
- mSessionModificationState,
- getVideoSettings());
+ getVideoTech().getSessionModificationState(),
+ getCameraDir());
}
public String toSimpleString() {
@@ -1012,20 +902,6 @@
mTelecomCall.unregisterCallback(mTelecomCallCallback);
}
- public void acceptUpgradeRequest(int videoState) {
- LogUtil.i("DialerCall.acceptUpgradeRequest", "videoState: " + videoState);
- VideoProfile videoProfile = new VideoProfile(videoState);
- getVideoCall().sendSessionModifyResponse(videoProfile);
- setSessionModificationState(DialerCall.SESSION_MODIFICATION_STATE_NO_REQUEST);
- }
-
- public void declineUpgradeRequest() {
- LogUtil.i("DialerCall.declineUpgradeRequest", "");
- VideoProfile videoProfile = new VideoProfile(getVideoState());
- getVideoCall().sendSessionModifyResponse(videoProfile);
- setSessionModificationState(DialerCall.SESSION_MODIFICATION_STATE_NO_REQUEST);
- }
-
public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
LogUtil.i(
"DialerCall.phoneAccountSelected",
@@ -1064,6 +940,10 @@
mTelecomCall.answer(videoState);
}
+ public void answer() {
+ answer(mTelecomCall.getDetails().getVideoState());
+ }
+
public void reject(boolean rejectWithMessage, String message) {
LogUtil.i("DialerCall.reject", "");
mTelecomCall.reject(rejectWithMessage, message);
@@ -1095,6 +975,10 @@
return mContext.getSystemService(TelecomManager.class).getPhoneAccount(accountHandle);
}
+ public VideoTech getVideoTech() {
+ return mVideoTechManager.getVideoTech();
+ }
+
public String getCallbackNumber() {
if (callbackNumber == null) {
// Show the emergency callback number if either:
@@ -1146,6 +1030,39 @@
return null;
}
+ @Override
+ public void onVideoTechStateChanged() {
+ update();
+ }
+
+ @Override
+ public void onSessionModificationStateChanged() {
+ for (DialerCallListener listener : mListeners) {
+ listener.onDialerCallSessionModificationStateChange();
+ }
+ }
+
+ @Override
+ public void onCameraDimensionsChanged(int width, int height) {
+ InCallVideoCallCallbackNotifier.getInstance().cameraDimensionsChanged(this, width, height);
+ }
+
+ @Override
+ public void onPeerDimensionsChanged(int width, int height) {
+ InCallVideoCallCallbackNotifier.getInstance().peerDimensionsChanged(this, width, height);
+ }
+
+ @Override
+ public void onVideoUpgradeRequestReceived() {
+ LogUtil.enterBlock("DialerCall.onVideoUpgradeRequestReceived");
+
+ for (DialerCallListener listener : mListeners) {
+ listener.onDialerCallUpgradeToVideo();
+ }
+
+ update();
+ }
+
/**
* Specifies whether a number is in the call history or not. {@link #CALL_HISTORY_STATUS_UNKNOWN}
* means there is no result.
@@ -1191,8 +1108,8 @@
case CONFERENCED:
return true;
default:
+ return false;
}
- return false;
}
public static boolean isDialing(int state) {
@@ -1239,71 +1156,11 @@
}
}
- /**
- * Defines different states of session modify requests, which are used to upgrade to video, or
- * downgrade to audio.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- SESSION_MODIFICATION_STATE_NO_REQUEST,
- SESSION_MODIFICATION_STATE_WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE,
- SESSION_MODIFICATION_STATE_REQUEST_FAILED,
- SESSION_MODIFICATION_STATE_RECEIVED_UPGRADE_TO_VIDEO_REQUEST,
- SESSION_MODIFICATION_STATE_UPGRADE_TO_VIDEO_REQUEST_TIMED_OUT,
- SESSION_MODIFICATION_STATE_UPGRADE_TO_VIDEO_REQUEST_FAILED,
- SESSION_MODIFICATION_STATE_REQUEST_REJECTED,
- SESSION_MODIFICATION_STATE_WAITING_FOR_RESPONSE
- })
- public @interface SessionModificationState {}
-
- public static final int SESSION_MODIFICATION_STATE_NO_REQUEST = 0;
- public static final int SESSION_MODIFICATION_STATE_WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE = 1;
- public static final int SESSION_MODIFICATION_STATE_REQUEST_FAILED = 2;
- public static final int SESSION_MODIFICATION_STATE_RECEIVED_UPGRADE_TO_VIDEO_REQUEST = 3;
- public static final int SESSION_MODIFICATION_STATE_UPGRADE_TO_VIDEO_REQUEST_TIMED_OUT = 4;
- public static final int SESSION_MODIFICATION_STATE_UPGRADE_TO_VIDEO_REQUEST_FAILED = 5;
- public static final int SESSION_MODIFICATION_STATE_REQUEST_REJECTED = 6;
- public static final int SESSION_MODIFICATION_STATE_WAITING_FOR_RESPONSE = 7;
-
- public static class VideoSettings {
-
+ /** Camera direction constants */
+ public static class CameraDirection {
public static final int CAMERA_DIRECTION_UNKNOWN = -1;
public static final int CAMERA_DIRECTION_FRONT_FACING = CameraCharacteristics.LENS_FACING_FRONT;
public static final int CAMERA_DIRECTION_BACK_FACING = CameraCharacteristics.LENS_FACING_BACK;
-
- private int mCameraDirection = CAMERA_DIRECTION_UNKNOWN;
-
- /**
- * Gets the camera direction. if camera direction is set to CAMERA_DIRECTION_UNKNOWN, the video
- * state of the call should be used to infer the camera direction.
- *
- * @see {@link CameraCharacteristics#LENS_FACING_FRONT}
- * @see {@link CameraCharacteristics#LENS_FACING_BACK}
- */
- public int getCameraDir() {
- return mCameraDirection;
- }
-
- /**
- * Sets the camera direction. if camera direction is set to CAMERA_DIRECTION_UNKNOWN, the video
- * state of the call should be used to infer the camera direction.
- *
- * @see {@link CameraCharacteristics#LENS_FACING_FRONT}
- * @see {@link CameraCharacteristics#LENS_FACING_BACK}
- */
- public void setCameraDir(int cameraDirection) {
- if (cameraDirection == CAMERA_DIRECTION_FRONT_FACING
- || cameraDirection == CAMERA_DIRECTION_BACK_FACING) {
- mCameraDirection = cameraDirection;
- } else {
- mCameraDirection = CAMERA_DIRECTION_UNKNOWN;
- }
- }
-
- @Override
- public String toString() {
- return "(CameraDir:" + getCameraDir() + ")";
- }
}
/**
@@ -1394,6 +1251,48 @@
}
}
+ private static class VideoTechManager {
+ private final EmptyVideoTech emptyVideoTech = new EmptyVideoTech();
+ private final VideoTech[] videoTechs;
+ private VideoTech savedTech;
+
+ VideoTechManager(DialerCall call) {
+ String phoneNumber = call.getNumber();
+
+ // Insert order here determines the priority of that video tech option
+ videoTechs =
+ new VideoTech[] {
+ new ImsVideoTech(call, call.mTelecomCall),
+ new RcsVideoShare(
+ EnrichedCallComponent.get(call.mContext).getEnrichedCallManager(),
+ call,
+ phoneNumber != null ? phoneNumber : "")
+ };
+ }
+
+ VideoTech getVideoTech() {
+ if (savedTech != null) {
+ return savedTech;
+ }
+
+ for (VideoTech tech : videoTechs) {
+ if (tech.isAvailable()) {
+ // Remember the first VideoTech that becomes available and always use it
+ savedTech = tech;
+ return savedTech;
+ }
+ }
+
+ return emptyVideoTech;
+ }
+
+ void dispatchCallStateChanged(int newState) {
+ for (VideoTech videoTech : videoTechs) {
+ videoTech.onCallStateChanged(newState);
+ }
+ }
+ }
+
/** Called when canned text responses have been loaded. */
public interface CannedTextResponsesLoadedListener {
void onCannedTextResponsesLoaded(DialerCall call);