diff options
Diffstat (limited to 'java/com/android/dialer/compat')
-rw-r--r-- | java/com/android/dialer/compat/CompatUtils.java | 167 | ||||
-rw-r--r-- | java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java | 200 |
2 files changed, 215 insertions, 152 deletions
diff --git a/java/com/android/dialer/compat/CompatUtils.java b/java/com/android/dialer/compat/CompatUtils.java index 673cb709b..584f20549 100644 --- a/java/com/android/dialer/compat/CompatUtils.java +++ b/java/com/android/dialer/compat/CompatUtils.java @@ -15,16 +15,15 @@ */ package com.android.dialer.compat; +import android.content.Context; import android.os.Build; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.util.Log; -import java.lang.reflect.InvocationTargetException; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.os.LocaleList; +import java.util.Locale; public final class CompatUtils { - private static final String TAG = CompatUtils.class.getSimpleName(); - /** PrioritizedMimeType is added in API level 23. */ public static boolean hasPrioritizedMimeType() { return SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.M) >= Build.VERSION_CODES.M; @@ -71,152 +70,16 @@ public final class CompatUtils { return SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.LOLLIPOP) >= Build.VERSION_CODES.M; } - /** - * Determines if this version is compatible with a default dialer. Can also force the version to - * be lower through {@link SdkVersionOverride}. - * - * @return {@code true} if default dialer is a feature on this device, {@code false} otherwise. - */ - public static boolean isDefaultDialerCompatible() { - return isMarshmallowCompatible(); - } - - /** - * Determines if this version is compatible with Lollipop Mr1-specific APIs. Can also force the - * version to be lower through SdkVersionOverride. - * - * @return {@code true} if runtime sdk is compatible with Lollipop MR1, {@code false} otherwise. - */ - public static boolean isLollipopMr1Compatible() { - return SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.LOLLIPOP_MR1) - >= Build.VERSION_CODES.LOLLIPOP_MR1; - } - - /** - * Determines if this version is compatible with Marshmallow-specific APIs. Can also force the - * version to be lower through SdkVersionOverride. - * - * @return {@code true} if runtime sdk is compatible with Marshmallow, {@code false} otherwise. - */ - public static boolean isMarshmallowCompatible() { - return SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.LOLLIPOP) >= Build.VERSION_CODES.M; - } - - /** - * Determines if the given class is available. Can be used to check if system apis exist at - * runtime. - * - * @param className the name of the class to look for. - * @return {@code true} if the given class is available, {@code false} otherwise or if className - * is empty. - */ - public static boolean isClassAvailable(@Nullable String className) { - if (TextUtils.isEmpty(className)) { - return false; + /** Returns locale of the device. */ + public static Locale getLocale(Context context) { + if (VERSION.SDK_INT >= VERSION_CODES.N) { + LocaleList localList = context.getResources().getConfiguration().getLocales(); + if (!localList.isEmpty()) { + return localList.get(0); + } + return Locale.getDefault(); + } else { + return context.getResources().getConfiguration().locale; } - try { - Class.forName(className); - return true; - } catch (ClassNotFoundException e) { - return false; - } catch (Throwable t) { - Log.e( - TAG, - "Unexpected exception when checking if class:" + className + " exists at " + "runtime", - t); - return false; - } - } - - /** - * Determines if the given class's method is available to call. Can be used to check if system - * apis exist at runtime. - * - * @param className the name of the class to look for - * @param methodName the name of the method to look for - * @param parameterTypes the needed parameter types for the method to look for - * @return {@code true} if the given class is available, {@code false} otherwise or if className - * or methodName are empty. - */ - public static boolean isMethodAvailable( - @Nullable String className, @Nullable String methodName, Class<?>... parameterTypes) { - if (TextUtils.isEmpty(className) || TextUtils.isEmpty(methodName)) { - return false; - } - - try { - Class.forName(className).getMethod(methodName, parameterTypes); - return true; - } catch (ClassNotFoundException | NoSuchMethodException e) { - Log.v(TAG, "Could not find method: " + className + "#" + methodName); - return false; - } catch (Throwable t) { - Log.e( - TAG, - "Unexpected exception when checking if method: " - + className - + "#" - + methodName - + " exists at runtime", - t); - return false; - } - } - - /** - * Invokes a given class's method using reflection. Can be used to call system apis that exist at - * runtime but not in the SDK. - * - * @param instance The instance of the class to invoke the method on. - * @param methodName The name of the method to invoke. - * @param parameterTypes The needed parameter types for the method. - * @param parameters The parameter values to pass into the method. - * @return The result of the invocation or {@code null} if instance or methodName are empty, or if - * the reflection fails. - */ - @Nullable - public static Object invokeMethod( - @Nullable Object instance, - @Nullable String methodName, - Class<?>[] parameterTypes, - Object[] parameters) { - if (instance == null || TextUtils.isEmpty(methodName)) { - return null; - } - - String className = instance.getClass().getName(); - try { - return Class.forName(className) - .getMethod(methodName, parameterTypes) - .invoke(instance, parameters); - } catch (ClassNotFoundException - | NoSuchMethodException - | IllegalArgumentException - | IllegalAccessException - | InvocationTargetException e) { - Log.v(TAG, "Could not invoke method: " + className + "#" + methodName); - return null; - } catch (Throwable t) { - Log.e( - TAG, - "Unexpected exception when invoking method: " - + className - + "#" - + methodName - + " at runtime", - t); - return null; - } - } - - /** - * Determines if this version is compatible with Lollipop-specific APIs. Can also force the - * version to be lower through SdkVersionOverride. - * - * @return {@code true} if call subject is a feature on this device, {@code false} otherwise. - */ - public static boolean isLollipopCompatible() { - return SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.LOLLIPOP) - >= Build.VERSION_CODES.LOLLIPOP; } } diff --git a/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java b/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java new file mode 100644 index 000000000..22ec70cba --- /dev/null +++ b/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2015 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.compat.telephony; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.support.annotation.Nullable; +import android.support.v4.os.BuildCompat; +import android.telecom.PhoneAccountHandle; +import android.telephony.TelephonyManager; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.dialer.telecom.TelecomUtil; +import java.lang.reflect.InvocationTargetException; + +public class TelephonyManagerCompat { + + // TODO(maxwelb): Use public API for these constants when available + public static final String EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE = + "android.telephony.event.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE"; + public static final String EVENT_HANDOVER_TO_WIFI_FAILED = + "android.telephony.event.EVENT_HANDOVER_TO_WIFI_FAILED"; + public static final String EVENT_CALL_REMOTELY_HELD = "android.telecom.event.CALL_REMOTELY_HELD"; + public static final String EVENT_CALL_REMOTELY_UNHELD = + "android.telecom.event.CALL_REMOTELY_UNHELD"; + public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START"; + public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE"; + + public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC = + "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC"; + + public static final String TELEPHONY_MANAGER_CLASS = "android.telephony.TelephonyManager"; + + private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE"; + + // TODO(erfanian): b/63995261 Replace with the platform/telecom constant when available. + /** + * Indicates that the call being placed originated from a known contact. + * + * <p>This signals to the telephony platform that an outgoing call qualifies for assisted dialing. + */ + public static final String ALLOW_ASSISTED_DIAL = "android.telecom.extra.ALLOW_ASSISTED_DIAL"; + + // TODO(erfanian): b/63995261 Replace with the platform/telecom constant when available. + /** + * Indicates that an outgoing call has undergone assisted dialing. + * + * <p>Unlike {@link ALLOW_ASSISTED_DIAL}, the presence of this key further indicates that a call + * has undergone Assisted Dialing -- not just that it qualified for Assisted Dialing. + */ + public static final String IS_ASSISTED_DIALED = "android.telecom.extra.IS_ASSISTED_DIALED"; + + /** + * Returns the number of phones available. Returns 1 for Single standby mode (Single SIM + * functionality) Returns 2 for Dual standby mode.(Dual SIM functionality) + * + * <p>Returns 1 if the method or telephonyManager is not available. + * + * @param telephonyManager The telephony manager instance to use for method calls. + */ + public static int getPhoneCount(@Nullable TelephonyManager telephonyManager) { + if (telephonyManager == null) { + return 1; + } + return telephonyManager.getPhoneCount(); + } + + /** + * Whether the phone supports TTY mode. + * + * @param telephonyManager The telephony manager instance to use for method calls. + * @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(); + } + + /** + * Whether the phone supports hearing aid compatibility. + * + * @param telephonyManager The telephony manager instance to use for method calls. + * @return {@code true} if the device supports hearing aid compatibility, and {@code false} + * otherwise. + */ + public static boolean isHearingAidCompatibilitySupported( + @Nullable TelephonyManager telephonyManager) { + return telephonyManager != null && telephonyManager.isHearingAidCompatibilitySupported(); + } + + /** + * Returns the URI for the per-account voicemail ringtone set in Phone settings. + * + * @param telephonyManager The telephony manager instance to use for method calls. + * @param accountHandle The handle for the {@link android.telecom.PhoneAccount} for which to + * retrieve the voicemail ringtone. + * @return The URI for the ringtone to play when receiving a voicemail from a specific + * PhoneAccount. + */ + @Nullable + public static Uri getVoicemailRingtoneUri( + TelephonyManager telephonyManager, PhoneAccountHandle accountHandle) { + if (VERSION.SDK_INT < VERSION_CODES.N) { + return null; + } + return telephonyManager.getVoicemailRingtoneUri(accountHandle); + } + + /** + * Returns whether vibration is set for voicemail notification in Phone settings. + * + * @param telephonyManager The telephony manager instance to use for method calls. + * @param accountHandle The handle for the {@link android.telecom.PhoneAccount} for which to + * retrieve the voicemail vibration setting. + * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise. + */ + public static boolean isVoicemailVibrationEnabled( + TelephonyManager telephonyManager, PhoneAccountHandle accountHandle) { + return VERSION.SDK_INT < VERSION_CODES.N + || telephonyManager.isVoicemailVibrationEnabled(accountHandle); + } + + /** + * This method uses a new system API to enable or disable visual voicemail. TODO(twyen): restrict + * to N MR1, not needed in future SDK. + */ + public static void setVisualVoicemailEnabled( + TelephonyManager telephonyManager, PhoneAccountHandle handle, boolean enabled) { + if (VERSION.SDK_INT < VERSION_CODES.N_MR1) { + Assert.fail("setVisualVoicemailEnabled called on pre-NMR1"); + } + try { + TelephonyManager.class + .getMethod("setVisualVoicemailEnabled", PhoneAccountHandle.class, boolean.class) + .invoke(telephonyManager, handle, enabled); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + LogUtil.e("TelephonyManagerCompat.setVisualVoicemailEnabled", "failed", e); + } + } + + /** + * This method uses a new system API to check if visual voicemail is enabled TODO(twyen): restrict + * to N MR1, not needed in future SDK. + */ + public static boolean isVisualVoicemailEnabled( + TelephonyManager telephonyManager, PhoneAccountHandle handle) { + if (VERSION.SDK_INT < VERSION_CODES.N_MR1) { + Assert.fail("isVisualVoicemailEnabled called on pre-NMR1"); + } + try { + return (boolean) + TelephonyManager.class + .getMethod("isVisualVoicemailEnabled", PhoneAccountHandle.class) + .invoke(telephonyManager, handle); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + LogUtil.e("TelephonyManagerCompat.setVisualVoicemailEnabled", "failed", e); + } + return false; + } + + /** + * Handles secret codes to launch arbitrary activities. + * + * @param context the context to use + * @param secretCode the secret code without the "*#*#" prefix and "#*#*" suffix + */ + public static void handleSecretCode(Context context, String secretCode) { + // Must use system service on O+ to avoid using broadcasts, which are not allowed on O+. + if (BuildCompat.isAtLeastO()) { + if (!TelecomUtil.isDefaultDialer(context)) { + LogUtil.e( + "TelephonyManagerCompat.handleSecretCode", + "not default dialer, cannot send special code"); + return; + } + context.getSystemService(TelephonyManager.class).sendDialerSpecialCode(secretCode); + } else { + // System service call is not supported pre-O, so must use a broadcast for N-. + Intent intent = + new Intent(SECRET_CODE_ACTION, Uri.parse("android_secret_code://" + secretCode)); + context.sendBroadcast(intent); + } + } +} |