1 /* 2 * Copyright (C) 2020 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.ims.rcs.uce.presence.publish; 18 19 import android.content.Context; 20 import android.net.Uri; 21 import android.telephony.PhoneNumberUtils; 22 import android.telephony.TelephonyManager; 23 import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities; 24 import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag; 25 import android.text.TextUtils; 26 import android.util.Log; 27 28 import com.android.ims.rcs.uce.util.UceUtils; 29 30 import java.util.Arrays; 31 32 /** 33 * The util class of publishing device's capabilities. 34 */ 35 public class PublishUtils { 36 private static final String LOG_TAG = UceUtils.getLogPrefix() + "PublishUtils"; 37 38 private static final String SCHEME_SIP = "sip"; 39 private static final String SCHEME_TEL = "tel"; 40 private static final String DOMAIN_SEPARATOR = "@"; 41 getDeviceContactUri(Context context, int subId, DeviceCapabilityInfo deviceCap)42 public static Uri getDeviceContactUri(Context context, int subId, 43 DeviceCapabilityInfo deviceCap) { 44 // Get the uri from the IMS associated URI which is provided by the IMS service. 45 Uri contactUri = deviceCap.getImsAssociatedUri(); 46 if (contactUri != null) { 47 Log.d(LOG_TAG, "getDeviceContactUri: ims associated uri"); 48 return contactUri; 49 } 50 51 TelephonyManager telephonyManager = getTelephonyManager(context, subId); 52 if (telephonyManager == null) { 53 Log.w(LOG_TAG, "getDeviceContactUri: TelephonyManager is null"); 54 return null; 55 } 56 57 // Get the contact uri from ISIM. 58 contactUri = getContactUriFromIsim(telephonyManager); 59 if (contactUri != null) { 60 Log.d(LOG_TAG, "getDeviceContactUri: impu"); 61 return contactUri; 62 } else { 63 Log.d(LOG_TAG, "getDeviceContactUri: line number"); 64 return getContactUriFromLine1Number(telephonyManager); 65 } 66 } 67 68 /** 69 * Find all instances of sip/sips/tel URIs containing PII and replace them. 70 * <p> 71 * This is used for removing PII in logging. 72 * @param source The source string to remove the phone numbers from. 73 * @return A version of the given string with SIP URIs removed. 74 */ removeNumbersFromUris(String source)75 public static String removeNumbersFromUris(String source) { 76 // Replace only the number portion in the sip/sips/tel URI 77 return source.replaceAll("(?:sips?|tel):(\\+?[\\d\\-]+)", "[removed]"); 78 } 79 getContactUriFromIsim(TelephonyManager telephonyManager)80 private static Uri getContactUriFromIsim(TelephonyManager telephonyManager) { 81 // Get the home network domain and the array of the public user identities 82 String domain = telephonyManager.getIsimDomain(); 83 String[] impus = telephonyManager.getIsimImpu(); 84 85 if (TextUtils.isEmpty(domain) || impus == null) { 86 Log.d(LOG_TAG, "getContactUriFromIsim: domain is null=" + TextUtils.isEmpty(domain)); 87 Log.d(LOG_TAG, "getContactUriFromIsim: impu is null=" + 88 ((impus == null || impus.length == 0) ? "true" : "false")); 89 return null; 90 } 91 92 for (String impu : impus) { 93 if (TextUtils.isEmpty(impu)) continue; 94 Uri impuUri = Uri.parse(impu); 95 String scheme = impuUri.getScheme(); 96 String schemeSpecificPart = impuUri.getSchemeSpecificPart(); 97 if (SCHEME_SIP.equals(scheme) && !TextUtils.isEmpty(schemeSpecificPart) && 98 schemeSpecificPart.endsWith(domain)) { 99 return impuUri; 100 } 101 } 102 Log.d(LOG_TAG, "getContactUriFromIsim: there is no impu matching the domain"); 103 return null; 104 } 105 getContactUriFromLine1Number(TelephonyManager telephonyManager)106 private static Uri getContactUriFromLine1Number(TelephonyManager telephonyManager) { 107 String phoneNumber = formatPhoneNumber(telephonyManager.getLine1Number()); 108 if (TextUtils.isEmpty(phoneNumber)) { 109 Log.w(LOG_TAG, "Cannot get the phone number"); 110 return null; 111 } 112 113 String domain = telephonyManager.getIsimDomain(); 114 if (!TextUtils.isEmpty(domain)) { 115 return Uri.fromParts(SCHEME_SIP, phoneNumber + DOMAIN_SEPARATOR + domain, null); 116 } else { 117 return Uri.fromParts(SCHEME_TEL, phoneNumber, null); 118 } 119 } 120 formatPhoneNumber(final String phoneNumber)121 private static String formatPhoneNumber(final String phoneNumber) { 122 if (TextUtils.isEmpty(phoneNumber)) { 123 Log.w(LOG_TAG, "formatPhoneNumber: phone number is empty"); 124 return null; 125 } 126 String number = PhoneNumberUtils.stripSeparators(phoneNumber); 127 return PhoneNumberUtils.normalizeNumber(number); 128 } 129 getTelephonyManager(Context context, int subId)130 private static TelephonyManager getTelephonyManager(Context context, int subId) { 131 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 132 if (telephonyManager == null) { 133 return null; 134 } else { 135 return telephonyManager.createForSubscriptionId(subId); 136 } 137 } 138 getCapabilityType(Context context, int subId)139 static @RcsImsCapabilityFlag int getCapabilityType(Context context, int subId) { 140 boolean isPresenceSupported = UceUtils.isPresenceSupported(context, subId); 141 boolean isSipOptionsSupported = UceUtils.isSipOptionsSupported(context, subId); 142 if (isPresenceSupported) { 143 return RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE; 144 } else if (isSipOptionsSupported) { 145 return RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE; 146 } else { 147 // Return NONE when neither OPTIONS nor PRESENCE is supported. 148 return RcsImsCapabilities.CAPABILITY_TYPE_NONE; 149 } 150 } 151 } 152