Some thoughts about WhatsApp + VoIP

Today WhatsApp has released a new version with the green blue read notification icon.

I downloaded it and tried to inspect the APK in searching of somethingĀ interesting.

Tools:

  • WhatsApp APK
  • Apktool – in order to analyze XML resources
  • Dex2Jar – if you want to analyze the (obfuscated) source code

These are some thoughts about the next VoIP feature after a fast and quick analysis. I think that with enough time it’s possible to find a lot of interesting things (for example: it is possible to enable VoIP feature hacking the smali files?).

VoIP engine is fully implemented (I think). The native library libwhatsapp.so contains a lot of PJSIP references. This is an excerpt of a “strings libwhatsapp.so” command

Error creating stream: %d
pjmedia_stream_get_port error
Error creating conf bridge
stream_port
Error adding stream port to conf bridge
pjmedia_stream_start error
....
Unspecified audio device error (PJMEDIA_EAUD_ERR)
Unknown error from audio driver (PJMEDIA_EAUD_SYSERR)
Audio subsystem not initialized (PJMEDIA_EAUD_INIT)
Invalid audio device (PJMEDIA_EAUD_INVDEV)
Found no audio devices (PJMEDIA_EAUD_NODEV)

Another interesting thing is that there are a lot of references to SRTP protocol. SRTPĀ is implemented by default in PjSIP but there are also some little references in .class files, so maybe the VoIP calls will be made using SRTP encryption.

error during srtp key copy for offer
error during srtp key copy for offer accept
pjmedia_transport_srtp_create failed
pjmedia_transport_srtp_start failed: %d
incompatible-srtp-key-exchange
....
%s: function srtp_protect
%s: srtp auth tag: %s
%s: function srtp_unprotect

The last interesting thing is the VoipActivity layout and the visual rendering made by Eclipse. This will be the “In call activity” ?

WhatsApp Voip Activity

Below you can analyze the Activity XML file (sorry for the bad XML rendering on this page…I need to find a better WordPress Template)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:background="@*android:color/black" android:layout_width="fill_parent" android:layout_height="fill_parent"
  xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView android:textSize="27.0sp" android:textColor="@*android:color/white" android:gravity="left" android:id="@id/name" android:paddingLeft="16.0dip" android:paddingTop="10.0dip" android:paddingRight="16.0dip" android:paddingBottom="10.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:fontFamily="sans-serif-light" />
    <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignTop="@id/name" android:layout_alignRight="@id/name" android:layout_alignBottom="@id/name">
        <View android:layout_width="0.0dip" android:layout_height="fill_parent" android:layout_weight="2.0" />
        <Button android:id="@id/report_audio_quality_btn" android:background="@*android:color/transparent" android:layout_width="0.0dip" android:layout_height="fill_parent" android:layout_weight="1.0" />
    </LinearLayout>
    <LinearLayout android:orientation="vertical" android:id="@id/footer" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true">
        <com.whatsapp.AnswerCallView android:id="@id/answer_call_slider" android:layout_width="fill_parent" android:layout_height="78.0dip" />
        <FrameLayout android:id="@id/answer_call_btns" android:layout_width="fill_parent" android:layout_height="78.0dip">
            <ImageButton android:layout_gravity="center" android:id="@id/reject_with_message" android:background="@drawable/reject_with_message_btn_background" android:padding="12.0dip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_reject_with_message" android:contentDescription="@string/voip_call_goto_chat_description" />
        </FrameLayout>
        <LinearLayout android:orientation="horizontal" android:id="@id/call_btns" android:visibility="gone" android:layout_width="fill_parent" android:layout_height="78.0dip">
            <ImageButton android:id="@id/end_call_btn" android:background="@drawable/btn_end_call_background" android:layout_width="0.0dip" android:layout_height="fill_parent" android:src="@drawable/btn_end_call" android:layout_weight="1.0" android:contentDescription="@string/voip_call_end_button_description" />
            <ImageButton android:id="@id/voip_call_btn" android:background="@drawable/btn_start_call_background" android:visibility="gone" android:layout_width="0.0dip" android:layout_height="fill_parent" android:src="@drawable/btn_start_call" android:layout_weight="1.0" android:contentDescription="@string/voip_call_start_button_description" />
        </LinearLayout>
        <LinearLayout android:orientation="horizontal" android:id="@id/audio_btns" android:visibility="gone" android:layout_width="fill_parent" android:layout_height="78.0dip">
            <LinearLayout android:orientation="vertical" android:layout_width="0.0dip" android:layout_height="wrap_content" android:layout_weight="1.0">
                <ImageButton android:id="@id/speaker_btn" android:background="#ff111111" android:paddingTop="17.0dip" android:paddingBottom="17.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/ic_speaker" android:contentDescription="@string/voip_call_speakerphone_toggle_description" />
                <View android:id="@id/speaker_btn_on" android:background="#b238caff" android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="10.0dip" />
            </LinearLayout>
            <LinearLayout android:orientation="vertical" android:layout_width="0.0dip" android:layout_height="wrap_content" android:layout_weight="1.0">
                <ImageButton android:id="@id/chat_btn" android:background="#ff111111" android:paddingTop="17.0dip" android:paddingBottom="17.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/ic_chat" android:contentDescription="@string/voip_call_goto_chat_description" />
                <View android:id="@id/chat_btn_on" android:background="#b238caff" android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="10.0dip" />
            </LinearLayout>
            <LinearLayout android:orientation="vertical" android:layout_width="0.0dip" android:layout_height="wrap_content" android:layout_weight="1.0">
                <ImageButton android:id="@id/mute_btn" android:background="#ff111111" android:paddingTop="17.0dip" android:paddingBottom="17.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/ic_mute" android:contentDescription="@string/voip_call_mute_toggle_description" />
                <View android:id="@id/mute_btn_on" android:background="#b238caff" android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="10.0dip" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
    <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_above="@id/footer" android:layout_below="@id/name">
        <ImageView android:id="@id/profile_picture" android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/ic_pic_contact_xlarge" android:scaleType="centerCrop" android:contentDescription="@string/contact_avatar_image" />
        <View android:layout_gravity="bottom" android:background="@drawable/call_photo_overlay" android:layout_width="fill_parent" android:layout_height="4.0dip" />
        <TextView android:textSize="28.0sp" android:textColor="@*android:color/white" android:gravity="center" android:layout_gravity="bottom" android:id="@id/user_hint" android:padding="12.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:shadowColor="@*android:color/black" android:shadowDx="1.0" android:shadowDy="1.0" android:shadowRadius="2.0" android:fontFamily="sans-serif-light" />
    </FrameLayout>
    <LinearLayout android:gravity="center" android:orientation="horizontal" android:id="@id/call_status_bar" android:background="#cc4abc34" android:paddingLeft="16.0dip" android:paddingTop="7.0dip" android:paddingRight="16.0dip" android:paddingBottom="7.0dip" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/name" android:animateLayoutChanges="true">
        <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="6.0dip" android:src="@drawable/call_icon" android:contentDescription="@string/call_icon_content_description" />
        <TextView android:textSize="16.0sp" android:textColor="#c6ffffff" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/voip_call_label" />
        <View android:layout_width="0.0dip" android:layout_height="1.0dip" android:layout_weight="1.0" />
        <TextView android:textSize="16.0sp" android:textColor="#c6ffffff" android:id="@id/call_status" android:layout_width="wrap_content" android:layout_height="wrap_content" />
    </LinearLayout>
</RelativeLayout>