1 /* 2 * Copyright (C) 2022 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.mms.service.metrics; 18 19 import static com.android.mms.MmsStatsLog.INCOMING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED; 20 import static com.android.mms.MmsStatsLog.INCOMING_MMS__RESULT__MMS_RESULT_SUCCESS; 21 import static com.android.mms.MmsStatsLog.OUTGOING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED; 22 import static com.android.mms.MmsStatsLog.OUTGOING_MMS__RESULT__MMS_RESULT_SUCCESS; 23 24 import android.app.Activity; 25 import android.content.Context; 26 import android.os.Binder; 27 import android.os.SystemClock; 28 import android.telephony.ServiceState; 29 import android.telephony.SmsManager; 30 import android.telephony.SubscriptionInfo; 31 import android.telephony.SubscriptionManager; 32 import android.telephony.TelephonyManager; 33 import android.telephony.UiccCardInfo; 34 35 import com.android.internal.telephony.SmsApplication; 36 import com.android.mms.IncomingMms; 37 import com.android.mms.OutgoingMms; 38 39 import java.util.List; 40 41 /** Collects mms events for the pulled atom. */ 42 public class MmsStats { 43 private static final String TAG = MmsStats.class.getSimpleName(); 44 45 private final Context mContext; 46 private final PersistMmsAtomsStorage mPersistMmsAtomsStorage; 47 private final String mCallingPkg; 48 private final boolean mIsIncomingMms; 49 private final long mTimestamp; 50 private int mSubId; 51 private TelephonyManager mTelephonyManager; 52 MmsStats(Context context, PersistMmsAtomsStorage persistMmsAtomsStorage, int subId, TelephonyManager telephonyManager, String callingPkg, boolean isIncomingMms)53 public MmsStats(Context context, PersistMmsAtomsStorage persistMmsAtomsStorage, int subId, 54 TelephonyManager telephonyManager, String callingPkg, boolean isIncomingMms) { 55 mContext = context; 56 mPersistMmsAtomsStorage = persistMmsAtomsStorage; 57 mSubId = subId; 58 mTelephonyManager = telephonyManager; 59 mCallingPkg = callingPkg; 60 mIsIncomingMms = isIncomingMms; 61 mTimestamp = SystemClock.elapsedRealtime(); 62 } 63 64 /** Updates subId and corresponding telephonyManager. */ updateSubId(int subId, TelephonyManager telephonyManager)65 public void updateSubId(int subId, TelephonyManager telephonyManager) { 66 mSubId = subId; 67 mTelephonyManager = telephonyManager; 68 } 69 70 /** Adds incoming or outgoing mms atom to storage. */ addAtomToStorage(int result)71 public void addAtomToStorage(int result) { 72 addAtomToStorage(result, 0, false); 73 } 74 75 /** Adds incoming or outgoing mms atom to storage. */ addAtomToStorage(int result, int retryId, boolean handledByCarrierApp)76 public void addAtomToStorage(int result, int retryId, boolean handledByCarrierApp) { 77 long identity = Binder.clearCallingIdentity(); 78 try { 79 if (mIsIncomingMms) { 80 onIncomingMms(result, retryId, handledByCarrierApp); 81 } else { 82 onOutgoingMms(result, retryId, handledByCarrierApp); 83 } 84 } finally { 85 Binder.restoreCallingIdentity(identity); 86 } 87 } 88 89 /** Creates a new atom when MMS is received. */ onIncomingMms(int result, int retryId, boolean handledByCarrierApp)90 private void onIncomingMms(int result, int retryId, boolean handledByCarrierApp) { 91 IncomingMms incomingMms = IncomingMms.newBuilder() 92 .setRat(getDataNetworkType()) 93 .setResult(getIncomingMmsResult(result)) 94 .setRoaming(getDataRoamingType()) 95 .setSimSlotIndex(getSlotIndex()) 96 .setIsMultiSim(getIsMultiSim()) 97 .setIsEsim(getIsEuicc()) 98 .setCarrierId(getSimCarrierId()) 99 .setAvgIntervalMillis(getInterval()) 100 .setMmsCount(1) 101 .setRetryId(retryId) 102 .setHandledByCarrierApp(handledByCarrierApp) 103 .build(); 104 mPersistMmsAtomsStorage.addIncomingMms(incomingMms); 105 } 106 107 /** Creates a new atom when MMS is sent. */ onOutgoingMms(int result, int retryId, boolean handledByCarrierApp)108 private void onOutgoingMms(int result, int retryId, boolean handledByCarrierApp) { 109 OutgoingMms outgoingMms = OutgoingMms.newBuilder() 110 .setRat(getDataNetworkType()) 111 .setResult(getOutgoingMmsResult(result)) 112 .setRoaming(getDataRoamingType()) 113 .setSimSlotIndex(getSlotIndex()) 114 .setIsMultiSim(getIsMultiSim()) 115 .setIsEsim(getIsEuicc()) 116 .setCarrierId(getSimCarrierId()) 117 .setAvgIntervalMillis(getInterval()) 118 .setMmsCount(1) 119 .setIsFromDefaultApp(isDefaultMmsApp()) 120 .setRetryId(retryId) 121 .setHandledByCarrierApp(handledByCarrierApp) 122 .build(); 123 mPersistMmsAtomsStorage.addOutgoingMms(outgoingMms); 124 } 125 126 /** Returns data network type of current subscription. */ getDataNetworkType()127 private int getDataNetworkType() { 128 return mTelephonyManager.getDataNetworkType(); 129 } 130 131 /** Returns incoming mms result. */ getIncomingMmsResult(int result)132 private int getIncomingMmsResult(int result) { 133 switch (result) { 134 case SmsManager.MMS_ERROR_UNSPECIFIED: 135 // SmsManager.MMS_ERROR_UNSPECIFIED(1) -> MMS_RESULT_ERROR_UNSPECIFIED(0) 136 return INCOMING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED; 137 case Activity.RESULT_OK: 138 // Activity.RESULT_OK -> MMS_RESULT_SUCCESS(1) 139 return INCOMING_MMS__RESULT__MMS_RESULT_SUCCESS; 140 default: 141 // Int value of other SmsManager.MMS_ERROR matches MMS_RESULT_ERROR 142 return result; 143 } 144 } 145 146 /** Returns outgoing mms result. */ getOutgoingMmsResult(int result)147 private int getOutgoingMmsResult(int result) { 148 switch (result) { 149 case SmsManager.MMS_ERROR_UNSPECIFIED: 150 // SmsManager.MMS_ERROR_UNSPECIFIED(1) -> MMS_RESULT_ERROR_UNSPECIFIED(0) 151 return OUTGOING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED; 152 case Activity.RESULT_OK: 153 // Activity.RESULT_OK -> MMS_RESULT_SUCCESS(1) 154 return OUTGOING_MMS__RESULT__MMS_RESULT_SUCCESS; 155 default: 156 // Int value of other SmsManager.MMS_ERROR matches MMS_RESULT_ERROR 157 return result; 158 } 159 } 160 161 /** Returns data network roaming type of current subscription. */ getDataRoamingType()162 private int getDataRoamingType() { 163 ServiceState serviceState = mTelephonyManager.getServiceState(); 164 return (serviceState != null) ? serviceState.getDataRoamingType() : 165 ServiceState.ROAMING_TYPE_NOT_ROAMING; 166 } 167 168 /** Returns slot index associated with the subscription. */ getSlotIndex()169 private int getSlotIndex() { 170 return SubscriptionManager.getSlotIndex(mSubId); 171 } 172 173 /** Returns whether the device has multiple active SIM profiles. */ getIsMultiSim()174 private boolean getIsMultiSim() { 175 SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class); 176 if(subManager == null) { 177 return false; 178 } 179 180 List<SubscriptionInfo> activeSubscriptionInfo = subManager.getActiveSubscriptionInfoList(); 181 return (activeSubscriptionInfo.size() > 1); 182 } 183 184 /** Returns if current subscription is embedded subscription. */ getIsEuicc()185 private boolean getIsEuicc() { 186 List<UiccCardInfo> uiccCardInfoList = mTelephonyManager.getUiccCardsInfo(); 187 for (UiccCardInfo card : uiccCardInfoList) { 188 if (card.getPhysicalSlotIndex() == getSlotIndex()) { 189 return card.isEuicc(); 190 } 191 } 192 return false; 193 } 194 195 /** Returns carrier id of the current subscription used by MMS. */ getSimCarrierId()196 private int getSimCarrierId() { 197 return mTelephonyManager.getSimCarrierId(); 198 } 199 200 /** Returns if the MMS was originated from the default MMS application. */ isDefaultMmsApp()201 private boolean isDefaultMmsApp() { 202 return SmsApplication.isDefaultMmsApplication(mContext, mCallingPkg); 203 } 204 205 /** 206 * Returns the interval in milliseconds between sending/receiving MMS message and current time. 207 * Calculates the time taken to send message to the network 208 * or download message from the network. 209 */ getInterval()210 private long getInterval() { 211 return (SystemClock.elapsedRealtime() - mTimestamp); 212 } 213 }