Merge "Convert unnecessary RelativeLayout to FrameLayout"
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 3d80835..8e161bc 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -86,7 +86,7 @@
     <string name="dialer_settings_label" msgid="4305043242594150479">"Ρυθμίσεις"</string>
     <string name="menu_newContact" msgid="1209922412763274638">"Νέα επαφή"</string>
     <string name="menu_allContacts" msgid="6948308384034051670">"Όλες οι επαφές"</string>
-    <string name="callDetailTitle" msgid="5340227785196217938">"Λεπτομέρειες κλήσης"</string>
+    <string name="callDetailTitle" msgid="5340227785196217938">"Στοιχ. κλήσης"</string>
     <string name="toast_call_detail_error" msgid="6947041258280380832">"Οι λεπτομέρειες δεν είναι διαθέσιμες"</string>
     <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Χρησιμοποιήστε το πληκτρολόγιο αφής ηχητικών τόνων"</string>
     <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"Επιστροφή στην κλήση που βρίσκεται σε εξέλιξη"</string>
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 6c57650..fb663d7 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -50,9 +50,9 @@
 import android.widget.Toast;
 
 import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
 import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.CallUtil;
 import com.android.dialer.calllog.CallDetailHistoryAdapter;
 import com.android.dialer.calllog.CallTypeHelper;
 import com.android.dialer.calllog.ContactInfo;
@@ -62,6 +62,7 @@
 import com.android.dialer.calllog.PhoneNumberUtilsWrapper;
 import com.android.dialer.util.AsyncTaskExecutor;
 import com.android.dialer.util.AsyncTaskExecutors;
+import com.android.dialer.util.PrivilegedCallUtil;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.voicemail.VoicemailPlaybackFragment;
 import com.android.dialer.voicemail.VoicemailStatusHelper;
@@ -364,8 +365,8 @@
                         getSystemService(Context.TELEPHONY_SERVICE);
                 if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
                     DialerUtils.startActivityWithErrorToast(this,
-                            CallUtil.getCallIntent(Uri.fromParts(PhoneAccount.SCHEME_TEL, mNumber,
-                                    null)), R.string.call_not_available);
+                            PrivilegedCallUtil.getCallIntent(Uri.fromParts(PhoneAccount.SCHEME_TEL,
+                                    mNumber, null)), R.string.call_not_available);
                     return true;
                 }
             }
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index beec280..01d59c4 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -59,7 +59,6 @@
 import android.widget.PopupMenu;
 import android.widget.Toast;
 
-import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.activity.TransactionSafeActivity;
 import com.android.contacts.common.dialog.ClearFrequentsDialog;
 import com.android.contacts.common.interactions.ImportExportDialogFragment;
@@ -83,6 +82,7 @@
 import com.android.dialer.list.SmartDialSearchFragment;
 import com.android.dialer.list.SpeedDialFragment;
 import com.android.dialer.settings.DialerSettingsActivity;
+import com.android.dialer.util.PrivilegedCallUtil;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.widget.ActionBarController;
 import com.android.dialer.widget.SearchEditTextLayout;
@@ -91,6 +91,8 @@
 import com.android.phone.common.animation.AnimUtils;
 import com.android.phone.common.animation.AnimationListenerAdapter;
 
+import junit.framework.Assert;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -406,12 +408,11 @@
         mOverflowMenu = buildOptionsMenu(searchEditTextLayout);
         optionsMenuButton.setOnTouchListener(mOverflowMenu.getDragToOpenListener());
 
-        // Add the favorites fragment, and the dialpad fragment, but only if savedInstanceState
-        // is null. Otherwise the fragment manager takes care of recreating these fragments.
+        // Add the favorites fragment but only if savedInstanceState is null. Otherwise the
+        // fragment manager is responsible for recreating it.
         if (savedInstanceState == null) {
             getFragmentManager().beginTransaction()
                     .add(R.id.dialtacts_frame, new ListsFragment(), TAG_FAVORITES_FRAGMENT)
-                    .add(R.id.dialtacts_container, new DialpadFragment(), TAG_DIALPAD_FRAGMENT)
                     .commit();
         } else {
             mSearchQuery = savedInstanceState.getString(KEY_SEARCH_QUERY);
@@ -554,7 +555,7 @@
     public void onAttachFragment(Fragment fragment) {
         if (fragment instanceof DialpadFragment) {
             mDialpadFragment = (DialpadFragment) fragment;
-            if (!mShowDialpadOnResume) {
+            if (!mIsDialpadShown && !mShowDialpadOnResume) {
                 final FragmentTransaction transaction = getFragmentManager().beginTransaction();
                 transaction.hide(mDialpadFragment);
                 transaction.commit();
@@ -667,12 +668,19 @@
             return;
         }
         mIsDialpadShown = true;
-        mDialpadFragment.setAnimate(animate);
+
         mListsFragment.setUserVisibleHint(false);
-        AnalyticsUtil.sendScreenView(mDialpadFragment);
 
         final FragmentTransaction ft = getFragmentManager().beginTransaction();
-        ft.show(mDialpadFragment);
+        if (mDialpadFragment == null) {
+            mDialpadFragment = new DialpadFragment();
+            ft.add(R.id.dialtacts_container, mDialpadFragment, TAG_DIALPAD_FRAGMENT);
+        } else {
+            ft.show(mDialpadFragment);
+        }
+
+        mDialpadFragment.setAnimate(animate);
+        AnalyticsUtil.sendScreenView(mDialpadFragment);
         ft.commit();
 
         if (animate) {
@@ -691,6 +699,7 @@
      * Callback from child DialpadFragment when the dialpad is shown.
      */
     public void onDialpadShown() {
+        Assert.assertNotNull(mDialpadFragment);
         if (mDialpadFragment.getAnimate()) {
             mDialpadFragment.getView().startAnimation(mSlideIn);
         } else {
@@ -742,7 +751,7 @@
      * Finishes hiding the dialpad fragment after any animations are completed.
      */
     private void commitDialpadFragmentHide() {
-        if (!mStateSaved && !mDialpadFragment.isHidden()) {
+        if (!mStateSaved && mDialpadFragment != null && !mDialpadFragment.isHidden()) {
             final FragmentTransaction ft = getFragmentManager().beginTransaction();
             ft.hide(mDialpadFragment);
             ft.commit();
@@ -850,14 +859,12 @@
             return;
         }
 
-        if (mDialpadFragment != null) {
-            final boolean phoneIsInUse = phoneIsInUse();
-            if (phoneIsInUse || (intent.getData() !=  null && isDialIntent(intent))) {
-                mDialpadFragment.setStartedFromNewIntent(true);
-                if (phoneIsInUse && !mDialpadFragment.isVisible()) {
-                    mInCallDialpadUp = true;
-                }
-                showDialpadFragment(false);
+        final boolean phoneIsInUse = phoneIsInUse();
+        if (phoneIsInUse || (intent.getData() !=  null && isDialIntent(intent))) {
+            showDialpadFragment(false);
+            mDialpadFragment.setStartedFromNewIntent(true);
+            if (phoneIsInUse && !mDialpadFragment.isVisible()) {
+                mInCallDialpadUp = true;
             }
         }
     }
@@ -959,7 +966,11 @@
         }
 
         mSearchView.setText(null);
-        mDialpadFragment.clearDialpad();
+
+        if (mDialpadFragment != null) {
+            mDialpadFragment.clearDialpad();
+        }
+
         setNotInSearchUi();
 
         final FragmentTransaction transaction = getFragmentManager().beginTransaction();
@@ -972,7 +983,8 @@
         transaction.commit();
 
         mListsFragment.getView().animate().alpha(1).withLayer();
-        if (!mDialpadFragment.isVisible()) {
+
+        if (mDialpadFragment == null || !mDialpadFragment.isVisible()) {
             // If the dialpad fragment wasn't previously visible, then send a screen view because
             // we are exiting regular search. Otherwise, the screen view will be sent by
             // {@link #hideDialpadFragment}.
@@ -1153,8 +1165,8 @@
     @Override
     public void onCallNumberDirectly(String phoneNumber, boolean isVideoCall) {
         Intent intent = isVideoCall ?
-                CallUtil.getVideoCallIntent(phoneNumber, getCallOrigin()) :
-                CallUtil.getCallIntent(phoneNumber, getCallOrigin());
+                PrivilegedCallUtil.getVideoCallIntent(phoneNumber, getCallOrigin()) :
+                PrivilegedCallUtil.getCallIntent(phoneNumber, getCallOrigin());
         DialerUtils.startActivityWithErrorToast(this, intent);
         mClearSearchOnPause = true;
     }
diff --git a/src/com/android/dialer/PhoneCallDetailsHelper.java b/src/com/android/dialer/PhoneCallDetailsHelper.java
index b4e8171..7855a1d 100644
--- a/src/com/android/dialer/PhoneCallDetailsHelper.java
+++ b/src/com/android/dialer/PhoneCallDetailsHelper.java
@@ -28,7 +28,6 @@
 import android.view.View;
 import android.widget.TextView;
 
-import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.testing.NeededForTesting;
 import com.android.contacts.common.util.PhoneNumberHelper;
 import com.android.dialer.calllog.ContactInfo;
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index bb20a13..9c50a3b 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -19,7 +19,6 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
-import android.content.Loader;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteFullException;
@@ -48,7 +47,6 @@
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
-import com.android.contacts.common.util.PhoneNumberHelper;
 import com.android.contacts.common.model.Contact;
 import com.android.contacts.common.model.ContactLoader;
 import com.android.contacts.common.util.UriUtils;
diff --git a/src/com/android/dialer/calllog/IntentProvider.java b/src/com/android/dialer/calllog/IntentProvider.java
index 3084e24..8e96da7 100644
--- a/src/com/android/dialer/calllog/IntentProvider.java
+++ b/src/com/android/dialer/calllog/IntentProvider.java
@@ -23,8 +23,8 @@
 import android.provider.CallLog.Calls;
 import android.telecom.PhoneAccountHandle;
 
-import com.android.contacts.common.CallUtil;
 import com.android.dialer.CallDetailActivity;
+import com.android.dialer.util.PrivilegedCallUtil;
 
 /**
  * Used to create an intent to attach to an action in the call log.
@@ -46,7 +46,7 @@
         return new IntentProvider() {
             @Override
             public Intent getIntent(Context context) {
-                return CallUtil.getCallIntent(number, accountHandle);
+                return PrivilegedCallUtil.getCallIntent(number, accountHandle);
             }
         };
     }
@@ -60,7 +60,7 @@
         return new IntentProvider() {
             @Override
             public Intent getIntent(Context context) {
-                return CallUtil.getVideoCallIntent(number, accountHandle);
+                return PrivilegedCallUtil.getVideoCallIntent(number, accountHandle);
             }
         };
     }
@@ -69,7 +69,7 @@
         return new IntentProvider() {
             @Override
             public Intent getIntent(Context context) {
-                return CallUtil.getVoicemailIntent();
+                return PrivilegedCallUtil.getVoicemailIntent();
             }
         };
     }
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 71b9ae8..fbf862f 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -45,13 +45,10 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.text.Editable;
-import android.text.SpannableString;
 import android.text.TextUtils;
 import android.text.TextWatcher;
-import android.text.style.RelativeSizeSpan;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -71,7 +68,6 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
-import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.GeoUtil;
 import com.android.contacts.common.util.PhoneNumberFormatter;
@@ -82,6 +78,7 @@
 import com.android.dialer.R;
 import com.android.dialer.SpecialCharSequenceMgr;
 import com.android.dialer.calllog.PhoneAccountUtils;
+import com.android.dialer.util.PrivilegedCallUtil;
 import com.android.dialer.util.DialerUtils;
 import com.android.phone.common.CallLogAsync;
 import com.android.phone.common.HapticFeedback;
@@ -318,7 +315,9 @@
     public void onCreate(Bundle state) {
         Trace.beginSection(TAG + " onCreate");
         super.onCreate(state);
-        mFirstLaunch = true;
+
+        mFirstLaunch = state == null;
+
         mCurrentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
 
         try {
@@ -358,7 +357,6 @@
         Trace.endSection();
 
         Trace.beginSection(TAG + " setup views");
-        Resources r = getResources();
 
         mDialpadView = (DialpadView) fragmentView.findViewById(R.id.dialpad_view);
         mDialpadView.setCanDigitsBeEdited(true);
@@ -654,8 +652,6 @@
             showDialpadChooser(false);
         }
 
-        mFirstLaunch = false;
-
         stopWatch.lap("hnt");
 
         updateDeleteButtonEnabledState();
@@ -674,6 +670,14 @@
         mOverflowMenuButton.setOnTouchListener(mOverflowPopupMenu.getDragToOpenListener());
         mOverflowMenuButton.setOnClickListener(this);
         mOverflowMenuButton.setVisibility(isDigitsEmpty() ? View.INVISIBLE : View.VISIBLE);
+
+        if (mFirstLaunch) {
+            // The onHiddenChanged callback does not get called the first time the fragment is
+            // attached, so call it ourselves here.
+            onHiddenChanged(false);
+        }
+
+        mFirstLaunch = false;
         Trace.endSection();
     }
 
@@ -1002,7 +1006,8 @@
     }
 
     public void callVoicemail() {
-        DialerUtils.startActivityWithErrorToast(getActivity(), CallUtil.getVoicemailIntent());
+        DialerUtils.startActivityWithErrorToast(getActivity(), PrivilegedCallUtil
+                .getVoicemailIntent());
         hideAndClearDialpad(false);
     }
 
@@ -1098,7 +1103,7 @@
                 // Clear the digits just in case.
                 clearDialpad();
             } else {
-                final Intent intent = CallUtil.getCallIntent(number,
+                final Intent intent = PrivilegedCallUtil.getCallIntent(number,
                         (getActivity() instanceof DialtactsActivity ?
                                 ((DialtactsActivity) getActivity()).getCallOrigin() : null));
                 DialerUtils.startActivityWithErrorToast(getActivity(), intent);
@@ -1628,7 +1633,7 @@
     }
 
     private Intent newFlashIntent() {
-        final Intent intent = CallUtil.getCallIntent(EMPTY_NUMBER);
+        final Intent intent = PrivilegedCallUtil.getCallIntent(EMPTY_NUMBER);
         intent.putExtra(EXTRA_SEND_EMPTY_FLASH, true);
         return intent;
     }
diff --git a/src/com/android/dialer/interactions/PhoneNumberInteraction.java b/src/com/android/dialer/interactions/PhoneNumberInteraction.java
index de217ce..78c468b 100644
--- a/src/com/android/dialer/interactions/PhoneNumberInteraction.java
+++ b/src/com/android/dialer/interactions/PhoneNumberInteraction.java
@@ -45,7 +45,6 @@
 import android.widget.ListAdapter;
 import android.widget.TextView;
 
-import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.Collapser;
 import com.android.contacts.common.Collapser.Collapsible;
 import com.android.contacts.common.MoreContactUtils;
@@ -53,6 +52,7 @@
 import com.android.contacts.common.util.ContactDisplayUtils;
 import com.android.dialer.R;
 import com.android.dialer.contact.ContactUpdateService;
+import com.android.dialer.util.PrivilegedCallUtil;
 import com.android.dialer.util.DialerUtils;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -322,7 +322,7 @@
                         Intent.ACTION_SENDTO, Uri.fromParts("sms", phoneNumber, null));
                 break;
             default:
-                intent = CallUtil.getCallIntent(phoneNumber, callOrigin);
+                intent = PrivilegedCallUtil.getCallIntent(phoneNumber, callOrigin);
                 break;
         }
         DialerUtils.startActivityWithErrorToast(context, intent);
diff --git a/src/com/android/dialer/list/RegularSearchListAdapter.java b/src/com/android/dialer/list/RegularSearchListAdapter.java
index f1f2ae0..9d6694a 100644
--- a/src/com/android/dialer/list/RegularSearchListAdapter.java
+++ b/src/com/android/dialer/list/RegularSearchListAdapter.java
@@ -18,12 +18,10 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
-import android.provider.ContactsContract;
 import android.text.TextUtils;
 
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.list.DirectoryPartition;
-import com.android.contacts.common.list.PhoneNumberListAdapter;
 import com.android.dialer.calllog.ContactInfo;
 import com.android.dialer.service.CachedNumberLookupService;
 import com.android.dialer.service.CachedNumberLookupService.CachedContactInfo;
diff --git a/src/com/android/dialer/list/SmartDialNumberListAdapter.java b/src/com/android/dialer/list/SmartDialNumberListAdapter.java
index 04c0d62..db96682 100644
--- a/src/com/android/dialer/list/SmartDialNumberListAdapter.java
+++ b/src/com/android/dialer/list/SmartDialNumberListAdapter.java
@@ -20,15 +20,12 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Callable;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.list.ContactListItemView;
-import com.android.contacts.common.list.PhoneNumberListAdapter;
-import com.android.contacts.common.list.PhoneNumberListAdapter.PhoneQuery;
 import com.android.dialer.dialpad.SmartDialCursorLoader;
 import com.android.dialer.dialpad.SmartDialNameMatcher;
 import com.android.dialer.dialpad.SmartDialPrefix;
diff --git a/src/com/android/dialer/util/PrivilegedCallUtil.java b/src/com/android/dialer/util/PrivilegedCallUtil.java
new file mode 100644
index 0000000..88adc72
--- /dev/null
+++ b/src/com/android/dialer/util/PrivilegedCallUtil.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 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
+ */
+
+package com.android.dialer.util;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
+
+import com.android.contacts.common.CallUtil;
+import com.android.phone.common.PhoneConstants;
+
+/**
+ * Utilities related to calls that can only be used by system apps. These
+ * use {@link Intent#ACTION_CALL_PRIVILEGED}.
+ */
+public class PrivilegedCallUtil {
+
+    /**
+     * Return an Intent for making a phone call. Scheme (e.g. tel, sip) will be determined
+     * automatically.
+     */
+    public static Intent getCallIntent(String number) {
+        return getCallIntent(number, null, null);
+    }
+
+    /**
+     * Return an Intent for making a phone call. A given Uri will be used as is (without any
+     * sanity check).
+     */
+    public static Intent getCallIntent(Uri uri) {
+        return getCallIntent(uri, null, null);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(String)} but also accept a call origin.
+     * For more information about call origin, see comments in Phone package (PhoneApp).
+     */
+    public static Intent getCallIntent(String number, String callOrigin) {
+        return getCallIntent(CallUtil.getCallUri(number), callOrigin, null);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(String)} but also include {@code Account}.
+     */
+    public static Intent getCallIntent(String number, PhoneAccountHandle accountHandle) {
+        return getCallIntent(number, null, accountHandle);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(android.net.Uri)} but also include {@code Account}.
+     */
+    public static Intent getCallIntent(Uri uri, PhoneAccountHandle accountHandle) {
+        return getCallIntent(uri, null, accountHandle);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(String, String)} but also include {@code Account}.
+     */
+    public static Intent getCallIntent(
+            String number, String callOrigin, PhoneAccountHandle accountHandle) {
+        return getCallIntent(CallUtil.getCallUri(number), callOrigin, accountHandle);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(android.net.Uri)} but also accept a call
+     * origin and {@code Account}.
+     * For more information about call origin, see comments in Phone package (PhoneApp).
+     */
+    public static Intent getCallIntent(
+            Uri uri, String callOrigin, PhoneAccountHandle accountHandle) {
+        return getCallIntent(uri, callOrigin, accountHandle,
+                VideoProfile.VideoState.AUDIO_ONLY);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(String, String)} for starting a video call.
+     */
+    public static Intent getVideoCallIntent(String number, String callOrigin) {
+        return getCallIntent(CallUtil.getCallUri(number), callOrigin, null,
+                VideoProfile.VideoState.BIDIRECTIONAL);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(String, String, android.telecom.PhoneAccountHandle)} for
+     * starting a video call.
+     */
+    public static Intent getVideoCallIntent(
+            String number, String callOrigin, PhoneAccountHandle accountHandle) {
+        return getCallIntent(CallUtil.getCallUri(number), callOrigin, accountHandle,
+                VideoProfile.VideoState.BIDIRECTIONAL);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(String, String, android.telecom.PhoneAccountHandle)} for
+     * starting a video call.
+     */
+    public static Intent getVideoCallIntent(String number, PhoneAccountHandle accountHandle) {
+        return getVideoCallIntent(number, null, accountHandle);
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(android.net.Uri)} for calling Voicemail.
+     */
+    public static Intent getVoicemailIntent() {
+        return getCallIntent(Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null));
+    }
+
+    /**
+     * A variant of {@link #getCallIntent(android.net.Uri)} but also accept a call
+     * origin and {@code Account} and {@code VideoCallProfile} state.
+     * For more information about call origin, see comments in Phone package (PhoneApp).
+     */
+    public static Intent getCallIntent(
+            Uri uri, String callOrigin, PhoneAccountHandle accountHandle, int videoState) {
+        final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, uri);
+        intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
+        if (callOrigin != null) {
+            intent.putExtra(PhoneConstants.EXTRA_CALL_ORIGIN, callOrigin);
+        }
+        if (accountHandle != null) {
+            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle);
+        }
+
+        return intent;
+    }
+}