Merge "Extend timeout for reusing a call disconnected via NOCIB" into nyc-mr1-dev
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index fed5545..7ae3a29 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -33,7 +33,7 @@
     <string name="respond_via_sms_canned_response_3" msgid="3496079065723960450">"ನಾನು ನಂತರ ನಿಮಗೆ ಕರೆ ಮಾಡುತ್ತೇನೆ."</string>
     <string name="respond_via_sms_canned_response_4" msgid="1698989243040062190">"ಈಗ ಮಾತನಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಂತರ ಮಾಡುವಿರಾ?"</string>
     <string name="respond_via_sms_setting_title" msgid="3754000371039709383">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆಗಳು"</string>
-    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ ಸಂಪಾದಿಸಿ"</string>
+    <string name="respond_via_sms_setting_title_2" msgid="6104662227299493906">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="respond_via_sms_setting_summary" msgid="9150281183930613065"></string>
     <string name="respond_via_sms_edittext_dialog_title" msgid="20379890418289778">"ತ್ವರಿತ ಪ್ರತಿಕ್ರಿಯೆ"</string>
     <string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"<xliff:g id="PHONE_NUMBER">%s</xliff:g> ಗೆ ಸಂದೇಶ ಕಳುಹಿಸಲಾಗಿದೆ."</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 2fdf925..8374edb 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -25,7 +25,7 @@
     <string name="notification_missedCallsMsg" msgid="4575787816055205600">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> 个未接电话"</string>
     <string name="notification_missedCallTicker" msgid="504686252427747209">"来自<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>的未接电话"</string>
     <string name="notification_missedCall_call_back" msgid="2684890353590890187">"回拨"</string>
-    <string name="notification_missedCall_message" msgid="3049928912736917988">"短信"</string>
+    <string name="notification_missedCall_message" msgid="3049928912736917988">"发短信"</string>
     <string name="accessibility_call_muted" msgid="2776111226185342220">"通话已静音。"</string>
     <string name="accessibility_speakerphone_enabled" msgid="1988512040421036359">"扬声器已启用。"</string>
     <string name="respond_via_sms_canned_response_1" msgid="2461606462788380215">"现在无法接听。有什么事吗?"</string>
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index ba4b0e6..f536561 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1158,8 +1158,7 @@
         setConnectionCapabilities(connection.getConnectionCapabilities());
         setConnectionProperties(connection.getConnectionProperties());
         setVideoProvider(connection.getVideoProvider());
-        setVideoState(mCallsManager.getCheckedVideoState(connection.getVideoState(),
-                connection.getPhoneAccount()));
+        setVideoState(connection.getVideoState());
         setRingbackRequested(connection.isRingbackRequested());
         setIsVoipAudioMode(connection.getIsVoipAudioMode());
         setStatusHints(connection.getStatusHints());
@@ -1334,6 +1333,11 @@
         // Check to verify that the call is still in the ringing state. A call can change states
         // between the time the user hits 'answer' and Telecom receives the command.
         if (isRinging("answer")) {
+            if (!isVideoCallingSupported() && VideoProfile.isVideo(videoState)) {
+                // Video calling is not supported, yet the InCallService is attempting to answer as
+                // video.  We will simply answer as audio-only.
+                videoState = VideoProfile.STATE_AUDIO_ONLY;
+            }
             // At this point, we are asking the connection service to answer but we don't assume
             // that it will work. Instead, we wait until confirmation from the connectino service
             // that the call is in a non-STATE_RINGING state before changing the UI. See
@@ -1931,6 +1935,12 @@
      * @param videoState The video state for the call.
      */
     public void setVideoState(int videoState) {
+        // If the phone account associated with this call does not support video calling, then we
+        // will automatically set the video state to audio-only.
+        if (!isVideoCallingSupported()) {
+            videoState = VideoProfile.STATE_AUDIO_ONLY;
+        }
+
         // Track which video states were applicable over the duration of the call.
         // Only track the call state when the call is active or disconnected.  This ensures we do
         // not include the video state when:
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 5377f67..80f1da2 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -157,6 +157,8 @@
                 type = Calls.MISSED_TYPE;
             } else if (disconnectCause == DisconnectCause.ANSWERED_ELSEWHERE) {
                 type = Calls.ANSWERED_EXTERNALLY_TYPE;
+            } else if (disconnectCause == DisconnectCause.REJECTED) {
+                type = Calls.REJECTED_TYPE;
             } else {
                 type = Calls.INCOMING_TYPE;
             }
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 2367138..08f2a98 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -1648,8 +1648,7 @@
                 "new conference call");
         call.setConnectionCapabilities(parcelableConference.getConnectionCapabilities());
         call.setConnectionProperties(parcelableConference.getConnectionProperties());
-        call.setVideoState(
-                getCheckedVideoState(parcelableConference.getVideoState(), phoneAccount));
+        call.setVideoState(parcelableConference.getVideoState());
         call.setVideoProvider(parcelableConference.getVideoProvider());
         call.setStatusHints(parcelableConference.getStatusHints());
         call.putExtras(Call.SOURCE_CONNECTION_SERVICE, parcelableConference.getExtras());
@@ -2172,27 +2171,4 @@
 
       call.setIntentExtras(extras);
     }
-
-    /**
-     * Given a video state and phone account handle, converts the passed video state to
-     * {@link VideoProfile#STATE_AUDIO_ONLY} if the phone account does not support video calling.
-     *
-     * Used to ensure that calls added by a connection service don't try to use video calling if
-     * they have not advertised that they can.
-     *
-     * @param videoState The video state.
-     * @param phoneAccountHandle The phone account handle.
-     * @return {@link VideoProfile#STATE_AUDIO_ONLY} if the phone account does not support video,
-     *      or the original videoState otherwise.
-     */
-    public int getCheckedVideoState(int videoState, PhoneAccountHandle phoneAccountHandle) {
-        if (VideoProfile.isVideo(videoState) && phoneAccountHandle != null) {
-            PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
-                    phoneAccountHandle);
-            if (!account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
-                return VideoProfile.STATE_AUDIO_ONLY;
-            }
-        }
-        return videoState;
-    }
 }
diff --git a/src/com/android/server/telecom/VideoProviderProxy.java b/src/com/android/server/telecom/VideoProviderProxy.java
index 9b2cc7a..a4dfce2 100644
--- a/src/com/android/server/telecom/VideoProviderProxy.java
+++ b/src/com/android/server/telecom/VideoProviderProxy.java
@@ -135,6 +135,26 @@
                     mCall.getAnalytics().addVideoEvent(
                             Analytics.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST,
                             videoProfile.getVideoState());
+
+                    if (!mCall.isVideoCallingSupported() &&
+                            VideoProfile.isVideo(videoProfile.getVideoState())) {
+                        // If video calling is not supported by the phone account, and we receive
+                        // a request to upgrade to video, automatically reject it without informing
+                        // the InCallService.
+
+                        Log.event(mCall, Log.Events.SEND_VIDEO_RESPONSE, "video not supported");
+                        VideoProfile responseProfile = new VideoProfile(
+                                VideoProfile.STATE_AUDIO_ONLY);
+                        try {
+                            mConectionServiceVideoProvider.sendSessionModifyResponse(
+                                    responseProfile);
+                        } catch (RemoteException e) {
+                        }
+
+                        // Don't want to inform listeners of the request as we've just rejected it.
+                        return;
+                    }
+
                     // Inform other Telecom components of the session modification request.
                     for (Listener listener : mListeners) {
                         listener.onSessionModifyRequestReceived(mCall, videoProfile);
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index bd399ae..b8dcb68 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -289,6 +289,31 @@
     }
 
     @MediumTest
+    public void testLogCallDirectionRejected() {
+        when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
+                .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID));
+        Call fakeMissedCall = makeFakeCall(
+                DisconnectCause.REJECTED, // disconnectCauseCode
+                false, // isConference
+                true, // isIncoming
+                1L, // creationTimeMillis
+                1000L, // ageMillis
+                TEL_PHONEHANDLE, // callHandle
+                mDefaultAccountHandle, // phoneAccountHandle
+                NO_VIDEO_STATE, // callVideoState
+                POST_DIAL_STRING, // postDialDigits
+                VIA_NUMBER_STRING, // viaNumber
+                null
+        );
+
+        mCallLogManager.onCallStateChanged(fakeMissedCall, CallState.ACTIVE,
+                CallState.DISCONNECTED);
+        ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID);
+        assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE),
+                Integer.valueOf(Calls.REJECTED_TYPE));
+    }
+
+    @MediumTest
     public void testCreationTimeAndAge() {
         when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class)))
                 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID));