blob: 26e896731375e868095e1298c96402ca6bc57739 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mms.service.metrics;
import static com.android.mms.MmsStatsLog.INCOMING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED;
import static com.android.mms.MmsStatsLog.INCOMING_MMS__RESULT__MMS_RESULT_SUCCESS;
import static com.android.mms.MmsStatsLog.OUTGOING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED;
import static com.android.mms.MmsStatsLog.OUTGOING_MMS__RESULT__MMS_RESULT_SUCCESS;
import android.app.Activity;
import android.content.Context;
import android.os.Binder;
import android.os.SystemClock;
import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import com.android.internal.telephony.SmsApplication;
import com.android.mms.IncomingMms;
import com.android.mms.OutgoingMms;
import java.util.List;
/** Collects mms events for the pulled atom. */
public class MmsStats {
private static final String TAG = MmsStats.class.getSimpleName();
private final Context mContext;
private final PersistMmsAtomsStorage mPersistMmsAtomsStorage;
private final String mCallingPkg;
private final boolean mIsIncomingMms;
private final long mTimestamp;
private int mSubId;
private TelephonyManager mTelephonyManager;
public MmsStats(Context context, PersistMmsAtomsStorage persistMmsAtomsStorage, int subId,
TelephonyManager telephonyManager, String callingPkg, boolean isIncomingMms) {
mContext = context;
mPersistMmsAtomsStorage = persistMmsAtomsStorage;
mSubId = subId;
mTelephonyManager = telephonyManager;
mCallingPkg = callingPkg;
mIsIncomingMms = isIncomingMms;
mTimestamp = SystemClock.elapsedRealtime();
}
/** Updates subId and corresponding telephonyManager. */
public void updateSubId(int subId, TelephonyManager telephonyManager) {
mSubId = subId;
mTelephonyManager = telephonyManager;
}
/** Adds incoming or outgoing mms atom to storage. */
public void addAtomToStorage(int result) {
addAtomToStorage(result, 0, false);
}
/** Adds incoming or outgoing mms atom to storage. */
public void addAtomToStorage(int result, int retryId, boolean handledByCarrierApp) {
long identity = Binder.clearCallingIdentity();
try {
if (mIsIncomingMms) {
onIncomingMms(result, retryId, handledByCarrierApp);
} else {
onOutgoingMms(result, retryId, handledByCarrierApp);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/** Creates a new atom when MMS is received. */
private void onIncomingMms(int result, int retryId, boolean handledByCarrierApp) {
IncomingMms incomingMms = IncomingMms.newBuilder()
.setRat(getDataNetworkType())
.setResult(getIncomingMmsResult(result))
.setRoaming(getDataRoamingType())
.setSimSlotIndex(getSlotIndex())
.setIsMultiSim(getIsMultiSim())
.setIsEsim(getIsEuicc())
.setCarrierId(getSimCarrierId())
.setAvgIntervalMillis(getInterval())
.setMmsCount(1)
.setRetryId(retryId)
.setHandledByCarrierApp(handledByCarrierApp)
.build();
mPersistMmsAtomsStorage.addIncomingMms(incomingMms);
}
/** Creates a new atom when MMS is sent. */
private void onOutgoingMms(int result, int retryId, boolean handledByCarrierApp) {
OutgoingMms outgoingMms = OutgoingMms.newBuilder()
.setRat(getDataNetworkType())
.setResult(getOutgoingMmsResult(result))
.setRoaming(getDataRoamingType())
.setSimSlotIndex(getSlotIndex())
.setIsMultiSim(getIsMultiSim())
.setIsEsim(getIsEuicc())
.setCarrierId(getSimCarrierId())
.setAvgIntervalMillis(getInterval())
.setMmsCount(1)
.setIsFromDefaultApp(isDefaultMmsApp())
.setRetryId(retryId)
.setHandledByCarrierApp(handledByCarrierApp)
.build();
mPersistMmsAtomsStorage.addOutgoingMms(outgoingMms);
}
/** Returns data network type of current subscription. */
private int getDataNetworkType() {
return mTelephonyManager.getDataNetworkType();
}
/** Returns incoming mms result. */
private int getIncomingMmsResult(int result) {
switch (result) {
case SmsManager.MMS_ERROR_UNSPECIFIED:
// SmsManager.MMS_ERROR_UNSPECIFIED(1) -> MMS_RESULT_ERROR_UNSPECIFIED(0)
return INCOMING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED;
case Activity.RESULT_OK:
// Activity.RESULT_OK -> MMS_RESULT_SUCCESS(1)
return INCOMING_MMS__RESULT__MMS_RESULT_SUCCESS;
default:
// Int value of other SmsManager.MMS_ERROR matches MMS_RESULT_ERROR
return result;
}
}
/** Returns outgoing mms result. */
private int getOutgoingMmsResult(int result) {
switch (result) {
case SmsManager.MMS_ERROR_UNSPECIFIED:
// SmsManager.MMS_ERROR_UNSPECIFIED(1) -> MMS_RESULT_ERROR_UNSPECIFIED(0)
return OUTGOING_MMS__RESULT__MMS_RESULT_ERROR_UNSPECIFIED;
case Activity.RESULT_OK:
// Activity.RESULT_OK -> MMS_RESULT_SUCCESS(1)
return OUTGOING_MMS__RESULT__MMS_RESULT_SUCCESS;
default:
// Int value of other SmsManager.MMS_ERROR matches MMS_RESULT_ERROR
return result;
}
}
/** Returns data network roaming type of current subscription. */
private int getDataRoamingType() {
ServiceState serviceState = mTelephonyManager.getServiceState();
return (serviceState != null) ? serviceState.getDataRoamingType() :
ServiceState.ROAMING_TYPE_NOT_ROAMING;
}
/** Returns slot index associated with the subscription. */
private int getSlotIndex() {
return SubscriptionManager.getSlotIndex(mSubId);
}
/** Returns whether the device has multiple active SIM profiles. */
private boolean getIsMultiSim() {
SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
if(subManager == null) {
return false;
}
List<SubscriptionInfo> activeSubscriptionInfo = subManager.getActiveSubscriptionInfoList();
return (activeSubscriptionInfo.size() > 1);
}
/** Returns if current subscription is embedded subscription. */
private boolean getIsEuicc() {
List<UiccCardInfo> uiccCardInfoList = mTelephonyManager.getUiccCardsInfo();
for (UiccCardInfo card : uiccCardInfoList) {
if (card.getPhysicalSlotIndex() == getSlotIndex()) {
return card.isEuicc();
}
}
return false;
}
/** Returns carrier id of the current subscription used by MMS. */
private int getSimCarrierId() {
return mTelephonyManager.getSimCarrierId();
}
/** Returns if the MMS was originated from the default MMS application. */
private boolean isDefaultMmsApp() {
return SmsApplication.isDefaultMmsApplication(mContext, mCallingPkg);
}
/**
* Returns the interval in milliseconds between sending/receiving MMS message and current time.
* Calculates the time taken to send message to the network
* or download message from the network.
*/
private long getInterval() {
return (SystemClock.elapsedRealtime() - mTimestamp);
}
}