summaryrefslogtreecommitdiff
path: root/java/com/android/contacts/common/compat
diff options
context:
space:
mode:
authorTobias Thierer <tobiast@google.com>2017-06-09 14:16:05 +0000
committerTobias Thierer <tobiast@google.com>2017-06-09 14:16:05 +0000
commitcded3beaf28a703e1ef8f71bbc6836e6806c3736 (patch)
treec1b5e8199b5996fc848e7455d04126b9cdbb3c39 /java/com/android/contacts/common/compat
parentc67d658e7daa453fe9ad9fd1a37f81eaf2048c44 (diff)
Revert "Update AOSP Dialer source from internal google3 repository at cl/158012278. am: 91ce7d2a47"
This reverts commit c67d658e7daa453fe9ad9fd1a37f81eaf2048c44. Reason for revert: This CL broke the sailfish-userdebug_javac-all target on master. Change-Id: I9b54333a654c00154ca84f4ece84bea4f07cc19b
Diffstat (limited to 'java/com/android/contacts/common/compat')
-rw-r--r--java/com/android/contacts/common/compat/ContactsCompat.java16
-rw-r--r--java/com/android/contacts/common/compat/PhoneAccountCompat.java55
-rw-r--r--java/com/android/contacts/common/compat/PhoneNumberUtilsCompat.java132
-rw-r--r--java/com/android/contacts/common/compat/TelephonyManagerCompat.java71
-rw-r--r--java/com/android/contacts/common/compat/telecom/TelecomManagerCompat.java260
5 files changed, 526 insertions, 8 deletions
diff --git a/java/com/android/contacts/common/compat/ContactsCompat.java b/java/com/android/contacts/common/compat/ContactsCompat.java
index e0c9b7e53..39d0b55d3 100644
--- a/java/com/android/contacts/common/compat/ContactsCompat.java
+++ b/java/com/android/contacts/common/compat/ContactsCompat.java
@@ -21,6 +21,7 @@ import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
+import com.android.dialer.compat.CompatUtils;
/** Compatibility class for {@link ContactsContract.Contacts} */
public class ContactsCompat {
@@ -28,6 +29,8 @@ public class ContactsCompat {
// TODO: Use N APIs
private static final Uri ENTERPRISE_CONTENT_FILTER_URI =
Uri.withAppendedPath(Contacts.CONTENT_URI, "filter_enterprise");
+ // Copied from ContactsContract.Contacts#ENTERPRISE_CONTACT_ID_BASE, which is hidden.
+ private static final long ENTERPRISE_CONTACT_ID_BASE = 1000000000;
/** Not instantiable. */
private ContactsCompat() {}
@@ -38,4 +41,17 @@ public class ContactsCompat {
}
return Contacts.CONTENT_FILTER_URI;
}
+
+ /**
+ * Return {@code true} if a contact ID is from the contacts provider on the enterprise profile.
+ */
+ public static boolean isEnterpriseContactId(long contactId) {
+ if (CompatUtils.isLollipopCompatible()) {
+ return Contacts.isEnterpriseContactId(contactId);
+ } else {
+ // copied from ContactsContract.Contacts.isEnterpriseContactId
+ return (contactId >= ENTERPRISE_CONTACT_ID_BASE)
+ && (contactId < ContactsContract.Profile.MIN_ID);
+ }
+ }
}
diff --git a/java/com/android/contacts/common/compat/PhoneAccountCompat.java b/java/com/android/contacts/common/compat/PhoneAccountCompat.java
index aa22c6861..6a24ec033 100644
--- a/java/com/android/contacts/common/compat/PhoneAccountCompat.java
+++ b/java/com/android/contacts/common/compat/PhoneAccountCompat.java
@@ -20,10 +20,33 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.support.annotation.Nullable;
import android.telecom.PhoneAccount;
+import android.util.Log;
+import com.android.dialer.compat.CompatUtils;
/** Compatiblity class for {@link android.telecom.PhoneAccount} */
public class PhoneAccountCompat {
+ private static final String TAG = PhoneAccountCompat.class.getSimpleName();
+
+ /**
+ * Gets the {@link Icon} associated with the given {@link PhoneAccount}
+ *
+ * @param phoneAccount the PhoneAccount from which to retrieve the Icon
+ * @return the Icon, or null
+ */
+ @Nullable
+ public static Icon getIcon(@Nullable PhoneAccount phoneAccount) {
+ if (phoneAccount == null) {
+ return null;
+ }
+
+ if (CompatUtils.isMarshmallowCompatible()) {
+ return phoneAccount.getIcon();
+ }
+
+ return null;
+ }
+
/**
* Builds and returns an icon {@code Drawable} to represent this {@code PhoneAccount} in a user
* interface.
@@ -38,16 +61,44 @@ public class PhoneAccountCompat {
if (phoneAccount == null || context == null) {
return null;
}
- return createIconDrawableMarshmallow(phoneAccount, context);
+
+ if (CompatUtils.isMarshmallowCompatible()) {
+ return createIconDrawableMarshmallow(phoneAccount, context);
+ }
+
+ if (CompatUtils.isLollipopMr1Compatible()) {
+ return createIconDrawableLollipopMr1(phoneAccount, context);
+ }
+ return null;
}
@Nullable
private static Drawable createIconDrawableMarshmallow(
PhoneAccount phoneAccount, Context context) {
- Icon accountIcon = phoneAccount.getIcon();
+ Icon accountIcon = getIcon(phoneAccount);
if (accountIcon == null) {
return null;
}
return accountIcon.loadDrawable(context);
}
+
+ @Nullable
+ private static Drawable createIconDrawableLollipopMr1(
+ PhoneAccount phoneAccount, Context context) {
+ try {
+ return (Drawable)
+ PhoneAccount.class
+ .getMethod("createIconDrawable", Context.class)
+ .invoke(phoneAccount, context);
+ } catch (ReflectiveOperationException e) {
+ return null;
+ } catch (Throwable t) {
+ Log.e(
+ TAG,
+ "Unexpected exception when attempting to call "
+ + "android.telecom.PhoneAccount#createIconDrawable",
+ t);
+ return null;
+ }
+ }
}
diff --git a/java/com/android/contacts/common/compat/PhoneNumberUtilsCompat.java b/java/com/android/contacts/common/compat/PhoneNumberUtilsCompat.java
index a6cfe07cd..960b340d8 100644
--- a/java/com/android/contacts/common/compat/PhoneNumberUtilsCompat.java
+++ b/java/com/android/contacts/common/compat/PhoneNumberUtilsCompat.java
@@ -17,7 +17,13 @@
package com.android.contacts.common.compat;
import android.telephony.PhoneNumberUtils;
+import android.text.Spannable;
+import android.text.TextUtils;
import android.text.style.TtsSpan;
+import com.android.dialer.compat.CompatUtils;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
/**
* This class contains static utility methods extracted from PhoneNumberUtils, and the methods were
@@ -31,16 +37,138 @@ public class PhoneNumberUtilsCompat {
/** Not instantiable. */
private PhoneNumberUtilsCompat() {}
+ public static String normalizeNumber(String phoneNumber) {
+ if (CompatUtils.isLollipopCompatible()) {
+ return PhoneNumberUtils.normalizeNumber(phoneNumber);
+ } else {
+ return normalizeNumberInternal(phoneNumber);
+ }
+ }
+
+ /** Implementation copied from {@link PhoneNumberUtils#normalizeNumber} */
+ private static String normalizeNumberInternal(String phoneNumber) {
+ if (TextUtils.isEmpty(phoneNumber)) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ int len = phoneNumber.length();
+ for (int i = 0; i < len; i++) {
+ char c = phoneNumber.charAt(i);
+ // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
+ int digit = Character.digit(c, 10);
+ if (digit != -1) {
+ sb.append(digit);
+ } else if (sb.length() == 0 && c == '+') {
+ sb.append(c);
+ } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(phoneNumber));
+ }
+ }
+ return sb.toString();
+ }
+
public static String formatNumber(
String phoneNumber, String phoneNumberE164, String defaultCountryIso) {
+ if (CompatUtils.isLollipopCompatible()) {
return PhoneNumberUtils.formatNumber(phoneNumber, phoneNumberE164, defaultCountryIso);
+ } else {
+ // This method was deprecated in API level 21, so it's only used on pre-L SDKs.
+ return PhoneNumberUtils.formatNumber(phoneNumber);
+ }
}
public static CharSequence createTtsSpannable(CharSequence phoneNumber) {
- return PhoneNumberUtils.createTtsSpannable(phoneNumber);
+ if (CompatUtils.isMarshmallowCompatible()) {
+ return PhoneNumberUtils.createTtsSpannable(phoneNumber);
+ } else {
+ return createTtsSpannableInternal(phoneNumber);
+ }
}
public static TtsSpan createTtsSpan(String phoneNumber) {
- return PhoneNumberUtils.createTtsSpan(phoneNumber);
+ if (CompatUtils.isMarshmallowCompatible()) {
+ return PhoneNumberUtils.createTtsSpan(phoneNumber);
+ } else if (CompatUtils.isLollipopCompatible()) {
+ return createTtsSpanLollipop(phoneNumber);
+ } else {
+ return null;
+ }
+ }
+
+ /** Copied from {@link PhoneNumberUtils#createTtsSpannable} */
+ private static CharSequence createTtsSpannableInternal(CharSequence phoneNumber) {
+ if (phoneNumber == null) {
+ return null;
+ }
+ Spannable spannable = Spannable.Factory.getInstance().newSpannable(phoneNumber);
+ addTtsSpanInternal(spannable, 0, spannable.length());
+ return spannable;
+ }
+
+ /** Compat method for addTtsSpan, see {@link PhoneNumberUtils#addTtsSpan} */
+ public static void addTtsSpan(Spannable s, int start, int endExclusive) {
+ if (CompatUtils.isMarshmallowCompatible()) {
+ PhoneNumberUtils.addTtsSpan(s, start, endExclusive);
+ } else {
+ addTtsSpanInternal(s, start, endExclusive);
+ }
+ }
+
+ /** Copied from {@link PhoneNumberUtils#addTtsSpan} */
+ private static void addTtsSpanInternal(Spannable s, int start, int endExclusive) {
+ s.setSpan(
+ createTtsSpan(s.subSequence(start, endExclusive).toString()),
+ start,
+ endExclusive,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+
+ /** Copied from {@link PhoneNumberUtils#createTtsSpan} */
+ private static TtsSpan createTtsSpanLollipop(String phoneNumberString) {
+ if (phoneNumberString == null) {
+ return null;
+ }
+
+ // Parse the phone number
+ final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+ PhoneNumber phoneNumber = null;
+ try {
+ // Don't supply a defaultRegion so this fails for non-international numbers because
+ // we don't want to TalkBalk to read a country code (e.g. +1) if it is not already
+ // present
+ phoneNumber = phoneNumberUtil.parse(phoneNumberString, /* defaultRegion */ null);
+ } catch (NumberParseException ignored) {
+ }
+
+ // Build a telephone tts span
+ final TtsSpan.TelephoneBuilder builder = new TtsSpan.TelephoneBuilder();
+ if (phoneNumber == null) {
+ // Strip separators otherwise TalkBack will be silent
+ // (this behavior was observed with TalkBalk 4.0.2 from their alpha channel)
+ builder.setNumberParts(splitAtNonNumerics(phoneNumberString));
+ } else {
+ if (phoneNumber.hasCountryCode()) {
+ builder.setCountryCode(Integer.toString(phoneNumber.getCountryCode()));
+ }
+ builder.setNumberParts(Long.toString(phoneNumber.getNationalNumber()));
+ }
+ return builder.build();
+ }
+
+ /**
+ * Split a phone number using spaces, ignoring anything that is not a digit
+ *
+ * @param number A {@code CharSequence} before splitting, e.g., "+20(123)-456#"
+ * @return A {@code String} after splitting, e.g., "20 123 456".
+ */
+ private static String splitAtNonNumerics(CharSequence number) {
+ StringBuilder sb = new StringBuilder(number.length());
+ for (int i = 0; i < number.length(); i++) {
+ sb.append(PhoneNumberUtils.isISODigit(number.charAt(i)) ? number.charAt(i) : " ");
+ }
+ // It is very important to remove extra spaces. At time of writing, any leading or trailing
+ // spaces, or any sequence of more than one space, will confuse TalkBack and cause the TTS
+ // span to be non-functional!
+ return sb.toString().replaceAll(" +", " ").trim();
}
}
diff --git a/java/com/android/contacts/common/compat/TelephonyManagerCompat.java b/java/com/android/contacts/common/compat/TelephonyManagerCompat.java
index 4a16fb855..7e4803ca5 100644
--- a/java/com/android/contacts/common/compat/TelephonyManagerCompat.java
+++ b/java/com/android/contacts/common/compat/TelephonyManagerCompat.java
@@ -27,6 +27,7 @@ import android.telecom.PhoneAccountHandle;
import android.telephony.TelephonyManager;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.compat.CompatUtils;
import java.lang.reflect.InvocationTargetException;
public class TelephonyManagerCompat {
@@ -48,6 +49,31 @@ public class TelephonyManagerCompat {
private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE";
/**
+ * @param telephonyManager The telephony manager instance to use for method calls.
+ * @return true if the current device is "voice capable".
+ * <p>"Voice capable" means that this device supports circuit-switched (i.e. voice) phone
+ * calls over the telephony network, and is allowed to display the in-call UI while a cellular
+ * voice call is active. This will be false on "data only" devices which can't make voice
+ * calls and don't support any in-call UI.
+ * <p>Note: the meaning of this flag is subtly different from the
+ * PackageManager.FEATURE_TELEPHONY system feature, which is available on any device with a
+ * telephony radio, even if the device is data-only.
+ */
+ public static boolean isVoiceCapable(@Nullable TelephonyManager telephonyManager) {
+ if (telephonyManager == null) {
+ return false;
+ }
+ if (CompatUtils.isLollipopMr1Compatible()
+ || CompatUtils.isMethodAvailable(TELEPHONY_MANAGER_CLASS, "isVoiceCapable")) {
+ // isVoiceCapable was unhidden in L-MR1
+ return telephonyManager.isVoiceCapable();
+ }
+ final int phoneType = telephonyManager.getPhoneType();
+ return phoneType == TelephonyManager.PHONE_TYPE_CDMA
+ || phoneType == TelephonyManager.PHONE_TYPE_GSM;
+ }
+
+ /**
* Returns the number of phones available. Returns 1 for Single standby mode (Single SIM
* functionality) Returns 2 for Dual standby mode.(Dual SIM functionality)
*
@@ -59,7 +85,31 @@ public class TelephonyManagerCompat {
if (telephonyManager == null) {
return 1;
}
- return telephonyManager.getPhoneCount();
+ if (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(TELEPHONY_MANAGER_CLASS, "getPhoneCount")) {
+ return telephonyManager.getPhoneCount();
+ }
+ return 1;
+ }
+
+ /**
+ * Returns the unique device ID of a subscription, for example, the IMEI for GSM and the MEID for
+ * CDMA phones. Return null if device ID is not available.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @param telephonyManager The telephony manager instance to use for method calls.
+ * @param slotId of which deviceID is returned
+ */
+ public static String getDeviceId(@Nullable TelephonyManager telephonyManager, int slotId) {
+ if (telephonyManager == null) {
+ return null;
+ }
+ if (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(TELEPHONY_MANAGER_CLASS, "getDeviceId", Integer.class)) {
+ return telephonyManager.getDeviceId(slotId);
+ }
+ return null;
}
/**
@@ -69,7 +119,14 @@ public class TelephonyManagerCompat {
* @return {@code true} if the device supports TTY mode, and {@code false} otherwise.
*/
public static boolean isTtyModeSupported(@Nullable TelephonyManager telephonyManager) {
- return telephonyManager != null && telephonyManager.isTtyModeSupported();
+ if (telephonyManager == null) {
+ return false;
+ }
+ if (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(TELEPHONY_MANAGER_CLASS, "isTtyModeSupported")) {
+ return telephonyManager.isTtyModeSupported();
+ }
+ return false;
}
/**
@@ -81,7 +138,15 @@ public class TelephonyManagerCompat {
*/
public static boolean isHearingAidCompatibilitySupported(
@Nullable TelephonyManager telephonyManager) {
- return telephonyManager != null && telephonyManager.isHearingAidCompatibilitySupported();
+ if (telephonyManager == null) {
+ return false;
+ }
+ if (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(
+ TELEPHONY_MANAGER_CLASS, "isHearingAidCompatibilitySupported")) {
+ return telephonyManager.isHearingAidCompatibilitySupported();
+ }
+ return false;
}
/**
diff --git a/java/com/android/contacts/common/compat/telecom/TelecomManagerCompat.java b/java/com/android/contacts/common/compat/telecom/TelecomManagerCompat.java
index 43eae589d..5687f6fbf 100644
--- a/java/com/android/contacts/common/compat/telecom/TelecomManagerCompat.java
+++ b/java/com/android/contacts/common/compat/telecom/TelecomManagerCompat.java
@@ -15,19 +15,275 @@
*/
package com.android.contacts.common.compat.telecom;
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
import android.support.annotation.Nullable;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import com.android.dialer.compat.CompatUtils;
+import java.util.ArrayList;
+import java.util.List;
/** Compatibility class for {@link android.telecom.TelecomManager}. */
public class TelecomManagerCompat {
+ public static final String TELECOM_MANAGER_CLASS = "android.telecom.TelecomManager";
+
// TODO: remove once this is available in android.telecom.Call
// b/33779976
public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
"android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
/**
+ * Places a new outgoing call to the provided address using the system telecom service with the
+ * specified intent.
+ *
+ * @param activity {@link Activity} used to start another activity for the given intent
+ * @param telecomManager the {@link TelecomManager} used to place a call, if possible
+ * @param intent the intent for the call
+ */
+ public static void placeCall(
+ @Nullable Activity activity,
+ @Nullable TelecomManager telecomManager,
+ @Nullable Intent intent) {
+ if (activity == null || telecomManager == null || intent == null) {
+ return;
+ }
+ if (CompatUtils.isMarshmallowCompatible()) {
+ telecomManager.placeCall(intent.getData(), intent.getExtras());
+ return;
+ }
+ activity.startActivityForResult(intent, 0);
+ }
+
+ /**
+ * Get the URI for running an adn query.
+ *
+ * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
+ * @param accountHandle The handle for the account to derive an adn query URI for or {@code null}
+ * to return a URI which will use the default account.
+ * @return The URI (with the content:// scheme) specific to the specified {@link PhoneAccount} for
+ * the the content retrieve.
+ */
+ public static Uri getAdnUriForPhoneAccount(
+ @Nullable TelecomManager telecomManager, PhoneAccountHandle accountHandle) {
+ if (telecomManager != null
+ && (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(
+ TELECOM_MANAGER_CLASS, "getAdnUriForPhoneAccount", PhoneAccountHandle.class))) {
+ return telecomManager.getAdnUriForPhoneAccount(accountHandle);
+ }
+ return Uri.parse("content://icc/adn");
+ }
+
+ /**
+ * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
+ * calls. The returned list includes only those accounts which have been explicitly enabled by the
+ * user.
+ *
+ * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
+ * @return A list of PhoneAccountHandle objects.
+ */
+ public static List<PhoneAccountHandle> getCallCapablePhoneAccounts(
+ @Nullable TelecomManager telecomManager) {
+ if (telecomManager != null
+ && (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(
+ TELECOM_MANAGER_CLASS, "getCallCapablePhoneAccounts"))) {
+ return telecomManager.getCallCapablePhoneAccounts();
+ }
+ return new ArrayList<>();
+ }
+
+ /**
+ * Used to determine the currently selected default dialer package.
+ *
+ * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
+ * @return package name for the default dialer package or null if no package has been selected as
+ * the default dialer.
+ */
+ @Nullable
+ public static String getDefaultDialerPackage(@Nullable TelecomManager telecomManager) {
+ if (telecomManager != null && CompatUtils.isDefaultDialerCompatible()) {
+ return telecomManager.getDefaultDialerPackage();
+ }
+ return null;
+ }
+
+ /**
+ * Return the {@link PhoneAccount} which will be used to place outgoing calls to addresses with
+ * the specified {@code uriScheme}. This PhoneAccount will always be a member of the list which is
+ * returned from invoking {@link TelecomManager#getCallCapablePhoneAccounts()}. The specific
+ * account returned depends on the following priorities:
+ *
+ * <p>1. If the user-selected default PhoneAccount supports the specified scheme, it will be
+ * returned. 2. If there exists only one PhoneAccount that supports the specified scheme, it will
+ * be returned.
+ *
+ * <p>If no PhoneAccount fits the criteria above, this method will return {@code null}.
+ *
+ * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
+ * @param uriScheme The URI scheme.
+ * @return The {@link PhoneAccountHandle} corresponding to the account to be used.
+ */
+ @Nullable
+ public static PhoneAccountHandle getDefaultOutgoingPhoneAccount(
+ @Nullable TelecomManager telecomManager, @Nullable String uriScheme) {
+ if (telecomManager != null
+ && (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(
+ TELECOM_MANAGER_CLASS, "getDefaultOutgoingPhoneAccount", String.class))) {
+ return telecomManager.getDefaultOutgoingPhoneAccount(uriScheme);
+ }
+ return null;
+ }
+
+ /**
+ * Return the line 1 phone number for given phone account.
+ *
+ * @param telecomManager the {@link TelecomManager} to use in the event that {@link
+ * TelecomManager#getLine1Number(PhoneAccountHandle)} is available
+ * @param telephonyManager the {@link TelephonyManager} to use if TelecomManager#getLine1Number is
+ * unavailable
+ * @param phoneAccountHandle the phoneAccountHandle upon which to check the line one number
+ * @return the line one number
+ */
+ @Nullable
+ public static String getLine1Number(
+ @Nullable TelecomManager telecomManager,
+ @Nullable TelephonyManager telephonyManager,
+ @Nullable PhoneAccountHandle phoneAccountHandle) {
+ if (telecomManager != null && CompatUtils.isMarshmallowCompatible()) {
+ return telecomManager.getLine1Number(phoneAccountHandle);
+ }
+ if (telephonyManager != null) {
+ return telephonyManager.getLine1Number();
+ }
+ return null;
+ }
+
+ /**
+ * Return whether a given phone number is the configured voicemail number for a particular phone
+ * account.
+ *
+ * @param telecomManager the {@link TelecomManager} to use for checking the number.
+ * @param accountHandle The handle for the account to check the voicemail number against
+ * @param number The number to look up.
+ */
+ public static boolean isVoiceMailNumber(
+ @Nullable TelecomManager telecomManager,
+ @Nullable PhoneAccountHandle accountHandle,
+ @Nullable String number) {
+ if (telecomManager != null
+ && (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(
+ TELECOM_MANAGER_CLASS,
+ "isVoiceMailNumber",
+ PhoneAccountHandle.class,
+ String.class))) {
+ return telecomManager.isVoiceMailNumber(accountHandle, number);
+ }
+ return PhoneNumberUtils.isVoiceMailNumber(number);
+ }
+
+ /**
+ * Return the {@link PhoneAccount} for a specified {@link PhoneAccountHandle}. Object includes
+ * resources which can be used in a user interface.
+ *
+ * @param telecomManager the {@link TelecomManager} used for method calls, if possible.
+ * @param account The {@link PhoneAccountHandle}.
+ * @return The {@link PhoneAccount} object or null if it doesn't exist.
+ */
+ @Nullable
+ public static PhoneAccount getPhoneAccount(
+ @Nullable TelecomManager telecomManager, @Nullable PhoneAccountHandle accountHandle) {
+ if (telecomManager != null
+ && (CompatUtils.isMethodAvailable(
+ TELECOM_MANAGER_CLASS, "getPhoneAccount", PhoneAccountHandle.class))) {
+ return telecomManager.getPhoneAccount(accountHandle);
+ }
+ return null;
+ }
+
+ /**
+ * Return the voicemail number for a given phone account.
+ *
+ * @param telecomManager The {@link TelecomManager} object to use for retrieving the voicemail
+ * number if accountHandle is specified.
+ * @param telephonyManager The {@link TelephonyManager} object to use for retrieving the voicemail
+ * number if accountHandle is null.
+ * @param accountHandle The handle for the phone account.
+ * @return The voicemail number for the phone account, and {@code null} if one has not been
+ * configured.
+ */
+ @Nullable
+ public static String getVoiceMailNumber(
+ @Nullable TelecomManager telecomManager,
+ @Nullable TelephonyManager telephonyManager,
+ @Nullable PhoneAccountHandle accountHandle) {
+ if (telecomManager != null
+ && (CompatUtils.isMethodAvailable(
+ TELECOM_MANAGER_CLASS, "getVoiceMailNumber", PhoneAccountHandle.class))) {
+ return telecomManager.getVoiceMailNumber(accountHandle);
+ } else if (telephonyManager != null) {
+ return telephonyManager.getVoiceMailNumber();
+ }
+ return null;
+ }
+
+ /**
+ * Processes the specified dial string as an MMI code. MMI codes are any sequence of characters
+ * entered into the dialpad that contain a "*" or "#". Some of these sequences launch special
+ * behavior through handled by Telephony.
+ *
+ * @param telecomManager The {@link TelecomManager} object to use for handling MMI.
+ * @param dialString The digits to dial.
+ * @return {@code true} if the digits were processed as an MMI code, {@code false} otherwise.
+ */
+ public static boolean handleMmi(
+ @Nullable TelecomManager telecomManager,
+ @Nullable String dialString,
+ @Nullable PhoneAccountHandle accountHandle) {
+ if (telecomManager == null || TextUtils.isEmpty(dialString)) {
+ return false;
+ }
+ if (CompatUtils.isMarshmallowCompatible()) {
+ return telecomManager.handleMmi(dialString, accountHandle);
+ }
+
+ Object handleMmiResult =
+ CompatUtils.invokeMethod(
+ telecomManager,
+ "handleMmi",
+ new Class<?>[] {PhoneAccountHandle.class, String.class},
+ new Object[] {accountHandle, dialString});
+ if (handleMmiResult != null) {
+ return (boolean) handleMmiResult;
+ }
+
+ return telecomManager.handleMmi(dialString);
+ }
+
+ /**
+ * Silences the ringer if a ringing call exists. Noop if {@link TelecomManager#silenceRinger()} is
+ * unavailable.
+ *
+ * @param telecomManager the TelecomManager to use to silence the ringer.
+ */
+ public static void silenceRinger(@Nullable TelecomManager telecomManager) {
+ if (telecomManager != null
+ && (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "silenceRinger"))) {
+ telecomManager.silenceRinger();
+ }
+ }
+
+ /**
* Returns the current SIM call manager. Apps must be prepared for this method to return null,
* indicating that there currently exists no registered SIM call manager.
*
@@ -36,7 +292,9 @@ public class TelecomManagerCompat {
*/
@Nullable
public static PhoneAccountHandle getSimCallManager(TelecomManager telecomManager) {
- if (telecomManager != null) {
+ if (telecomManager != null
+ && (CompatUtils.isMarshmallowCompatible()
+ || CompatUtils.isMethodAvailable(TELECOM_MANAGER_CLASS, "getSimCallManager"))) {
return telecomManager.getSimCallManager();
}
return null;