Home | History | Annotate | Download | only in telephony
      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.dialer.compat.telephony;
     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 /** Hidden APIs in {@link android.telephony.TelephonyManager}. */
     34 public class TelephonyManagerCompat {
     35 
     36   // TODO(maxwelb): Use public API for these constants when available
     37   public static final String EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE =
     38       "android.telephony.event.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE";
     39   public static final String EVENT_HANDOVER_TO_WIFI_FAILED =
     40       "android.telephony.event.EVENT_HANDOVER_TO_WIFI_FAILED";
     41   public static final String EVENT_CALL_REMOTELY_HELD = "android.telecom.event.CALL_REMOTELY_HELD";
     42   public static final String EVENT_CALL_REMOTELY_UNHELD =
     43       "android.telecom.event.CALL_REMOTELY_UNHELD";
     44   public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START";
     45   public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE";
     46 
     47   public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC =
     48       "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC";
     49   public static final String EVENT_CALL_FORWARDED = "android.telephony.event.EVENT_CALL_FORWARDED";
     50 
     51   public static final String TELEPHONY_MANAGER_CLASS = "android.telephony.TelephonyManager";
     52 
     53   private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE";
     54 
     55   // TODO(erfanian): a bug Replace with the platform/telecom constant when available.
     56   /**
     57    * Indicates that the call being placed originated from a known contact.
     58    *
     59    * <p>This signals to the telephony platform that an outgoing call qualifies for assisted dialing.
     60    */
     61   public static final String USE_ASSISTED_DIALING = "android.telecom.extra.USE_ASSISTED_DIALING";
     62 
     63   // TODO(erfanian): a bug Replace with the platform/telecom API when available.
     64   /** Additional information relating to the assisted dialing transformation. */
     65   public static final String ASSISTED_DIALING_EXTRAS =
     66       "android.telecom.extra.ASSISTED_DIALING_EXTRAS";
     67 
     68   /** Indicates the Connection/Call used assisted dialing. */
     69   public static final int PROPERTY_ASSISTED_DIALING_USED = 1 << 9;
     70 
     71   public static final String EXTRA_IS_REFRESH =
     72       BuildCompat.isAtLeastOMR1() ? "android.telephony.extra.IS_REFRESH" : "is_refresh";
     73 
     74   /**
     75    * Indicates the call underwent Assisted Dialing; typically set as a feature available from the
     76    * CallLog.
     77    */
     78   public static final Integer FEATURES_ASSISTED_DIALING = 1 << 4;
     79 
     80   /**
     81    * Returns the number of phones available. Returns 1 for Single standby mode (Single SIM
     82    * functionality) Returns 2 for Dual standby mode.(Dual SIM functionality)
     83    *
     84    * <p>Returns 1 if the method or telephonyManager is not available.
     85    *
     86    * @param telephonyManager The telephony manager instance to use for method calls.
     87    */
     88   public static int getPhoneCount(@Nullable TelephonyManager telephonyManager) {
     89     if (telephonyManager == null) {
     90       return 1;
     91     }
     92     return telephonyManager.getPhoneCount();
     93   }
     94 
     95   /**
     96    * Whether the phone supports TTY mode.
     97    *
     98    * @param telephonyManager The telephony manager instance to use for method calls.
     99    * @return {@code true} if the device supports TTY mode, and {@code false} otherwise.
    100    */
    101   public static boolean isTtyModeSupported(@Nullable TelephonyManager telephonyManager) {
    102     return telephonyManager != null && telephonyManager.isTtyModeSupported();
    103   }
    104 
    105   /**
    106    * Whether the phone supports hearing aid compatibility.
    107    *
    108    * @param telephonyManager The telephony manager instance to use for method calls.
    109    * @return {@code true} if the device supports hearing aid compatibility, and {@code false}
    110    *     otherwise.
    111    */
    112   public static boolean isHearingAidCompatibilitySupported(
    113       @Nullable TelephonyManager telephonyManager) {
    114     return telephonyManager != null && telephonyManager.isHearingAidCompatibilitySupported();
    115   }
    116 
    117   /**
    118    * Returns the URI for the per-account voicemail ringtone set in Phone settings.
    119    *
    120    * @param telephonyManager The telephony manager instance to use for method calls.
    121    * @param accountHandle The handle for the {@link android.telecom.PhoneAccount} for which to
    122    *     retrieve the voicemail ringtone.
    123    * @return The URI for the ringtone to play when receiving a voicemail from a specific
    124    *     PhoneAccount.
    125    */
    126   @Nullable
    127   public static Uri getVoicemailRingtoneUri(
    128       TelephonyManager telephonyManager, PhoneAccountHandle accountHandle) {
    129     if (VERSION.SDK_INT < VERSION_CODES.N) {
    130       return null;
    131     }
    132     return telephonyManager.getVoicemailRingtoneUri(accountHandle);
    133   }
    134 
    135   /**
    136    * Returns whether vibration is set for voicemail notification in Phone settings.
    137    *
    138    * @param telephonyManager The telephony manager instance to use for method calls.
    139    * @param accountHandle The handle for the {@link android.telecom.PhoneAccount} for which to
    140    *     retrieve the voicemail vibration setting.
    141    * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
    142    */
    143   public static boolean isVoicemailVibrationEnabled(
    144       TelephonyManager telephonyManager, PhoneAccountHandle accountHandle) {
    145     return VERSION.SDK_INT < VERSION_CODES.N
    146         || telephonyManager.isVoicemailVibrationEnabled(accountHandle);
    147   }
    148 
    149   /**
    150    * This method uses a new system API to enable or disable visual voicemail. TODO(twyen): restrict
    151    * to N MR1, not needed in future SDK.
    152    */
    153   public static void setVisualVoicemailEnabled(
    154       TelephonyManager telephonyManager, PhoneAccountHandle handle, boolean enabled) {
    155     if (VERSION.SDK_INT < VERSION_CODES.N_MR1) {
    156       Assert.fail("setVisualVoicemailEnabled called on pre-NMR1");
    157     }
    158     try {
    159       TelephonyManager.class
    160           .getMethod("setVisualVoicemailEnabled", PhoneAccountHandle.class, boolean.class)
    161           .invoke(telephonyManager, handle, enabled);
    162     } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    163       LogUtil.e("TelephonyManagerCompat.setVisualVoicemailEnabled", "failed", e);
    164     }
    165   }
    166 
    167   /**
    168    * This method uses a new system API to check if visual voicemail is enabled TODO(twyen): restrict
    169    * to N MR1, not needed in future SDK.
    170    */
    171   public static boolean isVisualVoicemailEnabled(
    172       TelephonyManager telephonyManager, PhoneAccountHandle handle) {
    173     if (VERSION.SDK_INT < VERSION_CODES.N_MR1) {
    174       Assert.fail("isVisualVoicemailEnabled called on pre-NMR1");
    175     }
    176     try {
    177       return (boolean)
    178           TelephonyManager.class
    179               .getMethod("isVisualVoicemailEnabled", PhoneAccountHandle.class)
    180               .invoke(telephonyManager, handle);
    181     } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    182       LogUtil.e("TelephonyManagerCompat.setVisualVoicemailEnabled", "failed", e);
    183     }
    184     return false;
    185   }
    186 
    187   /**
    188    * Handles secret codes to launch arbitrary activities.
    189    *
    190    * @param context the context to use
    191    * @param secretCode the secret code without the "*#*#" prefix and "#*#*" suffix
    192    */
    193   public static void handleSecretCode(Context context, String secretCode) {
    194     // Must use system service on O+ to avoid using broadcasts, which are not allowed on O+.
    195     if (BuildCompat.isAtLeastO()) {
    196       if (!TelecomUtil.isDefaultDialer(context)) {
    197         LogUtil.e(
    198             "TelephonyManagerCompat.handleSecretCode",
    199             "not default dialer, cannot send special code");
    200         return;
    201       }
    202       context.getSystemService(TelephonyManager.class).sendDialerSpecialCode(secretCode);
    203     } else {
    204       // System service call is not supported pre-O, so must use a broadcast for N-.
    205       Intent intent =
    206           new Intent(SECRET_CODE_ACTION, Uri.parse("android_secret_code://" + secretCode));
    207       context.sendBroadcast(intent);
    208     }
    209   }
    210 
    211   /**
    212    * Returns network country iso for given {@code PhoneAccountHandle} for O+ devices and country iso
    213    * for default sim for pre-O devices.
    214    */
    215   public static String getNetworkCountryIsoForPhoneAccountHandle(
    216       Context context, @Nullable PhoneAccountHandle phoneAccountHandle) {
    217     return getTelephonyManagerForPhoneAccountHandle(context, phoneAccountHandle)
    218         .getNetworkCountryIso();
    219   }
    220 
    221   /**
    222    * Returns TelephonyManager for given {@code PhoneAccountHandle} for O+ devices and default {@code
    223    * TelephonyManager} for pre-O devices.
    224    */
    225   public static TelephonyManager getTelephonyManagerForPhoneAccountHandle(
    226       Context context, @Nullable PhoneAccountHandle phoneAccountHandle) {
    227     TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
    228     if (phoneAccountHandle == null) {
    229       return telephonyManager;
    230     }
    231     if (VERSION.SDK_INT >= VERSION_CODES.O) {
    232       TelephonyManager telephonyManagerForPhoneAccount =
    233           telephonyManager.createForPhoneAccountHandle(phoneAccountHandle);
    234       if (telephonyManagerForPhoneAccount != null) {
    235         return telephonyManagerForPhoneAccount;
    236       }
    237     }
    238     return telephonyManager;
    239   }
    240 }
    241