Beta support for webrtc video and voice calling

// FREEBIE
pull/1/head
Moxie Marlinspike 9 years ago
parent a9651e2e9c
commit ea0945d406

@ -118,6 +118,14 @@
android:launchMode="singleTask">
</activity>
<activity android:name="org.thoughtcrime.securesms.WebRtcCallActivity"
android:excludeFromRecents="true"
android:screenOrientation="portrait"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|fontScale"
android:launchMode="singleTask">
</activity>
<activity android:name=".CountrySelectionActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@ -349,7 +357,7 @@
</intent-filter>
</activity>
<activity android:name="org.thoughtcrime.redphone.RedPhoneShare"
<activity android:name="org.thoughtcrime.redphone.VoiceCallShare"
android:excludeFromRecents="true"
android:theme="@style/NoAnimation.Theme.BlackScreen"
android:launchMode="singleTask"
@ -383,6 +391,7 @@
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
<service android:enabled="true" android:name="org.thoughtcrime.redphone.RedPhoneService"/>
<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
<service android:enabled="true" android:name=".service.KeyCachingService"/>

@ -57,7 +57,8 @@ dependencies {
compile 'org.whispersystems:jobmanager:1.0.2'
compile 'org.whispersystems:libpastelog:1.0.7'
compile 'org.whispersystems:signal-service-android:2.4.7'
compile 'org.whispersystems:signal-service-android:2.5.0'
compile 'org.whispersystems:webrtc-android:M56'
compile "me.leolin:ShortcutBadger:1.10-WS1"
compile 'se.emilsjolander:stickylistheaders:2.7.0'
@ -123,7 +124,8 @@ dependencyVerification {
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181',
'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88',
'org.whispersystems:signal-service-android:0b5e607c1ffdbc90f8b1117c43ceaba62e3e19c01c8d29b3e1bf57cffce07f2b',
'org.whispersystems:signal-service-android:f207fcf8f17b5a1f04053151cad518f9520f8fbfb2e5563a19828f6b2c2b7b6d',
'org.whispersystems:webrtc-android:1eaaf2c8b48e135834de74733dd5ffcf9585402ad4d568f5167bc3ba6f11d569',
'me.leolin:ShortcutBadger:e8e39df8a59d8211a30f40b1eeab21b3fa57b3f3e0f03abb995f82d66588778c',
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
@ -157,7 +159,7 @@ dependencyVerification {
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19',
'org.whispersystems:signal-service-java:9738c26c17069a2f1eff47a46da5df62efa875bd66321933bed78f2584b7cc70',
'org.whispersystems:signal-service-java:910ed96e928355d118454e1dff6c11b9f95daa801f3b4022e5c8999bff47a888',
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
@ -178,6 +180,7 @@ dependencyVerification {
]
}
android {
compileSdkVersion 25
buildToolsVersion '23.0.3'
@ -239,6 +242,7 @@ android {
'proguard-glide.pro',
'proguard-shortcutbadger.pro',
'proguard-retrofit.pro',
'proguard-webrtc.pro',
'proguard.cfg'
testProguardFiles 'proguard-automation.pro',
'proguard.cfg'

@ -0,0 +1,3 @@
-dontwarn org.webrtc.NetworkMonitorAutoDetect
-dontwarn android.net.Network
-keep class org.webrtc.** { *; }

@ -0,0 +1,3 @@
all:
protoc --java_out=../src/ WebRtcData.proto

@ -0,0 +1,31 @@
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package signal;
option java_package = "org.thoughtcrime.securesms.webrtc";
option java_outer_classname = "WebRtcDataProtos";
message Connected {
optional uint64 id = 1;
}
message Hangup {
optional uint64 id = 1;
}
message VideoStreamingStatus {
optional uint64 id = 1;
optional bool enabled = 2;
}
message Data {
optional Connected connected = 1;
optional Hangup hangup = 2;
optional VideoStreamingStatus videoStreamingStatus = 3;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#22000000" />
</shape>

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/compoundBackgroundItem" android:drawable="@drawable/webrtc_control_background"/>
<item android:id="@+id/moreIndicatorItem"
android:top="5dp"
android:left="5dp"
android:right="5dp"
android:bottom="5dp">
<bitmap android:src="@drawable/redphone_ic_more_indicator_holo_dark"
android:gravity="bottom|right" />
</item>
<item android:id="@+id/bluetoothItem"
android:top="5dp"
android:left="5dp"
android:right="5dp"
android:bottom="5dp">
<bitmap android:src="@drawable/ic_phone_bluetooth_speaker_white_24dp"
android:gravity="center" />
</item>
<!-- Handset earpiece is active -->
<item android:id="@+id/handsetItem" android:top="5dp"
android:left="5dp"
android:right="5dp"
android:bottom="5dp">
<bitmap android:src="@drawable/ic_phone_in_talk_white_24dp"
android:gravity="center" />
</item>
<!-- Speakerphone icon showing 'speaker on' state -->
<item android:id="@+id/speakerphoneOnItem" android:top="5dp"
android:left="5dp"
android:right="5dp"
android:bottom="5dp">
<bitmap android:src="@drawable/ic_volume_up_white_24dp"
android:gravity="center" />
</item>
<!--&lt;!&ndash; Speakerphone icon showing 'speaker off' state &ndash;&gt;-->
<!--<item android:id="@+id/speakerphoneOffItem">-->
<!--<bitmap android:src="@drawable/ic_volume_mute_white_24dp"-->
<!--android:gravity="center" />-->
<!--</item>-->
</layer-list>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/circle_alpha" android:state_checked="true"/>
<item android:drawable="@android:color/transparent" />
</selector>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/webrtc_control_background"/>
<item android:top="5dp"
android:left="5dp"
android:right="5dp"
android:bottom="5dp"
android:drawable="@drawable/ic_mic_off_white_24dp"/>
</layer-list>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/webrtc_control_background"/>
<item android:top="5dp"
android:left="5dp"
android:right="5dp"
android:bottom="5dp"
android:drawable="@drawable/ic_videocam_white_24dp"/>
</layer-list>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<org.thoughtcrime.securesms.components.webrtc.WebRtcCallScreen android:id="@+id/callScreen"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/inCallControls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:background="@color/textsecure_primary">
<ToggleButton android:id="@+id/audioButton"
style="@style/WebRtcCallCompoundButton"
android:background="@drawable/webrtc_audio_button"
tools:checked="true"
android:layout_marginRight="15dp"/>
<ToggleButton android:id="@+id/muteButton"
style="@style/WebRtcCallCompoundButton"
android:background="@drawable/webrtc_mute_button"
android:contentDescription="@string/redphone_call_controls__mute"
android:layout_marginRight="15dp"
tools:checked="false"
/>
<ToggleButton android:id="@+id/video_mute_button"
style="@style/WebRtcCallCompoundButton"
android:background="@drawable/webrtc_video_mute_button"/>
</merge>

@ -0,0 +1,249 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2007 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/incall_screen"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- "Call info" block #1, for the foreground call. -->
<RelativeLayout android:id="@+id/call_info_1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Contact photo for call_info_1 -->
<FrameLayout android:id="@+id/image_container"
android:layout_below="@+id/call_banner_1"
android:gravity="top|center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:id="@+id/photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:scaleType="centerCrop"
android:visibility="visible"
tools:src="@drawable/ic_contact_picture_large"
/>
<LinearLayout android:id="@+id/untrusted_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_400"
android:orientation="vertical"
android:visibility="gone"
android:gravity="center">
<TextView android:id="@+id/untrusted_explanation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="16sp"
android:maxWidth="270dp"
android:lineSpacingExtra="2sp"
tools:text="The safety numbers for your conversation with Masha have changed. This could either mean that someone is trying to intercept your communication, or that Masha simply re-installed Signal. You may wish to verify safety numbers for this contact."/>
<LinearLayout
android:layout_marginTop="20dp"
android:maxWidth="250dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:id="@+id/accept_safety_numbers"
android:text="Accept"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"/>
<Button android:id="@+id/cancel_safety_numbers"
android:text="Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
<org.thoughtcrime.securesms.components.webrtc.PercentFrameLayout
android:id="@+id/remote_render_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:visibility="invisible"/>
<org.thoughtcrime.securesms.components.webrtc.PercentFrameLayout
android:id="@+id/local_render_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:visibility="invisible"/>
</FrameLayout>
<!-- "Call Banner" for call #1, the foregound or ringing call.
The "call banner" is a block of info about a single call,
including the contact name, phone number, call time counter,
and other status info. This info is shown as a "banner"
overlaid across the top of contact photo. -->
<RelativeLayout android:id="@+id/call_banner_1"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="80dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:background="@color/textsecure_primary"
>
<!-- Name (or the phone number, if we don't have a name to display). -->
<TextView android:id="@+id/name"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="50sp"
android:textSize="40sp"
android:textColor="#FFFFFF"
android:singleLine="true"
android:maxLines="1"
android:ellipsize="end"
tools:text="Ali Connors"
/>
<!-- Label (like "Mobile" or "Work", if present) and phone number, side by side -->
<LinearLayout android:id="@+id/labelAndNumber"
android:layout_below="@id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="50sp"
android:orientation="horizontal"
>
<TextView android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/redphone_call_card__signal_call"
android:layout_marginRight="10dp"
/>
<TextView android:id="@+id/phoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:singleLine="true"
tools:text="+14152222222"
/>
</LinearLayout>
<!-- Elapsed time indication for a call in progress. -->
<TextView android:id="@+id/elapsedTime"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#FFFFFF"
android:singleLine="true"
/>
<!-- Call type indication: a special label and/or branding
for certain kinds of calls (like "Internet call" for a SIP call.) -->
<TextView android:id="@+id/callTypeLabel"
android:layout_below="@id/labelAndNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:maxLines="1"
android:ellipsize="end"
android:visibility="gone"
android:text="@string/redphone_call_card__signal_call"
/>
<!-- Social status (currently unused) -->
<TextView android:id="@+id/socialStatus"
android:layout_below="@id/callTypeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:maxLines="2"
android:ellipsize="end"
/>
<org.thoughtcrime.securesms.components.webrtc.WebRtcCallControls
android:id="@+id/inCallControls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="15dp"
android:layout_centerHorizontal="true"
android:layout_below="@id/labelAndNumber"/>
</RelativeLayout> <!-- End of call_banner for call_info #1. -->
<!-- The "call state label": In some states, this shows a special
indication like "Dialing" or "Incoming call" or "Call ended".
It's unused for the normal case of an active ongoing call. -->
<!-- This is visually part of the call banner, but it's not actually
part of the "call_banner_1" RelativeLayout since it needs a
different background color. -->
<TextView android:id="@+id/callStateLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/call_banner_1"
android:gravity="right"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingRight="24dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#FFFFFF"
android:textAllCaps="true"
android:background="#8033b5e5"
tools:text="connected"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/hangup_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/ic_call_end_white_48dp"
android:focusable="true"
app:backgroundTint="@color/red_500"
android:visibility="visible"
android:contentDescription="End call"
tools:visibility="visible"/>
</RelativeLayout>
<org.thoughtcrime.securesms.components.webrtc.WebRtcIncomingCallOverlay
android:id="@+id/callControls"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.thoughtcrime.redphone.util.multiwaveview.MultiWaveView
android:id="@+id/incomingCallWidget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="-46dp"
android:background="@android:color/black"
android:visibility="gone"
/>
<TextView android:id="@+id/redphone_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/incomingCallWidget"
android:gravity="center"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FFFFFF"
android:textAllCaps="true"
android:background="@color/textsecure_primary"
android:text="@string/redphone_call_controls__signal_call"/>
</RelativeLayout>

Binary file not shown.

Binary file not shown.

@ -641,6 +641,14 @@
<string name="SingleRecipientNotificationBuilder_signal">Signal</string>
<string name="SingleRecipientNotificationBuilder_new_message">New message</string>
<!-- WebRtcCallScreen -->
<string name="WebRtcCallScreen_new_safety_numbers">The safety numbers for your conversation with %1$s have changed. This could either mean that someone is trying to intercept your communication, or that %2$s simply re-installed Signal.</string>
<string name="WebRtcCallScreen_you_may_wish_to_verify_this_contact">You may wish to verify
safety numbers for this contact.
</string>
<string name="WebRtcCallScreen_new_safety_numbers_title">New safety numbers</string>
<!-- attachment_type_selector -->
<string name="attachment_type_selector__image">Image</string>
<string name="attachment_type_selector__image_description">Image</string>
@ -1129,6 +1137,9 @@
<string name="preferences_chats__message_trimming">Message trimming</string>
<string name="preferences_advanced__use_system_emoji">Use system emoji</string>
<string name="preferences_advanced__disable_signal_built_in_emoji_support">Disable Signal\'s built-in emoji support</string>
<string name="preferences_advanced__video_calling_beta">Video calling beta</string>
<string name="preferences_advanced__enable_support_for_next_generation_video_and_voice_calls">Support for next-generation video and voice calls when enabled by both parties. This feature is in beta.</string>
<!-- **************************************** -->
<!-- menus -->

@ -227,6 +227,13 @@
<item name="android:textOff">@null</item>
</style>
<style name="WebRtcCallCompoundButton">
<item name="android:layout_height">31dp</item>
<item name="android:layout_width">31dp</item>
<item name="android:textOn">@null</item>
<item name="android:textOff">@null</item>
</style>
<style name="IdentityKey">
<item name="android:fontFamily">monospace</item>
<item name="android:typeface">monospace</item>

@ -19,6 +19,12 @@
android:title="@string/preferences_advanced__use_system_emoji"
android:summary="@string/preferences_advanced__disable_signal_built_in_emoji_support" />
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_webrtc_calling"
android:title="@string/preferences_advanced__video_calling_beta"
android:summary="@string/preferences_advanced__enable_support_for_next_generation_video_and_voice_calls"/>
<Preference android:key="pref_choose_identity"
android:title="@string/preferences__choose_identity"
android:summary="@string/preferences__choose_your_contact_entry_from_the_contacts_list"/>

@ -1,46 +0,0 @@
package org.thoughtcrime.redphone;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
public class RedPhoneShare extends Activity {
private static final String TAG = RedPhone.class.getSimpleName();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (getIntent().getData() != null && "content".equals(getIntent().getData().getScheme())) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(getIntent().getData(), null, null, null, null);
if (cursor != null && cursor.moveToNext()) {
String destination = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.RawContacts.Data.DATA1));
if (!TextUtils.isEmpty(destination)) {
Intent serviceIntent = new Intent(this, RedPhoneService.class);
serviceIntent.setAction(RedPhoneService.ACTION_OUTGOING_CALL);
serviceIntent.putExtra(RedPhoneService.EXTRA_REMOTE_NUMBER, destination);
startService(serviceIntent);
Intent activityIntent = new Intent(this, RedPhone.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
}
}
} finally {
if (cursor != null) cursor.close();
}
}
finish();
}
}

@ -0,0 +1,70 @@
package org.thoughtcrime.redphone;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;
import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class VoiceCallShare extends Activity {
private static final String TAG = VoiceCallShare.class.getSimpleName();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (getIntent().getData() != null && "content".equals(getIntent().getData().getScheme())) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(getIntent().getData(), null, null, null, null);
if (cursor != null && cursor.moveToNext()) {
String destination = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.RawContacts.Data.DATA1));
if (!TextUtils.isEmpty(destination)) {
Recipients recipients = RecipientFactory.getRecipientsFromString(this, destination, true);
DirectoryHelper.UserCapabilities capabilities = DirectoryHelper.getUserCapabilities(this, recipients);
if (TextSecurePreferences.isWebrtcCallingEnabled(this) &&
capabilities.getVideoCapability() == DirectoryHelper.UserCapabilities.Capability.SUPPORTED)
{
Intent serviceIntent = new Intent(this, WebRtcCallService.class);
serviceIntent.setAction(WebRtcCallService.ACTION_OUTGOING_CALL);
serviceIntent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, destination);
startService(serviceIntent);
Intent activityIntent = new Intent(this, WebRtcCallActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
} else {
Intent serviceIntent = new Intent(this, RedPhoneService.class);
serviceIntent.setAction(RedPhoneService.ACTION_OUTGOING_CALL);
serviceIntent.putExtra(RedPhoneService.EXTRA_REMOTE_NUMBER, destination);
startService(serviceIntent);
Intent activityIntent = new Intent(this, RedPhone.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
}
}
}
} finally {
if (cursor != null) cursor.close();
}
}
finish();
}
}

@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.service.DirectoryRefreshListener;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.webrtc.PeerConnectionFactory;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.jobqueue.dependencies.DependencyInjector;
import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider;
@ -85,6 +86,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeSignedPreKeyCheck();
initializePeriodicTasks();
initializeCircumvention();
PeerConnectionFactory.initializeAndroidGlobals(this, true, true, true);
}
@Override

@ -2,18 +2,14 @@ package org.thoughtcrime.securesms;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
@ -31,6 +27,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.VerifySpan;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
@ -166,12 +163,14 @@ public class ConfirmIdentityDialog extends AlertDialog {
mismatch.getRecipientId(),
mismatch.getIdentityKey());
boolean legacy = !messageRecord.isContentBundleKeyExchange();
SignalServiceEnvelope envelope = new SignalServiceEnvelope(SignalServiceProtos.Envelope.Type.PREKEY_BUNDLE_VALUE,
messageRecord.getIndividualRecipient().getNumber(),
messageRecord.getRecipientDeviceId(), "",
messageRecord.getDateSent(),
Base64.decode(messageRecord.getBody().getBody()),
null);
legacy ? Base64.decode(messageRecord.getBody().getBody()) : null,
!legacy ? Base64.decode(messageRecord.getBody().getBody()) : null);
long pushId = pushDatabase.insert(envelope);
@ -197,22 +196,4 @@ public class ConfirmIdentityDialog extends AlertDialog {
}
}
private static class VerifySpan extends ClickableSpan {
private final Context context;
private final IdentityKeyMismatch mismatch;
private VerifySpan(Context context, IdentityKeyMismatch mismatch) {
this.context = context;
this.mismatch = mismatch;
}
@Override
public void onClick(View widget) {
Intent intent = new Intent(context, VerifyIdentityActivity.class);
intent.putExtra(VerifyIdentityActivity.RECIPIENT_ID, mismatch.getRecipientId());
intent.putExtra(VerifyIdentityActivity.RECIPIENT_IDENTITY, new IdentityKeyParcelable(mismatch.getIdentityKey()));
context.startActivity(intent);
}
}
}

@ -123,6 +123,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.recipients.Recipients.RecipientsModifiedListener;
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage;
@ -224,7 +225,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private int distributionType;
private boolean archived;
private boolean isSecureText;
private boolean isSecureVoice;
private boolean isSecureVideo;
private boolean isDefaultSms = true;
private boolean isMmsEnabled = true;
@ -437,8 +438,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
if (isSingleConversation()) {
if (isSecureVoice) inflater.inflate(R.menu.conversation_callable_secure, menu);
else inflater.inflate(R.menu.conversation_callable_insecure, menu);
if (isSecureText) inflater.inflate(R.menu.conversation_callable_secure, menu);
else inflater.inflate(R.menu.conversation_callable_insecure, menu);
} else if (isGroupConversation()) {
inflater.inflate(R.menu.conversation_group_options, menu);
@ -749,7 +750,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleDial(final Recipient recipient) {
if (recipient == null) return;
if (isSecureVoice) {
if (isSecureVideo && TextSecurePreferences.isWebrtcCallingEnabled(this)) {
Intent intent = new Intent(this, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_OUTGOING_CALL);
intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, recipient.getNumber());
startService(intent);
Intent activityIntent = new Intent(this, WebRtcCallActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
} else if (isSecureText) {
Intent intent = new Intent(this, RedPhoneService.class);
intent.setAction(RedPhoneService.ACTION_OUTGOING_CALL);
intent.putExtra(RedPhoneService.EXTRA_REMOTE_NUMBER, recipient.getNumber());
@ -806,9 +816,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
startActivity(intent);
}
private void handleSecurityChange(boolean isSecureText, boolean isSecureVoice, boolean isDefaultSms) {
private void handleSecurityChange(boolean isSecureText, boolean isSecureVideo, boolean isDefaultSms) {
this.isSecureText = isSecureText;
this.isSecureVoice = isSecureVoice;
this.isSecureVideo = isSecureVideo;
this.isDefaultSms = isDefaultSms;
boolean isMediaMessage = !recipients.isSingleRecipient() || attachmentManager.isAttachmentPresent();
@ -889,13 +899,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private ListenableFuture<Boolean> initializeSecurity(final boolean currentSecureText,
final boolean currentSecureVoice,
final boolean currentSecureVideo,
final boolean currentIsDefaultSms)
{
final SettableFuture<Boolean> future = new SettableFuture<>();
handleSecurityChange(currentSecureText || isPushGroupConversation(),
currentSecureVoice && !isGroupConversation(),
currentSecureVideo && !isGroupConversation(),
currentIsDefaultSms);
new AsyncTask<Recipients, Void, boolean[]>() {
@ -923,7 +933,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onPostExecute(boolean[] result) {
if (result[0] != currentSecureText || result[1] != currentSecureVoice || result[2] != currentIsDefaultSms) {
if (result[0] != currentSecureText || result[1] != currentSecureVideo || result[2] != currentIsDefaultSms) {
handleSecurityChange(result[0], result[1], result[2]);
}
future.set(true);
@ -1120,7 +1130,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
securityUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
initializeSecurity(isSecureText, isSecureVoice, isDefaultSms);
initializeSecurity(isSecureText, isSecureVideo, isDefaultSms);
calculateCharactersRemaining();
}
};
@ -1768,7 +1778,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onAttachmentChanged() {
handleSecurityChange(isSecureText, isSecureVoice, isDefaultSms);
handleSecurityChange(isSecureText, isSecureVideo, isDefaultSms);
updateToggleButtonState();
}

@ -520,8 +520,9 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
try {
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context, e164number, password);
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
boolean video = TextSecurePreferences.isWebrtcCallingEnabled(context);
accountManager.verifyAccountWithCode(code, signalingKey, registrationId, true);
accountManager.verifyAccountWithCode(code, signalingKey, registrationId, true, video);
return SUCCESS;
} catch (ExpectationFailedException e) {
@ -616,10 +617,10 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
return SUCCESS;
} catch (RateLimitException e) {
Log.w("RegistrationProgressActivity", e);
Log.w(TAG, e);
return RATE_LIMIT_EXCEEDED;
} catch (IOException e) {
Log.w("RegistrationProgressActivity", e);
Log.w(TAG, e);
return NETWORK_ERROR;
}
}

@ -0,0 +1,404 @@
/*
* Copyright (C) 2016 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import org.thoughtcrime.redphone.util.AudioUtils;
import org.thoughtcrime.securesms.components.webrtc.WebRtcCallControls;
import org.thoughtcrime.securesms.components.webrtc.WebRtcCallScreen;
import org.thoughtcrime.securesms.components.webrtc.WebRtcIncomingCallOverlay;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.events.WebRtcCallEvent;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.WebRtcCallService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.whispersystems.libsignal.IdentityKey;
import de.greenrobot.event.EventBus;
public class WebRtcCallActivity extends Activity {
private static final String TAG = WebRtcCallActivity.class.getSimpleName();
private static final int STANDARD_DELAY_FINISH = 1000;
public static final int BUSY_SIGNAL_DELAY_FINISH = 5500;
public static final String ANSWER_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".ANSWER_ACTION";
public static final String DENY_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".DENY_ACTION";
public static final String END_CALL_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".END_CALL_ACTION";
private WebRtcCallScreen callScreen;
private BroadcastReceiver bluetoothStateReceiver;
@Override
public void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.webrtc_call_activity);
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
initializeResources();
}
@Override
public void onResume() {
super.onResume();
initializeScreenshotSecurity();
EventBus.getDefault().registerSticky(this);
registerBluetoothReceiver();
}
@Override
public void onNewIntent(Intent intent){
if (ANSWER_ACTION.equals(intent.getAction())) {
handleAnswerCall();
} else if (DENY_ACTION.equals(intent.getAction())) {
handleDenyCall();
} else if (END_CALL_ACTION.equals(intent.getAction())) {
handleEndCall();
}
}
@Override
public void onPause() {
super.onPause();
EventBus.getDefault().unregister(this);