1 /* 2 * Copyright (C) 2021 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.imsserviceentitlement.utils; 18 19 import android.content.Context; 20 import android.net.ConnectivityManager; 21 import android.net.NetworkInfo; 22 import android.os.Build; 23 import android.os.PersistableBundle; 24 import android.telephony.CarrierConfigManager; 25 import android.telephony.SubscriptionInfo; 26 import android.telephony.SubscriptionManager; 27 import android.telephony.TelephonyManager; 28 import android.util.Log; 29 30 import com.google.common.collect.ImmutableSet; 31 32 import java.util.List; 33 34 /** This class implements Telephony helper methods. */ 35 public class TelephonyUtils { 36 public static final String TAG = "IMSSE-TelephonyUtils"; 37 38 private final ConnectivityManager mConnectivityManager; 39 private final TelephonyManager mTelephonyManager; 40 TelephonyUtils(Context context)41 public TelephonyUtils(Context context) { 42 this(context, SubscriptionManager.INVALID_SUBSCRIPTION_ID); 43 } 44 TelephonyUtils(Context context, int subId)45 public TelephonyUtils(Context context, int subId) { 46 if (SubscriptionManager.isValidSubscriptionId(subId)) { 47 mTelephonyManager = 48 context.getSystemService(TelephonyManager.class).createForSubscriptionId(subId); 49 } else { 50 mTelephonyManager = context.getSystemService(TelephonyManager.class); 51 } 52 mConnectivityManager = context.getSystemService(ConnectivityManager.class); 53 } 54 55 /** Returns device timestamp in milliseconds. */ getTimeStamp()56 public long getTimeStamp() { 57 return System.currentTimeMillis(); 58 } 59 60 /** Returns device uptime in milliseconds. */ getUptimeMillis()61 public long getUptimeMillis() { 62 return android.os.SystemClock.uptimeMillis(); 63 } 64 65 /** Returns device model name. */ getDeviceName()66 public String getDeviceName() { 67 return Build.MODEL; 68 } 69 70 /** Returns device OS version. */ getDeviceOsVersion()71 public String getDeviceOsVersion() { 72 return Build.VERSION.RELEASE; 73 } 74 75 /** Returns {@code true} if network is connected (cellular or WiFi). */ isNetworkConnected()76 public boolean isNetworkConnected() { 77 NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo(); 78 return activeNetwork != null && activeNetwork.isConnected(); 79 } 80 81 /** 82 * Returns the response of EAP-AKA authetication {@code data} or {@code null} on failure. 83 * 84 * <p>Requires permission: READ_PRIVILEGED_PHONE_STATE 85 */ getEapAkaAuthentication(String data)86 public String getEapAkaAuthentication(String data) { 87 return mTelephonyManager.getIccAuthentication( 88 TelephonyManager.APPTYPE_USIM, TelephonyManager.AUTHTYPE_EAP_AKA, data); 89 } 90 91 /** Returns carrier ID. */ getCarrierId()92 public int getCarrierId() { 93 return mTelephonyManager.getSimCarrierId(); 94 } 95 96 /** Returns fine-grained carrier ID. */ getSpecificCarrierId()97 public int getSpecificCarrierId() { 98 return mTelephonyManager.getSimSpecificCarrierId(); 99 } 100 101 /** 102 * Returns {@code true} if the {@code subId} still point to a actived SIM; {@code false} 103 * otherwise. 104 */ isActivedSubId(Context context, int subId)105 public static boolean isActivedSubId(Context context, int subId) { 106 SubscriptionManager subscriptionManager = 107 (SubscriptionManager) context.getSystemService( 108 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 109 SubscriptionInfo subInfo = subscriptionManager.getActiveSubscriptionInfo(subId); 110 return subInfo != null; 111 } 112 113 /** 114 * Returns the slot index for the actived {@code subId}; {@link 115 * SubscriptionManager#INVALID_SIM_SLOT_INDEX} otherwise. 116 */ getSlotId(Context context, int subId)117 public static int getSlotId(Context context, int subId) { 118 SubscriptionManager subscriptionManager = 119 (SubscriptionManager) context.getSystemService( 120 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 121 SubscriptionInfo subInfo = subscriptionManager.getActiveSubscriptionInfo(subId); 122 if (subInfo != null) { 123 return subInfo.getSimSlotIndex(); 124 } 125 Log.d(TAG, "Can't find actived subscription for " + subId); 126 return SubscriptionManager.INVALID_SIM_SLOT_INDEX; 127 } 128 129 /** Returns carrier config for the {@code subId}. */ getConfigForSubId(Context context, int subId)130 private static PersistableBundle getConfigForSubId(Context context, int subId) { 131 CarrierConfigManager carrierConfigManager = 132 context.getSystemService(CarrierConfigManager.class); 133 PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId); 134 if (carrierConfig == null) { 135 Log.d(TAG, "getDefaultConfig"); 136 carrierConfig = CarrierConfigManager.getDefaultConfig(); 137 } 138 return carrierConfig; 139 } 140 141 /** 142 * Returns FCM sender id for the {@code subId} or a default empty string if it is not available. 143 */ getFcmSenderId(Context context, int subId)144 public static String getFcmSenderId(Context context, int subId) { 145 return getConfigForSubId(context, subId).getString( 146 CarrierConfigManager.ImsServiceEntitlement.KEY_FCM_SENDER_ID_STRING, 147 "" 148 ); 149 } 150 151 /** 152 * Returns entitlement server url for the {@code subId} or 153 * a default empty string if it is not available. 154 */ getEntitlementServerUrl(Context context, int subId)155 public static String getEntitlementServerUrl(Context context, int subId) { 156 return getConfigForSubId(context, subId).getString( 157 CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING, 158 "" 159 ); 160 } 161 162 /** 163 * Returns true if app needs to do IMS (VoLTE/VoWiFi/SMSoIP) provisioning in the background 164 * or false if it doesn't need to do. 165 */ isImsProvisioningRequired(Context context, int subId)166 public static boolean isImsProvisioningRequired(Context context, int subId) { 167 return getConfigForSubId(context, subId).getBoolean( 168 CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL, 169 false 170 ); 171 } 172 173 /** Returns SubIds which support FCM. */ getSubIdsWithFcmSupported(Context context)174 public static ImmutableSet<Integer> getSubIdsWithFcmSupported(Context context) { 175 SubscriptionManager subscriptionManager = 176 context.getSystemService(SubscriptionManager.class); 177 List<SubscriptionInfo> infos = subscriptionManager.getActiveSubscriptionInfoList(); 178 if (infos == null) { 179 return ImmutableSet.of(); 180 } 181 182 ImmutableSet.Builder<Integer> builder = ImmutableSet.builder(); 183 for (SubscriptionInfo info : infos) { 184 int subId = info.getSubscriptionId(); 185 if (isFcmPushNotificationSupported(context, subId)) { 186 builder.add(subId); 187 } 188 } 189 return builder.build(); 190 } 191 isFcmPushNotificationSupported(Context context, int subId)192 private static boolean isFcmPushNotificationSupported(Context context, int subId) { 193 return !TelephonyUtils.getFcmSenderId(context, subId).isEmpty(); 194 } 195 } 196