1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.contacts.common.compat; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.net.Uri; 22 import android.os.Build.VERSION; 23 import android.os.Build.VERSION_CODES; 24 import android.support.annotation.Nullable; 25 import android.support.v4.os.BuildCompat; 26 import android.telecom.PhoneAccountHandle; 27 import android.telephony.TelephonyManager; 28 import com.android.dialer.common.Assert; 29 import com.android.dialer.common.LogUtil; 30 import com.android.dialer.telecom.TelecomUtil; 31 import java.lang.reflect.InvocationTargetException; 32 33 public class TelephonyManagerCompat { 34 35 // TODO: Use public API for these constants when available 36 public static final String EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE = 37 "android.telephony.event.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE"; 38 public static final String EVENT_HANDOVER_TO_WIFI_FAILED = 39 "android.telephony.event.EVENT_HANDOVER_TO_WIFI_FAILED"; 40 public static final String EVENT_CALL_REMOTELY_HELD = "android.telecom.event.CALL_REMOTELY_HELD"; 41 public static final String EVENT_CALL_REMOTELY_UNHELD = 42 "android.telecom.event.CALL_REMOTELY_UNHELD"; 43 public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START"; 44 public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE"; 45 46 public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC = 47 "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC"; 48 49 public static final String TELEPHONY_MANAGER_CLASS = "android.telephony.TelephonyManager"; 50 51 private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE"; 52 53 /** 54 * Returns the number of phones available. Returns 1 for Single standby mode (Single SIM 55 * functionality) Returns 2 for Dual standby mode.(Dual SIM functionality) 56 * 57 * <p>Returns 1 if the method or telephonyManager is not available. 58 * 59 * @param telephonyManager The telephony manager instance to use for method calls. 60 */ getPhoneCount(@ullable TelephonyManager telephonyManager)61 public static int getPhoneCount(@Nullable TelephonyManager telephonyManager) { 62 if (telephonyManager == null) { 63 return 1; 64 } 65 return telephonyManager.getPhoneCount(); 66 } 67 68 /** 69 * Whether the phone supports TTY mode. 70 * 71 * @param telephonyManager The telephony manager instance to use for method calls. 72 * @return {@code true} if the device supports TTY mode, and {@code false} otherwise. 73 */ isTtyModeSupported(@ullable TelephonyManager telephonyManager)74 public static boolean isTtyModeSupported(@Nullable TelephonyManager telephonyManager) { 75 return telephonyManager != null && telephonyManager.isTtyModeSupported(); 76 } 77 78 /** 79 * Whether the phone supports hearing aid compatibility. 80 * 81 * @param telephonyManager The telephony manager instance to use for method calls. 82 * @return {@code true} if the device supports hearing aid compatibility, and {@code false} 83 * otherwise. 84 */ isHearingAidCompatibilitySupported( @ullable TelephonyManager telephonyManager)85 public static boolean isHearingAidCompatibilitySupported( 86 @Nullable TelephonyManager telephonyManager) { 87 return telephonyManager != null && telephonyManager.isHearingAidCompatibilitySupported(); 88 } 89 90 /** 91 * Returns the URI for the per-account voicemail ringtone set in Phone settings. 92 * 93 * @param telephonyManager The telephony manager instance to use for method calls. 94 * @param accountHandle The handle for the {@link android.telecom.PhoneAccount} for which to 95 * retrieve the voicemail ringtone. 96 * @return The URI for the ringtone to play when receiving a voicemail from a specific 97 * PhoneAccount. 98 */ 99 @Nullable getVoicemailRingtoneUri( TelephonyManager telephonyManager, PhoneAccountHandle accountHandle)100 public static Uri getVoicemailRingtoneUri( 101 TelephonyManager telephonyManager, PhoneAccountHandle accountHandle) { 102 if (VERSION.SDK_INT < VERSION_CODES.N) { 103 return null; 104 } 105 return telephonyManager.getVoicemailRingtoneUri(accountHandle); 106 } 107 108 /** 109 * Returns whether vibration is set for voicemail notification in Phone settings. 110 * 111 * @param telephonyManager The telephony manager instance to use for method calls. 112 * @param accountHandle The handle for the {@link android.telecom.PhoneAccount} for which to 113 * retrieve the voicemail vibration setting. 114 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise. 115 */ isVoicemailVibrationEnabled( TelephonyManager telephonyManager, PhoneAccountHandle accountHandle)116 public static boolean isVoicemailVibrationEnabled( 117 TelephonyManager telephonyManager, PhoneAccountHandle accountHandle) { 118 return VERSION.SDK_INT < VERSION_CODES.N 119 || telephonyManager.isVoicemailVibrationEnabled(accountHandle); 120 } 121 122 /** 123 * This method uses a new system API to enable or disable visual voicemail. TODO: restrict 124 * to N MR1, not needed in future SDK. 125 */ setVisualVoicemailEnabled( TelephonyManager telephonyManager, PhoneAccountHandle handle, boolean enabled)126 public static void setVisualVoicemailEnabled( 127 TelephonyManager telephonyManager, PhoneAccountHandle handle, boolean enabled) { 128 if (VERSION.SDK_INT < VERSION_CODES.N_MR1) { 129 Assert.fail("setVisualVoicemailEnabled called on pre-NMR1"); 130 } 131 try { 132 TelephonyManager.class 133 .getMethod("setVisualVoicemailEnabled", PhoneAccountHandle.class, boolean.class) 134 .invoke(telephonyManager, handle, enabled); 135 } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 136 LogUtil.e("TelephonyManagerCompat.setVisualVoicemailEnabled", "failed", e); 137 } 138 } 139 140 /** 141 * This method uses a new system API to check if visual voicemail is enabled TODO: restrict 142 * to N MR1, not needed in future SDK. 143 */ isVisualVoicemailEnabled( TelephonyManager telephonyManager, PhoneAccountHandle handle)144 public static boolean isVisualVoicemailEnabled( 145 TelephonyManager telephonyManager, PhoneAccountHandle handle) { 146 if (VERSION.SDK_INT < VERSION_CODES.N_MR1) { 147 Assert.fail("isVisualVoicemailEnabled called on pre-NMR1"); 148 } 149 try { 150 return (boolean) 151 TelephonyManager.class 152 .getMethod("isVisualVoicemailEnabled", PhoneAccountHandle.class) 153 .invoke(telephonyManager, handle); 154 } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 155 LogUtil.e("TelephonyManagerCompat.setVisualVoicemailEnabled", "failed", e); 156 } 157 return false; 158 } 159 160 /** 161 * Handles secret codes to launch arbitrary activities. 162 * 163 * @param context the context to use 164 * @param secretCode the secret code without the "*#*#" prefix and "#*#*" suffix 165 */ handleSecretCode(Context context, String secretCode)166 public static void handleSecretCode(Context context, String secretCode) { 167 // Must use system service on O+ to avoid using broadcasts, which are not allowed on O+. 168 if (BuildCompat.isAtLeastO()) { 169 if (!TelecomUtil.isDefaultDialer(context)) { 170 LogUtil.e( 171 "TelephonyManagerCompat.handleSecretCode", 172 "not default dialer, cannot send special code"); 173 return; 174 } 175 context.getSystemService(TelephonyManager.class).sendDialerSpecialCode(secretCode); 176 } else { 177 // System service call is not supported pre-O, so must use a broadcast for N-. 178 Intent intent = 179 new Intent(SECRET_CODE_ACTION, Uri.parse("android_secret_code://" + secretCode)); 180 context.sendBroadcast(intent); 181 } 182 } 183 } 184