Merge c2da3dd9e25c512708855a0414cdd8b31eebdd0f on remote branch
Change-Id: I22820baeab8670103674b0ce2750d44e414cd6e2
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_cloud_queue_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_cloud_queue_24.xml
new file mode 100755
index 0000000..5010725
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_cloud_queue_24.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h0.71C7.37,7.69 9.48,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3s-1.34,3 -3,3z"/>
+</vector>
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_comment_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_comment_24.xml
new file mode 100755
index 0000000..eb8acb0
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_comment_24.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M21.99,4c0,-1.1 -0.89,-2 -1.99,-2L4,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h14l4,4 -0.01,-18zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
+</vector>
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_content_copy_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_content_copy_24.xml
new file mode 100755
index 0000000..d5ab870
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_content_copy_24.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
+</vector>
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_favorite_border_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_favorite_border_24.xml
new file mode 100755
index 0000000..0fc76be
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_favorite_border_24.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z"/>
+</vector>
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_info_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_info_24.xml
new file mode 100755
index 0000000..eeb02ad
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_info_24.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
+</vector>
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_money_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_money_24.xml
new file mode 100755
index 0000000..4b1bd98
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_money_24.xml
@@ -0,0 +1,34 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M5,8h2v8L5,16zM12,8L9,8c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h3c0.55,0 1,-0.45 1,-1L13,9c0,-0.55 -0.45,-1 -1,-1zM11,14h-1v-4h1v4zM18,8h-3c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h3c0.55,0 1,-0.45 1,-1L19,9c0,-0.55 -0.45,-1 -1,-1zM17,14h-1v-4h1v4z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M2,4v16h20L22,4L2,4zM4,18L4,6h16v12L4,18z"/>
+</vector>
diff --git a/assets/quantum/res/drawable/quantum_ic_baseline_share_24.xml b/assets/quantum/res/drawable/quantum_ic_baseline_share_24.xml
new file mode 100755
index 0000000..3897853
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_baseline_share_24.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions are
+ ~ met:
+ ~ * Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ * Redistributions in binary form must reproduce the above
+ ~ copyright notice, this list of conditions and the following
+ ~ disclaimer in the documentation and/or other materials provided
+ ~ with the distribution.
+ ~ * Neither the name of The Linux Foundation nor the names of its
+ ~ contributors may be used to endorse or promote products derived
+ ~ from this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ ~ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ ~ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ ~ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ ~ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ ~ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ ~ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ ~ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<vector android:height="24dp" android:tint="#989898"
+ android:viewportHeight="24" android:viewportWidth="24"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
+</vector>
diff --git a/java/com/android/incallui/BottomSheetHelper.java b/java/com/android/incallui/BottomSheetHelper.java
index 5bb09f9..7a4c868 100755
--- a/java/com/android/incallui/BottomSheetHelper.java
+++ b/java/com/android/incallui/BottomSheetHelper.java
@@ -477,6 +477,11 @@
}
@Override
+ public void onSipDtmfChanged(int bitMask) {
+ //No-op
+ }
+
+ @Override
public void onPrimaryCallChanged(DialerCall call) {
LogUtil.d("BottomSheetHelper.onPrimaryCallChanged", "");
dismissBottomSheet();
@@ -656,14 +661,15 @@
}
private void maybeUpdateDialpadOptionInMap() {
- // Enable dialpad option in bottomsheet only for video calls.
+ // Enable dialpad option in bottomsheet for video calls or video CRS.
// When video call is held, UI displays onscreen dialpad button
// similar to volte calls.
final int primaryCallState = mCall.getNonConferenceState();
- final boolean enable = mCall.isVideoCall()
- && primaryCallState != DialerCallState.INCOMING
- && primaryCallState != DialerCallState.CALL_WAITING
- && primaryCallState != DialerCallState.ONHOLD;
+ final boolean enable = (mCall.isVideoCall()
+ && primaryCallState != DialerCallState.INCOMING
+ && primaryCallState != DialerCallState.CALL_WAITING
+ && primaryCallState != DialerCallState.ONHOLD)
+ || QtiCallUtils.isVideoCrs(mCall);
moreOptionsMap.put(mResources.getString(R.string.dialpad_label), enable);
}
diff --git a/java/com/android/incallui/CallButtonPresenter.java b/java/com/android/incallui/CallButtonPresenter.java
index 9304274..9df5e90 100755
--- a/java/com/android/incallui/CallButtonPresenter.java
+++ b/java/com/android/incallui/CallButtonPresenter.java
@@ -443,6 +443,11 @@
inCallButtonUi.enableButton(InCallButtonIds.BUTTON_PAUSE_VIDEO, false);
}
+ @Override
+ public void sendSipDtmfClicked(int buttonId) {
+ InCallPresenter.getInstance().sendSipDtmfClicked(buttonId);
+ }
+
private void updateCamera(boolean useFrontFacingCamera) {
InCallCameraManager cameraManager = InCallPresenter.getInstance().getInCallCameraManager();
cameraManager.setUseFrontFacingCamera(useFrontFacingCamera);
@@ -567,6 +572,7 @@
inCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true);
inCallButtonUi.showButton(InCallButtonIds.BUTTON_MERGE, showMerge);
+ updateSipDtmfButtons(InCallPresenter.getInstance().getSipDtmfBitMask());
inCallButtonUi.updateButtonStates();
if (BottomSheetHelper.getInstance().shallShowMoreButton(getActivity())) {
BottomSheetHelper.getInstance().updateMap();
@@ -629,6 +635,37 @@
}
@Override
+ public void onSipDtmfChanged(int sipDtmfbitMap) {
+ if (inCallButtonUi != null && call != null) {
+ updateSipDtmfButtons(sipDtmfbitMap);
+ }
+ }
+
+ private void updateSipDtmfButtons(int sipDtmfbitMap) {
+ boolean enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_LIKE)
+ == SipDtmfUtil.SIP_DTMF_TYPE_LIKE;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_LIKE, enable);
+ enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_SHARE)
+ == SipDtmfUtil.SIP_DTMF_TYPE_SHARE;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_SHARE, enable);
+ enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_FAVORITE)
+ == SipDtmfUtil.SIP_DTMF_TYPE_FAVORITE;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_FAVORITE, enable);
+ enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_COPY)
+ == SipDtmfUtil.SIP_DTMF_TYPE_COPY;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_COPY, enable);
+ enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_COMMENT)
+ == SipDtmfUtil.SIP_DTMF_TYPE_COMMENT;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_COMMENT, enable);
+ enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_DETAIL)
+ == SipDtmfUtil.SIP_DTMF_TYPE_DETAIL;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_DETAIL, enable);
+ enable = (sipDtmfbitMap & SipDtmfUtil.SIP_DTMF_TYPE_RED_ENVELOPE)
+ == SipDtmfUtil.SIP_DTMF_TYPE_RED_ENVELOPE;
+ inCallButtonUi.showButton(InCallButtonIds.BUTTON_RED_ENVELOPE, enable);
+ }
+
+ @Override
public void onSaveInstanceState(Bundle outState) {}
@Override
diff --git a/java/com/android/incallui/CallCardPresenter.java b/java/com/android/incallui/CallCardPresenter.java
index 4ef35d3..f4c47af 100755
--- a/java/com/android/incallui/CallCardPresenter.java
+++ b/java/com/android/incallui/CallCardPresenter.java
@@ -1105,6 +1105,11 @@
//No-op
}
+ @Override
+ public void onSipDtmfChanged(int bitMask) {
+ //No-op
+ }
+
private boolean shouldShowEndCallButton(DialerCall primary, int callState) {
if (primary == null) {
return false;
diff --git a/java/com/android/incallui/DialpadPresenter.java b/java/com/android/incallui/DialpadPresenter.java
index e6fbdc2..9196fda 100644
--- a/java/com/android/incallui/DialpadPresenter.java
+++ b/java/com/android/incallui/DialpadPresenter.java
@@ -35,6 +35,9 @@
super.onUiReady(ui);
InCallPresenter.getInstance().addListener(this);
call = CallList.getInstance().getOutgoingOrActive();
+ if (call == null) {
+ call = CallList.getInstance().getIncomingCall();
+ }
}
@Override
@@ -49,6 +52,9 @@
InCallPresenter.InCallState newState,
CallList callList) {
call = callList.getOutgoingOrActive();
+ if (call == null) {
+ call = callList.getIncomingCall();
+ }
Log.d(this, "DialpadPresenter mCall = " + call);
}
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index 59ad580..40adbc6 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -1011,7 +1011,8 @@
return didShowInCallScreen
|| didShowVideoCallScreen
|| didShowRttCallScreen
- || didShowSpeakEasyScreen;
+ || didShowSpeakEasyScreen
+ || didShowAnswerScreen;
}
public void dismissKeyguard(boolean dismiss) {
@@ -1589,7 +1590,12 @@
shouldAllowAnswerAndRelease(call),
CallList.getInstance().getBackgroundCall() != null,
getSpeakEasyCallManager().isAvailable(getApplicationContext())
- && call.isSpeakEasyEligible());
+ && call.isSpeakEasyEligible(),
+ QtiCallUtils.isVideoCrs(call),
+ QtiCallUtils.isVideoCallOriginally(call));
+ LogUtil.d("InCallActivity.showAnswerScreenFragment", "Is video call originally : "
+ + QtiCallUtils.isVideoCallOriginally(call)
+ + " isVideoCrs : " + QtiCallUtils.isVideoCrs(call));
transaction.add(R.id.main, answerScreen.getAnswerScreenFragment(), Tags.ANSWER_SCREEN);
Logger.get(this).logScreenView(ScreenEvent.Type.INCOMING_CALL, this);
@@ -1755,6 +1761,9 @@
if (didShowVideoCallScreen) {
inCallScreen = (InCallScreen) getVideoCallScreen();
}
+ if (didShowAnswerScreen) {
+ inCallScreen = (InCallScreen) getAnswerScreen();
+ }
return inCallScreen;
}
diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java
index 95f8378..e317139 100644
--- a/java/com/android/incallui/InCallPresenter.java
+++ b/java/com/android/incallui/InCallPresenter.java
@@ -89,6 +89,14 @@
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.codeaurora.ims.CrsCrbtManager;
+import org.codeaurora.ims.CrsCrbtListenerBase;
+import org.codeaurora.ims.QtiCallConstants;
+import org.codeaurora.ims.QtiImsException;
+import org.codeaurora.ims.QtiImsExtListenerBaseImpl;
+import org.codeaurora.ims.QtiImsExtConnector;
+import org.codeaurora.ims.QtiImsExtManager;
+import org.codeaurora.ims.utils.QtiImsExtUtils;
/**
* Takes updates from the CallList and notifies the InCallActivity (UI) of the changes. Responsible
* for starting the activity for a new call and finishing the activity when all calls are
@@ -279,6 +287,13 @@
private boolean automaticallyMutedByAddCall = false;
private Toast errorToast;
+ private QtiImsExtConnector mQtiImsExtConnector;
+ private QtiImsExtManager mQtiImsExtManager;
+ private CrsCrbtManager mCrsCrbtManager = null;
+ private final Handler mHandler = new Handler();
+ private static boolean mIsPreparatoryMode = false;
+ private DialerCall mCrsCrbtCall = null;
+ private int mCacheSipDtmfBitMask = SipDtmfUtil.SIP_DTMF_TYPE_INVALID;
/** Inaccessible constructor. Must use getRunningInstance() to get this singleton. */
@VisibleForTesting
@@ -426,6 +441,141 @@
Trace.endSection();
}
+ private void createQtiImsExtConnector(Context context, DialerCall call) {
+ if (call.equals(mCrsCrbtCall)) {
+ return;
+ }
+ clearCrsCrbtState();
+ mCrsCrbtCall = call;
+ try {
+ mQtiImsExtConnector = new QtiImsExtConnector(context,
+ new QtiImsExtConnector.IListener() {
+ @Override
+ public void onConnectionAvailable(QtiImsExtManager qtiImsExtManager) {
+ LogUtil.i("InCallPresenter.setCrsCrbtListener", "onConnectionAvailable");
+ mQtiImsExtManager = qtiImsExtManager;
+ setCrsCrbtListener();
+ }
+ @Override
+ public void onConnectionUnavailable() {
+ mQtiImsExtManager = null;
+ }
+ });
+ mQtiImsExtConnector.connect();
+ } catch (QtiImsException e) {
+ LogUtil.e("InCallPresenter.createQtiImsExtConnector",
+ "Unable to create QtiImsExtConnector");
+ }
+ }
+
+ private void clearCrsCrbtState() {
+ mIsPreparatoryMode = false;
+ mCrsCrbtCall = null;
+ mCacheSipDtmfBitMask = SipDtmfUtil.SIP_DTMF_TYPE_INVALID;
+ if (mQtiImsExtConnector != null) {
+ removeCrsCrbtListener();
+ mQtiImsExtConnector.disconnect();
+ mQtiImsExtConnector = null;
+ mQtiImsExtManager = null;
+ }
+ }
+
+ private void setCrsCrbtListener() {
+ if (mQtiImsExtManager == null) {
+ LogUtil.d("InCallPresenter.setCrsCrbtListener",
+ "mQtiImsExtManager is null");
+ return;
+ }
+ try {
+ mCrsCrbtManager = mQtiImsExtManager.createCrsCrbtManager(
+ QtiCallUtils.getPhoneId(mCrsCrbtCall));
+ } catch (QtiImsException e) {
+ LogUtil.e("InCallPresenter.setCrsCrbtListener", "exception " + e);
+ return;
+ }
+ if (mCrsCrbtManager == null) {
+ LogUtil.d("InCallPresenter.setCrsCrbtListener",
+ "mCrsCrbtManager is null");
+ return;
+ }
+ try {
+ LogUtil.d("InCallPresenter.setCrsCrbtListener", "setCrsDataUpdateListener");
+ mCrsCrbtManager.setCrsCrbtListener(mCrsDataUpdateListener);
+ } catch (QtiImsException e) {
+ LogUtil.e("InCallPresenter.setCrsCrbtListener", "exception " + e);
+ }
+ }
+
+ private void removeCrsCrbtListener() {
+ if (mCrsCrbtManager == null) {
+ LogUtil.d("InCallPresenter.removeCrsCrbtListener",
+ "mCrsCrbtManager is null");
+ return;
+ }
+ try {
+ LogUtil.d("InCallPresenter.removeCrsCrbtListener", "");
+ mCrsCrbtManager.removeCrsCrbtListener(mCrsDataUpdateListener);
+ } catch (QtiImsException e) {
+ LogUtil.e("InCallPresenter.removeCrsCrbtListener", "exception " + e);
+ }
+ }
+
+ private CrsCrbtListenerBase mCrsDataUpdateListener =
+ new CrsCrbtListenerBase() {
+ @Override
+ public void onCrsDataUpdated(int phoneId, int crsType, boolean isPreparatory) {
+ LogUtil.i("InCallPresenter.onCrsDataUpdated", "crs type: "
+ + crsType + " isPreparatory:: " + isPreparatory );
+ if (!isPreparatory && mIsPreparatoryMode && mCrsCrbtCall!= null) {
+ onIncomingCall(mCrsCrbtCall);
+ mIsPreparatoryMode = false;
+ }
+ }
+
+ @Override
+ public void onSipDtmfReceived(int phoneId, String config) {
+ LogUtil.i("InCallPresenter.onSipDtmfReceived", "phoneId : %s, sipDtmfConfig : %s ",
+ phoneId, config);
+ //cache this bitMap due to sometimes SIP DTMF come early and UI is not shown,
+ //will use this cache value to update buttons for MT call CRS and MO CRBT call.
+ mCacheSipDtmfBitMask = SipDtmfUtil.toButtonBitmask(config);
+ for (InCallEventListener listener : inCallEventListeners) {
+ mHandler.post(()->listener.onSipDtmfChanged(mCacheSipDtmfBitMask));
+ }
+ }
+ };
+
+ /**
+ * Send SIP DTMF to modem/network when user clicks the icons in CRS/CRBT UI.
+ */
+ public void sendSipDtmfClicked(int buttonId) {
+ LogUtil.i("InCallPresenter.sendSipDtmf", "sipDtmf is : " + buttonId);
+ if (mCrsCrbtManager == null) {
+ LogUtil.i("InCallPresenter.sendSipDtmf", "mCrsCrbtManager is null");
+ return;
+ }
+ try {
+ mCrsCrbtManager.sendSipDtmf(SipDtmfUtil.toDtmfString(buttonId));
+ } catch (QtiImsException e) {
+ LogUtil.e("InCallPresenter.sendSipDtmf", "exception " + e);
+ }
+ }
+
+ /**
+ * this function to control show/hide DTMF icons in UI when have
+ * valid bitmap config from low layer.
+ */
+ public void updateSipDtmfMaskToUi(boolean show) {
+ LogUtil.i("InCallPresenter.updateSipDtmfMaskToUi", "show : " + show);
+ for (InCallEventListener listener : inCallEventListeners) {
+ listener.onSipDtmfChanged(show ?
+ mCacheSipDtmfBitMask : SipDtmfUtil.SIP_DTMF_TYPE_INVALID);
+ }
+ }
+
+ public int getSipDtmfBitMask() {
+ return mCacheSipDtmfBitMask;
+ }
/**
* Return whether we should start call in bubble mode and not show InCallActivity. The call mode
* should be set in CallConfiguration in EXTRA_OUTGOING_CALL_EXTRAS when starting a call intent.
@@ -908,6 +1058,12 @@
}
if (primary != null) {
onForegroundCallChanged(primary);
+ int phoneId = QtiCallUtils.getPhoneId(primary);
+ if (phoneId != QtiCallConstants.INVALID_PHONE_ID
+ && (QtiImsExtUtils.isVideoCrbtSupported(phoneId, context)
+ ||QtiImsExtUtils.isVideoCrsSupported(phoneId, context))) {
+ createQtiImsExtConnector(context, primary);
+ }
}
// notify listeners of new state
@@ -978,6 +1134,30 @@
/** Called when there is a new incoming call. */
@Override
public void onIncomingCall(DialerCall call) {
+ int phoneId = QtiCallUtils.getPhoneId(call);
+ if (QtiCallUtils.isVideoCrs(call)
+ && (phoneId != QtiCallConstants.INVALID_PHONE_ID)
+ && QtiImsExtUtils.isVideoCrsSupported(phoneId, context)) {
+ createQtiImsExtConnector(context, call);
+ //Modem need to negotiate with network for CRS RTP after receive incoming call,
+ //before negotiation finish, telephony will receive call as preparatory mode
+ //and show nothing to user. Preparatory value may have gap between UI and vendor
+ //IMS due to time consuming to pass the value to UI, so use side car API
+ //isPreparatorySession to get value in vendor directly.
+ if (mCrsCrbtManager != null && call != null) {
+ try {
+ boolean isPreparatory = mCrsCrbtManager.isPreparatorySession(call.getId());
+ if (isPreparatory) {
+ LogUtil.i("InCallPresenter.onIncomingCall",
+ "enter preparatory mode for CRS call, do not show notificaion to user");
+ mIsPreparatoryMode = true;
+ return;
+ }
+ } catch (QtiImsException e) {
+ LogUtil.e("InCallPresenter.onIncomingCall", "exception " + e);
+ }
+ }
+ }
Trace.beginSection("InCallPresenter.onIncomingCall");
InCallState newState = startOrFinishUi(InCallState.INCOMING);
InCallState oldState = inCallState;
@@ -1056,6 +1236,7 @@
public void onDisconnect(DialerCall call) {
showDialogOrToastForDisconnectedCall(call);
+ clearCrsCrbtState();
// We need to do the run the same code as onCallListChange.
onCallListChange(callList);
@@ -1268,6 +1449,10 @@
proximitySensor.onInCallShowing(showing);
}
+ if (statusBarNotifier != null) {
+ statusBarNotifier.updateNotification();
+ }
+
if (showing) {
refreshMuteState();
} else {
@@ -2063,6 +2248,7 @@
void onFullscreenModeChanged(boolean isFullscreenMode);
void onSendStaticImageStateChanged(boolean isEnabled);
void onOutgoingVideoSourceChanged(int videoSource);
+ void onSipDtmfChanged(int bitMask);
}
public interface InCallUiListener {
diff --git a/java/com/android/incallui/OrientationModeHandler.java b/java/com/android/incallui/OrientationModeHandler.java
index 1aa83cb..54b87d0 100644
--- a/java/com/android/incallui/OrientationModeHandler.java
+++ b/java/com/android/incallui/OrientationModeHandler.java
@@ -263,4 +263,9 @@
@Override
public void onOutgoingVideoSourceChanged(int videoSource) {}
+
+ @Override
+ public void onSipDtmfChanged(int bitMask) {
+ //No-op
+ }
}
diff --git a/java/com/android/incallui/QtiCallUtils.java b/java/com/android/incallui/QtiCallUtils.java
index c8152cd..71e0e26 100644
--- a/java/com/android/incallui/QtiCallUtils.java
+++ b/java/com/android/incallui/QtiCallUtils.java
@@ -37,6 +37,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -74,6 +75,7 @@
// ensure this extra is same the one defined in ConferenceURIDialer.java
public static final String EXTRA_ADD_PARTICIPANT_NUMBER =
"org.codeaurora.extra.ADD_PARTICIPANT_NUMBER";
+ private static final int UNKNOWN_CALL_TYPE = -1;
/**
* Returns true if it is emergency number else false
@@ -233,6 +235,10 @@
final int requestedVideoState = call.getVideoTech().getRequestedVideoState();
+ if (isVideoCrs(call)) {
+ return context.getString(R.string.incoming_video_crs_call);
+ }
+
if (QtiCallUtils.isVideoRxOnly(call)
|| requestedVideoState == VideoProfile.STATE_RX_ENABLED) {
return context.getString(R.string.incoming_video_rx_call);
@@ -536,4 +542,70 @@
}
return hasConfCall;
}
+
+ //Checks if incoming call has video CRS
+ public static boolean isVideoCrs(DialerCall call) {
+ if (call == null) {
+ Log.w(LOG_TAG, "call is null");
+ return false;
+ }
+ if (call.getState() != DialerCallState.INCOMING) {
+ Log.w(LOG_TAG, "call is not incoming state.");
+ return false;
+ }
+ Bundle extras = call.getExtras();
+ if (extras == null) {
+ return false;
+ }
+ int crsType = extras.getInt(QtiCallConstants.EXTRA_CRS_TYPE,
+ QtiCallConstants.CRS_TYPE_INVALID);
+ return crsType == (QtiCallConstants.CRS_TYPE_VIDEO | QtiCallConstants.CRS_TYPE_AUDIO);
+ }
+
+ //Checks what's original call type of video CRS
+ private static int getOriginalCallType(DialerCall call) {
+ if (!isVideoCrs(call)) {
+ return call.getVideoState();
+ }
+ //Ideally if call has video CRS, then original call type should be there.
+ Bundle extras = call.getExtras();
+ if (extras == null) {
+ return UNKNOWN_CALL_TYPE;
+ }
+ return extras.getInt(QtiCallConstants.EXTRA_ORIGINAL_CALL_TYPE,
+ UNKNOWN_CALL_TYPE);
+ }
+
+ //Checks if original call type is VT with or without video CRS
+ public static boolean isVideoCallOriginally(DialerCall call) {
+ if (!isVideoCrs(call)) {
+ return call == null ? false : call.isVideoCall();
+ }
+ int originalCallType = getOriginalCallType(call);
+ if (originalCallType == UNKNOWN_CALL_TYPE) {
+ Log.w(LOG_TAG, "Video CRS call has no original call type, it's not expected.");
+ }
+ return VideoProfile.STATE_BIDIRECTIONAL == originalCallType;
+ }
+
+ public static boolean isPreparatory(DialerCall call) {
+ if (!isVideoCrs(call)) {
+ return false;
+ }
+ Bundle extras = call.getExtras();
+ if (extras == null) {
+ return false;
+ }
+ return extras.getBoolean(QtiCallConstants.EXTRA_IS_PREPARATORY, false);
+ }
+
+ public static int getPhoneId(DialerCall call) {
+ if (call == null) {
+ return QtiCallConstants.INVALID_PHONE_ID;
+ }
+ final Bundle extras = call.getExtras();
+ return ((extras == null) ? QtiCallConstants.INVALID_PHONE_ID :
+ extras.getInt(QtiImsExtUtils.QTI_IMS_PHONE_ID_EXTRA_KEY,
+ QtiCallConstants.INVALID_PHONE_ID));
+ }
}
diff --git a/java/com/android/incallui/SipDtmfUtil.java b/java/com/android/incallui/SipDtmfUtil.java
new file mode 100644
index 0000000..2b7a35d
--- /dev/null
+++ b/java/com/android/incallui/SipDtmfUtil.java
@@ -0,0 +1,121 @@
+/**
+ Copyright (c) 2021 The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+* * Neither the name of The Linux Foundation nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+package com.android.incallui;
+
+import com.android.incallui.incall.protocol.InCallButtonIds;
+
+public class SipDtmfUtil {
+
+ public static final int SIP_DTMF_TYPE_INVALID = 0;
+ public static final int SIP_DTMF_TYPE_LIKE = 1 << 0;
+ public static final int SIP_DTMF_TYPE_SHARE = 1 << 1;
+ public static final int SIP_DTMF_TYPE_FAVORITE = 1 << 2;
+ public static final int SIP_DTMF_TYPE_COPY = 1 << 3;
+ public static final int SIP_DTMF_TYPE_COMMENT = 1 << 4;
+ public static final int SIP_DTMF_TYPE_DETAIL = 1 << 5;
+ public static final int SIP_DTMF_TYPE_RED_ENVELOPE = 1 << 6;
+
+ private static final String IN_SIP_DTMF_LIKE_MSG = "2*001";
+ private static final String IN_SIP_DTMF_SHARE_MSG = "2*002";
+ private static final String IN_SIP_DTMF_FAVORITE_MSG = "2*003";
+ private static final String IN_SIP_DTMF_COPY_MSG = "2*004";
+ private static final String IN_SIP_DTMF_COMMENT_MSG = "2*005";
+ private static final String IN_SIP_DTMF_DETAIL_MSG = "2*006";
+ private static final String IN_SIP_DTMF_RED_ENVELOPE = "2*007";
+
+ private static final String OUT_SIP_DTMF_LIKE_MSG = "1*001#";
+ private static final String OUT_SIP_DTMF_SHARE_MSG = "1*002#";
+ private static final String OUT_SIP_DTMF_FAVORITE_MSG = "1*003#";
+ private static final String OUT_SIP_DTMF_COPY_MSG = "1*004#";
+ private static final String OUT_SIP_DTMF_COMMENT_MSG = "1*005#";
+ private static final String OUT_SIP_DTMF_DETAIL_MSG = "1*006#";
+ private static final String OUT_SIP_DTMF_RED_ENVELOPE = "1*007#";
+
+ /**
+ * it takes DTMF text delimited by # and return bitmask which represents
+ * buttons in following order Like|Share|...|Red Envelope, 1 in the bitmask
+ * means that the button should be visible (presented to the user).
+ */
+ public static int toButtonBitmask(String fromDtmf) {
+ int sipDtmfBitMask = SIP_DTMF_TYPE_INVALID;
+ if (fromDtmf == null) {
+ return sipDtmfBitMask;
+ }
+ String[] splitSipDtmf = fromDtmf.split("#");
+ for (String config : splitSipDtmf) {
+ sipDtmfBitMask |= convertConfigToBitmask(config);
+ }
+ return sipDtmfBitMask;
+ }
+
+ /**
+ * it converts button Id to DTMF text string and send text to modem/network
+ */
+ public static String toDtmfString(int fromButtonId) {
+ switch (fromButtonId){
+ case InCallButtonIds.BUTTON_LIKE:
+ return OUT_SIP_DTMF_LIKE_MSG;
+ case InCallButtonIds.BUTTON_SHARE:
+ return OUT_SIP_DTMF_SHARE_MSG;
+ case InCallButtonIds.BUTTON_FAVORITE:
+ return OUT_SIP_DTMF_FAVORITE_MSG;
+ case InCallButtonIds.BUTTON_COPY:
+ return OUT_SIP_DTMF_COPY_MSG;
+ case InCallButtonIds.BUTTON_COMMENT:
+ return OUT_SIP_DTMF_COMMENT_MSG;
+ case InCallButtonIds.BUTTON_DETAIL:
+ return OUT_SIP_DTMF_DETAIL_MSG;
+ case InCallButtonIds.BUTTON_RED_ENVELOPE:
+ return OUT_SIP_DTMF_RED_ENVELOPE;
+ default:
+ return "";
+ }
+ }
+
+ private static int convertConfigToBitmask(String config) {
+ switch (config){
+ case IN_SIP_DTMF_LIKE_MSG:
+ return SIP_DTMF_TYPE_LIKE;
+ case IN_SIP_DTMF_SHARE_MSG:
+ return SIP_DTMF_TYPE_SHARE;
+ case IN_SIP_DTMF_FAVORITE_MSG:
+ return SIP_DTMF_TYPE_FAVORITE;
+ case IN_SIP_DTMF_COPY_MSG:
+ return SIP_DTMF_TYPE_COPY;
+ case IN_SIP_DTMF_COMMENT_MSG:
+ return SIP_DTMF_TYPE_COMMENT;
+ case IN_SIP_DTMF_DETAIL_MSG:
+ return SIP_DTMF_TYPE_DETAIL;
+ case IN_SIP_DTMF_RED_ENVELOPE:
+ return SIP_DTMF_TYPE_RED_ENVELOPE;
+ default:
+ return SIP_DTMF_TYPE_INVALID;
+ }
+ }
+}
diff --git a/java/com/android/incallui/StatusBarNotifier.java b/java/com/android/incallui/StatusBarNotifier.java
index 75677bd..330eee4 100755
--- a/java/com/android/incallui/StatusBarNotifier.java
+++ b/java/com/android/incallui/StatusBarNotifier.java
@@ -465,7 +465,7 @@
addSpeakerAction(builder, callAudioState);
} else if (state == DialerCallState.INCOMING || state == DialerCallState.CALL_WAITING) {
addDismissAction(builder);
- if (call.isVideoCall()) {
+ if (call.isVideoCall() && QtiCallUtils.isVideoCallOriginally(call)) {
addVideoCallAction(builder);
} else {
addAnswerAction(builder);
@@ -672,7 +672,7 @@
return R.drawable.quantum_ic_phone_paused_vd_theme_24;
} else if (call.getVideoTech().getSessionModificationState()
== SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST
- || call.isVideoCall()) {
+ || (call.isVideoCall() && QtiCallUtils.isVideoCallOriginally(call))) {
return R.drawable.quantum_ic_videocam_vd_white_24;
} else if (call.hasProperty(PROPERTY_HIGH_DEF_AUDIO)
&& MotorolaUtils.shouldShowHdIconInNotification(context)) {
@@ -724,7 +724,7 @@
resId = R.string.notification_incoming_call_wifi_template;
} else if (call.getAccountHandle() != null && hasMultiplePhoneAccounts(call)) {
return getMultiSimIncomingText(call);
- } else if (call.isVideoCall()) {
+ } else if (call.isVideoCall() && QtiCallUtils.isVideoCallOriginally(call)) {
resId = R.string.notification_incoming_video_call;
} else {
resId = R.string.notification_incoming_call;
diff --git a/java/com/android/incallui/VideoCallPresenter.java b/java/com/android/incallui/VideoCallPresenter.java
index cf0b9f9..e0b2f66 100644
--- a/java/com/android/incallui/VideoCallPresenter.java
+++ b/java/com/android/incallui/VideoCallPresenter.java
@@ -839,6 +839,12 @@
}
}
+
+ @Override
+ public void onSipDtmfChanged(int bitMask) {
+ //No-op
+ }
+
private void enterScreenShare() {
LogUtil.i("VideoCallPresenter.enterScreenShare", "enter screen share");
if (mQtiImsExtConnector == null) {
@@ -1158,7 +1164,8 @@
public boolean isIncomingVideoAvailableForEarlyMedia() {
return primaryCall != null
&& (primaryCall.getState() == DialerCallState.DIALING
- || primaryCall.getState() == DialerCallState.CONNECTING)
+ || primaryCall.getState() == DialerCallState.CONNECTING
+ || primaryCall.getState() == DialerCallState.INCOMING)
&& mIsIncomingVideoAvailable;
}
@@ -1897,6 +1904,8 @@
if (primaryCall == null) {
return;
}
+ InCallPresenter.getInstance()
+ .updateSipDtmfMaskToUi(isIncomingVideoAvailableForEarlyMedia());
showVideoUi(
primaryCall.getVideoState(),
primaryCall.getState(),
diff --git a/java/com/android/incallui/answer/bindings/AnswerBindings.java b/java/com/android/incallui/answer/bindings/AnswerBindings.java
index c370d74..f761c31 100644
--- a/java/com/android/incallui/answer/bindings/AnswerBindings.java
+++ b/java/com/android/incallui/answer/bindings/AnswerBindings.java
@@ -30,7 +30,9 @@
boolean isSelfManagedCamera,
boolean allowAnswerAndRelease,
boolean hasCallOnHold,
- boolean allowSpeakEasy) {
+ boolean allowSpeakEasy,
+ boolean hasCrs,
+ boolean isVideoCallOriginally) {
return AnswerFragment.newInstance(
callId,
isRttCall,
@@ -39,6 +41,8 @@
isSelfManagedCamera,
allowAnswerAndRelease,
hasCallOnHold,
- allowSpeakEasy);
+ allowSpeakEasy,
+ hasCrs,
+ isVideoCallOriginally);
}
}
diff --git a/java/com/android/incallui/answer/impl/AnswerFragment.java b/java/com/android/incallui/answer/impl/AnswerFragment.java
index 42adcd0..2f62599 100644
--- a/java/com/android/incallui/answer/impl/AnswerFragment.java
+++ b/java/com/android/incallui/answer/impl/AnswerFragment.java
@@ -30,6 +30,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Trace;
+import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
@@ -37,6 +38,7 @@
import android.support.annotation.StringRes;
import android.support.annotation.VisibleForTesting;
import android.support.v4.app.Fragment;
+import android.telecom.CallAudioState;
import android.telecom.VideoProfile;
import android.text.TextUtils;
import android.transition.TransitionManager;
@@ -63,8 +65,10 @@
import com.android.dialer.util.ViewUtil;
import com.android.incallui.BottomSheetHelper;
import com.android.incallui.ExtBottomSheetFragment.ExtBottomSheetActionCallback;
+import com.android.incallui.InCallPresenter;
import com.android.incallui.VideoCallPresenter;
import com.android.incallui.QtiCallUtils;
+import com.android.incallui.SipDtmfUtil;
import com.android.incallui.answer.impl.CreateCustomSmsDialogFragment.CreateCustomSmsHolder;
import com.android.incallui.answer.impl.SmsBottomSheetFragment.SmsSheetHolder;
import com.android.incallui.answer.impl.affordance.SwipeButtonHelper.Callback;
@@ -80,6 +84,11 @@
import com.android.incallui.call.state.DialerCallState;
import com.android.incallui.contactgrid.ContactGridManager;
import com.android.incallui.incall.protocol.ContactPhotoType;
+import com.android.incallui.incall.protocol.InCallButtonIds;
+import com.android.incallui.incall.protocol.InCallButtonIdsExtension;
+import com.android.incallui.incall.protocol.InCallButtonUi;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
+import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
import com.android.incallui.incall.protocol.InCallScreen;
import com.android.incallui.incall.protocol.InCallScreenDelegate;
import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
@@ -93,6 +102,8 @@
import com.android.incallui.speakeasy.Annotations.SpeakEasyChipResourceId;
import com.android.incallui.speakeasy.SpeakEasyComponent;
import com.android.incallui.util.AccessibilityUtil;
+import com.android.incallui.video.impl.CheckableImageButton;
+import com.android.incallui.video.impl.CheckableImageButton.OnCheckedChangeListener;
import com.android.incallui.video.protocol.VideoCallScreen;
import com.android.incallui.videotech.utils.VideoUtils;
import com.google.common.base.Optional;
@@ -105,10 +116,12 @@
public class AnswerFragment extends Fragment
implements AnswerScreen,
InCallScreen,
+ InCallButtonUi,
SmsSheetHolder,
CreateCustomSmsHolder,
AnswerMethodHolder,
OnClickListener,
+ OnCheckedChangeListener,
ExtBottomSheetActionCallback,
MultimediaFragment.Holder {
@@ -132,6 +145,10 @@
static final String ARG_ALLOW_SPEAK_EASY = "allow_speak_easy";
+ static final String ARG_HAS_VIDEO_CRS = "has_video_crs";
+
+ static final String ARG_IS_VIDEO_ORIGINALLY = "is_video_call_originally";
+
private static final String STATE_HAS_ANIMATED_ENTRY = "hasAnimated";
private static final int HINT_SECONDARY_SHOW_DURATION_MILLIS = 5000;
@@ -151,10 +168,18 @@
private AnswerScreenDelegate answerScreenDelegate;
private InCallScreenDelegate inCallScreenDelegate;
+ private InCallButtonUiDelegate inCallButtonUiDelegate;
private View importanceBadge;
private SwipeButtonView secondaryButton;
private SwipeButtonView answerAndReleaseButton;
+ private CheckableImageButton likeButton;
+ private CheckableImageButton shareButton;
+ private CheckableImageButton favoriteButton;
+ private CheckableImageButton copyButton;
+ private CheckableImageButton commentButton;
+ private CheckableImageButton detailButton;
+ private CheckableImageButton moneyButton;
private ImageButton moreOptionsMenuButton;
private AffordanceHolderLayout affordanceHolderLayout;
private LinearLayout chipContainer;
@@ -175,6 +200,7 @@
private ContactGridManager contactGridManager;
private VideoCallScreen answerVideoCallScreen;
private Handler handler = new Handler(Looper.getMainLooper());
+ private boolean isVideoScreenReady = false;
private enum SecondaryBehavior {
REJECT_WITH_SMS(
@@ -380,7 +406,9 @@
boolean isSelfManagedCamera,
boolean allowAnswerAndRelease,
boolean hasCallOnHold,
- boolean allowSpeakEasy) {
+ boolean allowSpeakEasy,
+ boolean hasVideoCrs,
+ boolean isVideoCallOriginally) {
Bundle bundle = new Bundle();
bundle.putString(ARG_CALL_ID, Assert.isNotNull(callId));
bundle.putBoolean(ARG_IS_RTT_CALL, isRttCall);
@@ -390,6 +418,8 @@
bundle.putBoolean(ARG_ALLOW_ANSWER_AND_RELEASE, allowAnswerAndRelease);
bundle.putBoolean(ARG_HAS_CALL_ON_HOLD, hasCallOnHold);
bundle.putBoolean(ARG_ALLOW_SPEAK_EASY, allowSpeakEasy);
+ bundle.putBoolean(ARG_HAS_VIDEO_CRS, hasVideoCrs);
+ bundle.putBoolean(ARG_IS_VIDEO_ORIGINALLY, isVideoCallOriginally);
AnswerFragment instance = new AnswerFragment();
instance.setArguments(bundle);
@@ -516,10 +546,94 @@
@Override
public void onClick(View v) {
- if (moreOptionsMenuButton == v) {
- BottomSheetHelper.getInstance()
- .showBottomSheet(getChildFragmentManager());
- }
+ if (moreOptionsMenuButton == v) {
+ BottomSheetHelper.getInstance()
+ .showBottomSheet(getChildFragmentManager());
+ }
+ }
+
+ @Override
+ public void showButton(@InCallButtonIds int buttonId, boolean show) {
+ LogUtil.v(
+ "VideoCallFragment.showButton",
+ "buttonId: %s, show: %b",
+ InCallButtonIdsExtension.toString(buttonId),
+ show);
+ // Donot show SIP DTMF icons for MT call without video CRS
+ if (!getArguments().getBoolean(ARG_HAS_VIDEO_CRS)) {
+ show = false;
+ }
+ if (buttonId == InCallButtonIds.BUTTON_LIKE) {
+ likeButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_SHARE) {
+ shareButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_FAVORITE) {
+ favoriteButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_COPY) {
+ copyButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_COMMENT) {
+ commentButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_DETAIL) {
+ detailButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_DETAIL) {
+ moneyButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ @Override
+ public void enableButton(@InCallButtonIds int buttonId, boolean enable) {}
+
+ @Override
+ public void setEnabled(boolean on) {}
+
+ @Override
+ public void setHold(boolean on) {}
+
+ @Override
+ public void setCameraSwitched(boolean isBackFacingCamera) {}
+
+ @Override
+ public void setVideoPaused(boolean isPaused) {}
+
+ @Override
+ public void setAudioState(CallAudioState audioState) {}
+
+ @Override
+ public void updateButtonStates() {}
+
+ @Override
+ public void updateInCallButtonUiColors(@ColorInt int color) {}
+
+ @Override
+ public Fragment getInCallButtonUiFragment() {return null;}
+
+ @Override
+ public void showAudioRouteSelector() {}
+
+ @Override
+ public void onCheckedChanged(CheckableImageButton button, boolean isChecked) {
+ if (button == likeButton && !likeButton.isChecked()) {
+ likeButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_LIKE);
+ } else if (button == shareButton && !shareButton.isChecked()) {
+ shareButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_SHARE);
+ } else if (button == favoriteButton && !favoriteButton.isChecked()) {
+ favoriteButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_FAVORITE);
+ } else if (button == copyButton && !copyButton.isChecked()) {
+ copyButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_COPY);
+ } else if (button == commentButton && !commentButton.isChecked()) {
+ commentButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_COMMENT);
+ } else if (button == detailButton && !detailButton.isChecked()) {
+ detailButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_DETAIL);
+ } else if (button == moneyButton && !moneyButton.isChecked()) {
+ moneyButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_RED_ENVELOPE);
+ }
}
@Override
@@ -733,7 +847,7 @@
@Override
public int getAnswerAndDialpadContainerResourceId() {
- throw Assert.createUnsupportedOperationFailException();
+ return R.id.videocall_dialpad_container;
}
@Override
@@ -762,6 +876,22 @@
View view = inflater.inflate(R.layout.fragment_incoming_call, container, false);
secondaryButton = (SwipeButtonView) view.findViewById(R.id.incoming_secondary_button);
answerAndReleaseButton = (SwipeButtonView) view.findViewById(R.id.incoming_secondary_button2);
+ view.findViewById(R.id.sip_dtmf_controls)
+ .setVisibility(getActivity().isInMultiWindowMode() ? View.GONE : View.VISIBLE);
+ likeButton = (CheckableImageButton) view.findViewById(R.id.crs_crbt_like_button);
+ likeButton.setOnCheckedChangeListener(this);
+ shareButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_share_button);
+ shareButton.setOnCheckedChangeListener(this);
+ favoriteButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_favorite_button);
+ favoriteButton.setOnCheckedChangeListener(this);
+ copyButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_copy_button);
+ copyButton.setOnCheckedChangeListener(this);
+ commentButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_comment_button);
+ commentButton.setOnCheckedChangeListener(this);
+ detailButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_detail_button);
+ detailButton.setOnCheckedChangeListener(this);
+ moneyButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_money_button);
+ moneyButton.setOnCheckedChangeListener(this);
moreOptionsMenuButton = (ImageButton) view.findViewById(R.id.qti_dialer_incoming_botton_more);
moreOptionsMenuButton.setOnClickListener(this);
@@ -818,7 +948,8 @@
flags |= STATUS_BAR_DISABLE_BACK | STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT;
}
view.setSystemUiVisibility(flags);
- if (isVideoCall() || isVideoUpgradeRequest()) {
+ if ((isVideoCall() || isVideoUpgradeRequest())
+ && !getArguments().getBoolean(ARG_HAS_VIDEO_CRS) ) {
final DialerCall call = QtiCallUtils.getIncomingOrActiveCall();
int requestedVideoState = VideoProfile.STATE_AUDIO_ONLY;
if (call != null) {
@@ -836,6 +967,9 @@
} else {
view.findViewById(R.id.videocall_video_off).setVisibility(View.VISIBLE);
}
+ } else if(getArguments().getBoolean(ARG_HAS_VIDEO_CRS)) {
+ LogUtil.i("AnswerFragment.onCreateView", "CRS is coming, show remote view");
+ answerVideoCallScreen = new AnswerVideoCallScreen(getCallId(), this, view);
}
Trace.endSection();
@@ -853,6 +987,7 @@
Trace.beginSection("AnswerFragment.onViewCreated");
super.onViewCreated(view, savedInstanceState);
createInCallScreenDelegate();
+ createInCallButtonUiDelegate();
updateUI();
if (savedInstanceState == null || !savedInstanceState.getBoolean(STATE_HAS_ANIMATED_ENTRY)) {
@@ -915,6 +1050,8 @@
super.onDestroyView();
inCallScreenDelegate.onInCallScreenUnready();
answerScreenDelegate.onAnswerScreenUnready();
+ inCallButtonUiDelegate.onInCallButtonUiUnready();
+ InCallPresenter.getInstance().updateSipDtmfMaskToUi(false);
}
@Override
@@ -951,7 +1088,8 @@
@Override
public boolean isVideoCall() {
- return getArguments().getBoolean(ARG_IS_VIDEO_CALL);
+ return getArguments().getBoolean(ARG_IS_VIDEO_CALL)
+ && getArguments().getBoolean(ARG_IS_VIDEO_ORIGINALLY);
}
public boolean isSelfManagedCamera() {
@@ -983,7 +1121,11 @@
@Override
public void answerFromMethod() {
- acceptCallByUser(false /* answerVideoAsAudio */);
+ if (!getArguments().getBoolean(ARG_IS_VIDEO_ORIGINALLY)) {
+ acceptCallByUser(true /* answerVideoAsAudio */);
+ } else {
+ acceptCallByUser(false /* answerVideoAsAudio */);
+ }
}
@Override
@@ -1171,6 +1313,14 @@
inCallScreenDelegate.onInCallScreenReady();
}
+ private void createInCallButtonUiDelegate() {
+ inCallButtonUiDelegate =
+ FragmentUtils.getParent(this, InCallButtonUiDelegateFactory.class)
+ .newInCallButtonUiDelegate();
+ inCallButtonUiDelegate.onInCallButtonUiReady(this);
+ InCallPresenter.getInstance().updateSipDtmfMaskToUi(true);
+ }
+
private void updateImportanceBadgeVisibility() {
if (!isAdded() || getView() == null) {
return;
diff --git a/java/com/android/incallui/answer/impl/AnswerVideoCallScreen.java b/java/com/android/incallui/answer/impl/AnswerVideoCallScreen.java
index 2810eb2..06169c2 100644
--- a/java/com/android/incallui/answer/impl/AnswerVideoCallScreen.java
+++ b/java/com/android/incallui/answer/impl/AnswerVideoCallScreen.java
@@ -25,10 +25,12 @@
import com.android.dialer.common.Assert;
import com.android.dialer.common.FragmentUtils;
import com.android.dialer.common.LogUtil;
+import com.android.incallui.call.DialerCall;
import com.android.incallui.video.protocol.VideoCallScreen;
import com.android.incallui.video.protocol.VideoCallScreenDelegate;
import com.android.incallui.video.protocol.VideoCallScreenDelegateFactory;
import com.android.incallui.videosurface.bindings.VideoSurfaceBindings;
+import com.android.incallui.QtiCallUtils;
/** Shows a video preview for an incoming call. */
public class AnswerVideoCallScreen implements VideoCallScreen {
@@ -60,7 +62,14 @@
public void onVideoScreenStart() {
LogUtil.i("AnswerVideoCallScreen.onStart", null);
delegate.onVideoCallScreenUiReady(this);
- delegate.getLocalVideoSurfaceTexture().attachToTextureView(textureView);
+ DialerCall call = QtiCallUtils.getIncomingCall();
+ if (QtiCallUtils.isVideoCrs(call)) {
+ LogUtil.i("AnswerVideoCallScreen.onStart, video CRS, create remote surface", null);
+ delegate.getRemoteVideoSurfaceTexture().attachToTextureView(textureView);
+ } else {
+ LogUtil.i("AnswerVideoCallScreen.onStart, no video CRS, create local surface", null);
+ delegate.getLocalVideoSurfaceTexture().attachToTextureView(textureView);
+ }
}
@Override
diff --git a/java/com/android/incallui/answer/impl/res/layout/fragment_incoming_call.xml b/java/com/android/incallui/answer/impl/res/layout/fragment_incoming_call.xml
index 500dccb..fa40d7d 100644
--- a/java/com/android/incallui/answer/impl/res/layout/fragment_incoming_call.xml
+++ b/java/com/android/incallui/answer/impl/res/layout/fragment_incoming_call.xml
@@ -191,15 +191,118 @@
android:visibility="invisible"
tools:visibility="visible"/>
- <ImageButton
+<LinearLayout
+ android:id="@+id/sip_dtmf_controls"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center|end"
+ android:scaleType="center"
+ android:orientation="vertical"
+ android:layout_margin="15dp">
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_like_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_favorite_border_24"
+ android:contentDescription="@string/crs_crbt_description_like"
+ android:layout_marginEnd="24dp"
+ android:visibility="gone"
+ tools:visibility="visible"/>
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_share_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_share_24"
+ android:contentDescription="@string/crs_crbt_description_share"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"/>
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_favorite_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_cloud_queue_24"
+ android:contentDescription="@string/crs_crbt_description_favorite"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"/>
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_copy_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_content_copy_24"
+ android:contentDescription="@string/crs_crbt_description_copy"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"/>
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_comment_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_comment_24"
+ android:contentDescription="@string/crs_crbt_description_comment"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_detail_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:src="@drawable/quantum_ic_baseline_info_24"
+ android:checked="false"
+ android:contentDescription="@string/crs_crbt_description_detail"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_money_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:src="@drawable/quantum_ic_baseline_money_24"
+ android:checked="false"
+ android:contentDescription="@string/crs_crbt_description_money"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <ImageButton
android:id="@+id/qti_dialer_incoming_botton_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center|end"
- android:layout_margin="15dp"
- android:scaleType="center"
style="@style/Incall.Button.VideoCall"
android:src="@drawable/quantum_ic_more_vert_white_24"
tools:visibility="visible"/>
+</LinearLayout>
+ <FrameLayout
+ android:id="@+id/videocall_dialpad_container"
+ style="@style/DialpadContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center|bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ tools:background="@android:color/white"
+ tools:visibility="gone"/>
</com.android.incallui.answer.impl.AffordanceHolderLayout>
diff --git a/java/com/android/incallui/callpending/CallPendingActivity.java b/java/com/android/incallui/callpending/CallPendingActivity.java
index 4086e14..bd16625 100644
--- a/java/com/android/incallui/callpending/CallPendingActivity.java
+++ b/java/com/android/incallui/callpending/CallPendingActivity.java
@@ -285,6 +285,9 @@
public void swapSimClicked() {}
@Override
+ public void sendSipDtmfClicked(int buttonId) {}
+
+ @Override
public Context getContext() {
return CallPendingActivity.this;
}
diff --git a/java/com/android/incallui/commontheme/res/values/strings.xml b/java/com/android/incallui/commontheme/res/values/strings.xml
index 0b7ed03..2271f7d 100644
--- a/java/com/android/incallui/commontheme/res/values/strings.xml
+++ b/java/com/android/incallui/commontheme/res/values/strings.xml
@@ -60,4 +60,12 @@
[CHAR LIMIT=12] -->
<string name="incall_label_audio">Sound</string>
+ <string name="crs_crbt_description_like">Like</string>
+ <string name="crs_crbt_description_share">Share</string>
+ <string name="crs_crbt_description_favorite">Favorite</string>
+ <string name="crs_crbt_description_copy">Copy</string>
+ <string name="crs_crbt_description_comment">Comment</string>
+ <string name="crs_crbt_description_detail">Detail</string>
+ <string name="crs_crbt_description_money">Red Envelope</string>
+
</resources>
diff --git a/java/com/android/incallui/incall/protocol/InCallButtonIds.java b/java/com/android/incallui/incall/protocol/InCallButtonIds.java
index 80ea75e..8a05c14 100644
--- a/java/com/android/incallui/incall/protocol/InCallButtonIds.java
+++ b/java/com/android/incallui/incall/protocol/InCallButtonIds.java
@@ -39,7 +39,14 @@
InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY,
InCallButtonIds.BUTTON_SWAP_SIM,
InCallButtonIds.BUTTON_COUNT,
- InCallButtonIds.BUTTON_UPGRADE_TO_RTT
+ InCallButtonIds.BUTTON_UPGRADE_TO_RTT,
+ InCallButtonIds.BUTTON_LIKE,
+ InCallButtonIds.BUTTON_SHARE,
+ InCallButtonIds.BUTTON_FAVORITE,
+ InCallButtonIds.BUTTON_COPY,
+ InCallButtonIds.BUTTON_COMMENT,
+ InCallButtonIds.BUTTON_DETAIL,
+ InCallButtonIds.BUTTON_RED_ENVELOPE
})
public @interface InCallButtonIds {
@@ -60,4 +67,11 @@
int BUTTON_SWAP_SIM = 14;
int BUTTON_COUNT = 15;
int BUTTON_UPGRADE_TO_RTT = 16;
+ int BUTTON_LIKE = 17;
+ int BUTTON_SHARE = 18;
+ int BUTTON_FAVORITE = 19;
+ int BUTTON_COPY = 20;
+ int BUTTON_COMMENT = 21;
+ int BUTTON_DETAIL = 22;
+ int BUTTON_RED_ENVELOPE = 23;
}
diff --git a/java/com/android/incallui/incall/protocol/InCallButtonIdsExtension.java b/java/com/android/incallui/incall/protocol/InCallButtonIdsExtension.java
index 5239d9d..6745c23 100644
--- a/java/com/android/incallui/incall/protocol/InCallButtonIdsExtension.java
+++ b/java/com/android/incallui/incall/protocol/InCallButtonIdsExtension.java
@@ -58,6 +58,20 @@
return "SWAP_SIM";
} else if (id == InCallButtonIds.BUTTON_UPGRADE_TO_RTT) {
return "UPGRADE_TO_RTT";
+ } else if (id == InCallButtonIds.BUTTON_LIKE) {
+ return "LIKE";
+ } else if (id == InCallButtonIds.BUTTON_SHARE) {
+ return "SHARE";
+ } else if (id == InCallButtonIds.BUTTON_FAVORITE) {
+ return "FAVORITE";
+ } else if (id == InCallButtonIds.BUTTON_COPY) {
+ return "COPY";
+ } else if (id == InCallButtonIds.BUTTON_COMMENT) {
+ return "COMMENT";
+ } else if (id == InCallButtonIds.BUTTON_DETAIL) {
+ return "DETAIL";
+ } else if (id == InCallButtonIds.BUTTON_RED_ENVELOPE) {
+ return "RED_ENVELOPE";
} else {
return "INVALID_BUTTON: " + id;
}
diff --git a/java/com/android/incallui/incall/protocol/InCallButtonUiDelegate.java b/java/com/android/incallui/incall/protocol/InCallButtonUiDelegate.java
index 4cf40ef..e77304c 100644
--- a/java/com/android/incallui/incall/protocol/InCallButtonUiDelegate.java
+++ b/java/com/android/incallui/incall/protocol/InCallButtonUiDelegate.java
@@ -65,5 +65,7 @@
void swapSimClicked();
+ void sendSipDtmfClicked(int buttonId);
+
Context getContext();
}
diff --git a/java/com/android/incallui/res/values-zh-rCN/strings.xml b/java/com/android/incallui/res/values-zh-rCN/strings.xml
index 85f73b8..569541b 100644
--- a/java/com/android/incallui/res/values-zh-rCN/strings.xml
+++ b/java/com/android/incallui/res/values-zh-rCN/strings.xml
@@ -119,4 +119,6 @@
<string name="call_progress_info_call_rejected">对方通话中,请稍后再拨</string>
<string name="call_progress_info_user_call_rejected">您的号码已停机</string>
<string name="call_progress_info_nonuser_call_rejected">您拨打的号码已停机</string>
+ <!-- Displayed in the answer call screen for incoming video CRS calls. -->
+ <string name="incoming_video_crs_call">正在播放视频彩振</string>
</resources>
diff --git a/java/com/android/incallui/res/values/qtistrings.xml b/java/com/android/incallui/res/values/qtistrings.xml
index ae64946..e5b8687 100644
--- a/java/com/android/incallui/res/values/qtistrings.xml
+++ b/java/com/android/incallui/res/values/qtistrings.xml
@@ -166,6 +166,9 @@
<string name="cancel_upgrade">Cancel Upgrade</string>
<string name="not_cancel">Not Cancel</string>
+ <!-- Displayed in the answer call screen for incoming video CRS calls. -->
+ <string name="incoming_video_crs_call">Video CRS Receive call from</string>
+
<!-- Displayed in the answer call screen for incoming video rx calls. -->
<string name="incoming_video_rx_call">Video Receive call from</string>
diff --git a/java/com/android/incallui/video/impl/VideoCallFragment.java b/java/com/android/incallui/video/impl/VideoCallFragment.java
index 94b8a80..7f0f5e1 100644
--- a/java/com/android/incallui/video/impl/VideoCallFragment.java
+++ b/java/com/android/incallui/video/impl/VideoCallFragment.java
@@ -154,6 +154,15 @@
private ImageButton swapCameraButton;
private ImageButton addCallButton;
private ImageButton mergeCallButton;
+ //SIP DTMF buttons
+ private CheckableImageButton likeButton;
+ private CheckableImageButton shareButton;
+ private CheckableImageButton favoriteButton;
+ private CheckableImageButton copyButton;
+ private CheckableImageButton commentButton;
+ private CheckableImageButton detailButton;
+ private CheckableImageButton moneyButton;
+
private View switchOnHoldButton;
private View onHoldContainer;
private SwitchOnHoldCallController switchOnHoldCallController;
@@ -308,6 +317,20 @@
(ImageView) view.findViewById(R.id.videocall_remote_off_blurred_image_view);
endCallButton = view.findViewById(R.id.videocall_end_call);
endCallButton.setOnClickListener(this);
+ likeButton = (CheckableImageButton) view.findViewById(R.id.crs_crbt_like_button);
+ likeButton.setOnCheckedChangeListener(this);
+ shareButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_share_button);
+ shareButton.setOnCheckedChangeListener(this);
+ favoriteButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_favorite_button);
+ favoriteButton.setOnCheckedChangeListener(this);
+ copyButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_copy_button);
+ copyButton.setOnCheckedChangeListener(this);
+ commentButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_comment_button);
+ commentButton.setOnCheckedChangeListener(this);
+ detailButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_detail_button);
+ detailButton.setOnCheckedChangeListener(this);
+ moneyButton = (CheckableImageButton)view.findViewById(R.id.crs_crbt_money_button);
+ moneyButton.setOnCheckedChangeListener(this);
moreOptionsMenuButton = view.findViewById(R.id.videocall_more_button);
moreOptionsMenuButton.setOnClickListener(this);
previewTextureView = (TextureView) view.findViewById(R.id.videocall_video_preview);
@@ -837,6 +860,27 @@
LogUtil.i("VideoCallFragment.onCheckedChanged","hold Button");
inCallButtonUiDelegate.holdClicked(isChecked);
videoCallScreenDelegate.resetAutoFullscreenTimer();
+ } else if (button == likeButton && !likeButton.isChecked()) {
+ likeButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_LIKE);
+ } else if (button == shareButton && !shareButton.isChecked()) {
+ shareButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_SHARE);
+ } else if (button == favoriteButton && !favoriteButton.isChecked()) {
+ favoriteButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_FAVORITE);
+ } else if (button == copyButton && !copyButton.isChecked()) {
+ copyButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_COPY);
+ } else if (button == commentButton && !commentButton.isChecked()) {
+ commentButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_COMMENT);
+ } else if (button == detailButton && !detailButton.isChecked()) {
+ detailButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_DETAIL);
+ } else if (button == moneyButton && !moneyButton.isChecked()) {
+ moneyButton.setChecked(isChecked);
+ inCallButtonUiDelegate.sendSipDtmfClicked(InCallButtonIds.BUTTON_RED_ENVELOPE);
}
}
@@ -1095,6 +1139,7 @@
show);
BottomSheetHelper bottomSheetHelper = BottomSheetHelper.getInstance();
boolean isDialpadVisible = InCallPresenter.getInstance().isDialpadVisible();
+ boolean isCrbtReady = videoCallScreenDelegate.isIncomingVideoAvailableForEarlyMedia();
bottomSheetHelper.updateMoreButtonVisibility(
isDialpadVisible ? false : bottomSheetHelper.shallShowMoreButton(getActivity()),
moreOptionsMenuButton);
@@ -1118,6 +1163,20 @@
mergeCallButton.setVisibility(show ? View.VISIBLE : View.GONE);
} else if (buttonId == InCallButtonIds.BUTTON_HOLD) {
holdButton.setVisibility(show ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_LIKE) {
+ likeButton.setVisibility((show && isCrbtReady) ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_SHARE) {
+ shareButton.setVisibility((show && isCrbtReady)? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_FAVORITE) {
+ favoriteButton.setVisibility((show && isCrbtReady) ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_COPY) {
+ copyButton.setVisibility((show && isCrbtReady) ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_COMMENT) {
+ commentButton.setVisibility((show && isCrbtReady) ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_DETAIL) {
+ detailButton.setVisibility((show &&isCrbtReady) ? View.VISIBLE : View.GONE);
+ } else if (buttonId == InCallButtonIds.BUTTON_RED_ENVELOPE) {
+ moneyButton.setVisibility((show && isCrbtReady) ? View.VISIBLE : View.GONE);
}
}
diff --git a/java/com/android/incallui/video/impl/res/layout/videocall_controls.xml b/java/com/android/incallui/video/impl/res/layout/videocall_controls.xml
index 5b0bb0f..0c82ac9 100644
--- a/java/com/android/incallui/video/impl/res/layout/videocall_controls.xml
+++ b/java/com/android/incallui/video/impl/res/layout/videocall_controls.xml
@@ -143,6 +143,97 @@
android:layout_marginEnd="24dp"
tools:visibility="visible"
/>
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_like_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_favorite_border_24"
+ android:contentDescription="@string/crs_crbt_description_like"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_share_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_share_24"
+ android:contentDescription="@string/crs_crbt_description_share"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_favorite_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_cloud_queue_24"
+ android:contentDescription="@string/crs_crbt_description_favorite"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_copy_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_content_copy_24"
+ android:contentDescription="@string/crs_crbt_description_copy"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_comment_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_comment_24"
+ android:contentDescription="@string/crs_crbt_description_comment"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_detail_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:src="@drawable/quantum_ic_baseline_info_24"
+ android:checked="false"
+ android:contentDescription="@string/crs_crbt_description_detail"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_money_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:src="@drawable/quantum_ic_baseline_money_24"
+ android:checked="false"
+ android:contentDescription="@string/crs_crbt_description_money"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
<ImageButton
android:id="@+id/videocall_more_button"
style="@style/Incall.Button.VideoCall"
diff --git a/java/com/android/incallui/video/impl/res/layout/videocall_controls_land.xml b/java/com/android/incallui/video/impl/res/layout/videocall_controls_land.xml
index 11ab573..ea33e0a 100644
--- a/java/com/android/incallui/video/impl/res/layout/videocall_controls_land.xml
+++ b/java/com/android/incallui/video/impl/res/layout/videocall_controls_land.xml
@@ -116,6 +116,97 @@
android:visibility="gone"
tools:visibility="visible"
/>
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_like_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_favorite_border_24"
+ android:contentDescription="@string/crs_crbt_description_like"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_share_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_share_24"
+ android:contentDescription="@string/crs_crbt_description_share"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_favorite_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_cloud_queue_24"
+ android:contentDescription="@string/crs_crbt_description_favorite"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_copy_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_content_copy_24"
+ android:contentDescription="@string/crs_crbt_description_copy"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_comment_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:checked="false"
+ android:src="@drawable/quantum_ic_baseline_comment_24"
+ android:contentDescription="@string/crs_crbt_description_comment"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_detail_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:src="@drawable/quantum_ic_baseline_info_24"
+ android:checked="false"
+ android:contentDescription="@string/crs_crbt_description_detail"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
+ <com.android.incallui.video.impl.CheckableImageButton
+ android:id="@+id/crs_crbt_money_button"
+ style="@style/Incall.Button.VideoCall"
+ android:layout_width="@dimen/videocall_button_size"
+ android:layout_height="@dimen/videocall_button_size"
+ android:layout_marginBottom="@dimen/videocall_button_spacing"
+ android:src="@drawable/quantum_ic_baseline_money_24"
+ android:checked="false"
+ android:contentDescription="@string/crs_crbt_description_money"
+ android:visibility="gone"
+ android:layout_marginEnd="24dp"
+ tools:visibility="visible"
+ />
</LinearLayout>
<FrameLayout