Loading src/java/com/android/internal/telephony/metrics/MetricsCollector.java +88 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.internal.telephony.metrics; import static android.telephony.PhoneNumberUtils.areSamePhoneNumber; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_IMS; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_UICC; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS; Loading @@ -33,6 +37,7 @@ import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_ import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_TERMINATION; import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS; import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT; import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS; import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS; Loading @@ -50,11 +55,14 @@ import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSIO import android.annotation.Nullable; import android.app.StatsManager; import android.content.Context; import android.telephony.SubscriptionInfo; import android.text.TextUtils; import android.util.StatsEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.SubscriptionController; import com.android.internal.telephony.TelephonyStatsLog; import com.android.internal.telephony.imsphone.ImsPhone; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; Loading Loading @@ -86,6 +94,7 @@ import com.android.telephony.Rlog; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; Loading Loading @@ -127,14 +136,24 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { .setCoolDownMillis(MIN_COOLDOWN_MILLIS) .build(); private PersistAtomsStorage mStorage; private final PersistAtomsStorage mStorage; private final TelephonyStatsLogHelper mTelephonyStatsLog; private final StatsManager mStatsManager; private final AirplaneModeStats mAirplaneModeStats; private final Set<DataCallSessionStats> mOngoingDataCallStats = ConcurrentHashMap.newKeySet(); private static final Random sRandom = new Random(); public MetricsCollector(Context context) { mStorage = new PersistAtomsStorage(context); this(context, new PersistAtomsStorage(context), new TelephonyStatsLogHelper()); } /** Allows dependency injection. Used during unit tests. */ @VisibleForTesting public MetricsCollector(Context context, PersistAtomsStorage storage, TelephonyStatsLogHelper telephonyStatsLog) { mStorage = storage; mTelephonyStatsLog = telephonyStatsLog; mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER); if (mStatsManager != null) { registerAtom(CELLULAR_DATA_SERVICE_SWITCH, POLICY_PULL_DAILY); Loading Loading @@ -163,6 +182,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { registerAtom(UCE_EVENT_STATS, POLICY_PULL_DAILY); registerAtom(PRESENCE_NOTIFY_EVENT, POLICY_PULL_DAILY); registerAtom(GBA_EVENT, POLICY_PULL_DAILY); registerAtom(PER_SIM_STATUS, null); Rlog.d(TAG, "registered"); } else { Loading @@ -172,12 +192,6 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { mAirplaneModeStats = new AirplaneModeStats(context); } /** Replaces the {@link PersistAtomsStorage} backing the puller. Used during unit tests. */ @VisibleForTesting public void setPersistAtomsStorage(PersistAtomsStorage storage) { mStorage = storage; } /** * {@inheritDoc} * Loading Loading @@ -240,6 +254,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { return pullPresenceNotifyEvent(data); case GBA_EVENT: return pullGbaEvent(data); case PER_SIM_STATUS: return pullPerSimStatus(data); default: Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag)); return StatsManager.PULL_SKIP; Loading Loading @@ -639,6 +655,70 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { } } private int pullPerSimStatus(List<StatsEvent> data) { SubscriptionController subscriptionController = SubscriptionController.getInstance(); if (subscriptionController == null) { return StatsManager.PULL_SKIP; } for (Phone phone : getPhonesIfAny()) { int subId = phone.getSubId(); String countryIso = Optional.ofNullable(subscriptionController.getSubscriptionInfo(subId)) .map(SubscriptionInfo::getCountryIso) .orElse(""); // numbersFromAllSources[]- Phone numbers from each sources // numberIds[] - Array of integer ids representing phone numbers. // If number is empty then id will be 0. Two same numbers will have same id, and // different numbers will have different ids. // For example, [1, 0, 1] means that uicc and ims numbers are the same while carrier // number is empty and [1, 2, 3] means all numbers are different. // index 0 - PHONE_NUMBER_SOURCE_UICC // index 1 - PHONE_NUMBER_SOURCE_CARRIER // index 2 - PHONE_NUMBER_SOURCE_IMS String[] numbersFromAllSources = new String[] { subscriptionController.getPhoneNumber( subId, PHONE_NUMBER_SOURCE_UICC, null, null), // 0 subscriptionController.getPhoneNumber( subId, PHONE_NUMBER_SOURCE_CARRIER, null, null), // 1 subscriptionController.getPhoneNumber( subId, PHONE_NUMBER_SOURCE_IMS, null, null), // 2 }; int[] numberIds = new int[numbersFromAllSources.length]; // default value 0 for (int i = 0, idForNextUniqueNumber = 1; i < numberIds.length; i++) { if (TextUtils.isEmpty(numbersFromAllSources[i])) { // keep id 0 if number not available continue; } // the number is available: // try to find the same number from other sources and reuse the id for (int j = 0; j < i; j++) { if (!TextUtils.isEmpty(numbersFromAllSources[j]) && areSamePhoneNumber( numbersFromAllSources[i], numbersFromAllSources[j], countryIso)) { numberIds[i] = numberIds[j]; } } // didn't find same number (otherwise should not be id 0), assign a new id if (numberIds[i] == 0) { numberIds[i] = idForNextUniqueNumber; idForNextUniqueNumber++; } } StatsEvent statsEvent = mTelephonyStatsLog.buildStatsEvent( PER_SIM_STATUS, phone.getPhoneId(), // simSlotIndex phone.getCarrierId(), // carrierId numberIds[0], // phoneNumberSourceUicc numberIds[1], // phoneNumberSourceCarrier numberIds[2]); // phoneNumberSourceIms data.add(statsEvent); } return StatsManager.PULL_SUCCESS; } /** Registers a pulled atom ID {@code atomId} with optional {@code policy} for pulling. */ private void registerAtom(int atomId, @Nullable StatsManager.PullAtomMetadata policy) { mStatsManager.setPullAtomCallback(atomId, policy, ConcurrentUtils.DIRECT_EXECUTOR, this); Loading src/java/com/android/internal/telephony/metrics/TelephonyStatsLogHelper.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * 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.internal.telephony.metrics; import android.util.StatsEvent; import com.android.internal.telephony.TelephonyStatsLog; /** * Wrapper of generated TelephonyStatsLog class. Can be mocked during unit test. * * <p>Methods here have the same name/arguments/return as their counterparts in TelephonyStatsLog * and simply call their counterparts. Do not put any involved logic here as they cannot be * covered by unit test. */ public class TelephonyStatsLogHelper { /** Wraps TelephonyStatsLog.buildStatsEvent(...) for atom PER_SIM_STATUS. */ public StatsEvent buildStatsEvent( int atomId, int simSlotIndex, int carrierId, int phoneNumberSourceUicc, int phoneNumberSourceCarrier, int phoneNumberSourceIms) { return TelephonyStatsLog.buildStatsEvent( atomId, simSlotIndex, carrierId, phoneNumberSourceUicc, phoneNumberSourceCarrier, phoneNumberSourceIms); } } tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java +73 −2 Original line number Diff line number Diff line Loading @@ -16,8 +16,13 @@ package com.android.internal.telephony.metrics; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_IMS; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_UICC; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE; import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS; import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE; import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE; Loading @@ -34,12 +39,14 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import android.app.StatsManager; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.util.StatsEvent; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.SubscriptionController; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; Loading Loading @@ -84,6 +91,7 @@ public class MetricsCollectorTest extends TelephonyTest { // Mocked classes private Phone mSecondPhone; private TelephonyStatsLogHelper mTelephonyStatsLog; private UiccSlot mPhysicalSlot; private UiccSlot mEsimSlot; private UiccCard mActiveCard; Loading @@ -96,13 +104,14 @@ public class MetricsCollectorTest extends TelephonyTest { public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); mSecondPhone = mock(Phone.class); mTelephonyStatsLog = mock(TelephonyStatsLogHelper.class); mPhysicalSlot = mock(UiccSlot.class); mEsimSlot = mock(UiccSlot.class); mActiveCard = mock(UiccCard.class); mActivePort = mock(UiccPort.class); mServiceStateStats = mock(ServiceStateStats.class); mMetricsCollector = new MetricsCollector(mContext); mMetricsCollector.setPersistAtomsStorage(mPersistAtomsStorage); mMetricsCollector = new MetricsCollector(mContext, mPersistAtomsStorage, mTelephonyStatsLog); doReturn(mSST).when(mSecondPhone).getServiceStateTracker(); doReturn(mServiceStateStats).when(mSST).getServiceStateStats(); } Loading Loading @@ -412,4 +421,66 @@ public class MetricsCollectorTest extends TelephonyTest { assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); // TODO(b/153196254): verify atom contents } @Test @SmallTest public void onPullAtom_perSimStatus() throws Exception { // Make PhoneFactory.getPhones() return an array of two replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mSecondPhone}); // phone 0 setup doReturn(0).when(mPhone).getPhoneId(); doReturn(1).when(mPhone).getSubId(); doReturn(100).when(mPhone).getCarrierId(); doReturn("6506953210") .when(mSubscriptionController) .getPhoneNumber(1, PHONE_NUMBER_SOURCE_UICC, null, null); doReturn("") .when(mSubscriptionController) .getPhoneNumber(1, PHONE_NUMBER_SOURCE_CARRIER, null, null); doReturn("+16506953210") .when(mSubscriptionController) .getPhoneNumber(1, PHONE_NUMBER_SOURCE_IMS, null, null); SubscriptionInfo subscriptionInfo1 = mock(SubscriptionInfo.class); doReturn("us").when(subscriptionInfo1).getCountryIso(); doReturn(subscriptionInfo1).when(mSubscriptionController).getSubscriptionInfo(1); // phone 1 setup doReturn(1).when(mSecondPhone).getPhoneId(); doReturn(2).when(mSecondPhone).getSubId(); doReturn(101).when(mSecondPhone).getCarrierId(); doReturn("0123") .when(mSubscriptionController) .getPhoneNumber(2, PHONE_NUMBER_SOURCE_UICC, null, null); doReturn("16506950123") .when(mSubscriptionController) .getPhoneNumber(2, PHONE_NUMBER_SOURCE_CARRIER, null, null); doReturn("+16506950123") .when(mSubscriptionController) .getPhoneNumber(2, PHONE_NUMBER_SOURCE_IMS, null, null); SubscriptionInfo subscriptionInfo2 = mock(SubscriptionInfo.class); doReturn("us").when(subscriptionInfo2).getCountryIso(); doReturn(subscriptionInfo2).when(mSubscriptionController).getSubscriptionInfo(2); List<StatsEvent> actualAtoms = new ArrayList<>(); int result = mMetricsCollector.onPullAtom(PER_SIM_STATUS, actualAtoms); verify(mTelephonyStatsLog).buildStatsEvent( PER_SIM_STATUS, 0, 100, 1, 0, 1); verify(mTelephonyStatsLog).buildStatsEvent( PER_SIM_STATUS, 1, 101, 1, 2, 2); assertThat(actualAtoms).hasSize(2); assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); } @Test @SmallTest public void onPullAtom_perSimStatus_noSubscriptionController_skip() throws Exception { // Make SubscriptionController.getInstance() return null replaceInstance(SubscriptionController.class, "sInstance", null, null); List<StatsEvent> actualAtoms = new ArrayList<>(); int result = mMetricsCollector.onPullAtom(PER_SIM_STATUS, actualAtoms); assertThat(actualAtoms).isEmpty(); assertThat(result).isEqualTo(StatsManager.PULL_SKIP); } } Loading
src/java/com/android/internal/telephony/metrics/MetricsCollector.java +88 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.internal.telephony.metrics; import static android.telephony.PhoneNumberUtils.areSamePhoneNumber; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_IMS; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_UICC; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS; Loading @@ -33,6 +37,7 @@ import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_ import static com.android.internal.telephony.TelephonyStatsLog.IMS_REGISTRATION_TERMINATION; import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS; import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT; import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS; import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS; Loading @@ -50,11 +55,14 @@ import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSIO import android.annotation.Nullable; import android.app.StatsManager; import android.content.Context; import android.telephony.SubscriptionInfo; import android.text.TextUtils; import android.util.StatsEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.SubscriptionController; import com.android.internal.telephony.TelephonyStatsLog; import com.android.internal.telephony.imsphone.ImsPhone; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; Loading Loading @@ -86,6 +94,7 @@ import com.android.telephony.Rlog; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; Loading Loading @@ -127,14 +136,24 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { .setCoolDownMillis(MIN_COOLDOWN_MILLIS) .build(); private PersistAtomsStorage mStorage; private final PersistAtomsStorage mStorage; private final TelephonyStatsLogHelper mTelephonyStatsLog; private final StatsManager mStatsManager; private final AirplaneModeStats mAirplaneModeStats; private final Set<DataCallSessionStats> mOngoingDataCallStats = ConcurrentHashMap.newKeySet(); private static final Random sRandom = new Random(); public MetricsCollector(Context context) { mStorage = new PersistAtomsStorage(context); this(context, new PersistAtomsStorage(context), new TelephonyStatsLogHelper()); } /** Allows dependency injection. Used during unit tests. */ @VisibleForTesting public MetricsCollector(Context context, PersistAtomsStorage storage, TelephonyStatsLogHelper telephonyStatsLog) { mStorage = storage; mTelephonyStatsLog = telephonyStatsLog; mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER); if (mStatsManager != null) { registerAtom(CELLULAR_DATA_SERVICE_SWITCH, POLICY_PULL_DAILY); Loading Loading @@ -163,6 +182,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { registerAtom(UCE_EVENT_STATS, POLICY_PULL_DAILY); registerAtom(PRESENCE_NOTIFY_EVENT, POLICY_PULL_DAILY); registerAtom(GBA_EVENT, POLICY_PULL_DAILY); registerAtom(PER_SIM_STATUS, null); Rlog.d(TAG, "registered"); } else { Loading @@ -172,12 +192,6 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { mAirplaneModeStats = new AirplaneModeStats(context); } /** Replaces the {@link PersistAtomsStorage} backing the puller. Used during unit tests. */ @VisibleForTesting public void setPersistAtomsStorage(PersistAtomsStorage storage) { mStorage = storage; } /** * {@inheritDoc} * Loading Loading @@ -240,6 +254,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { return pullPresenceNotifyEvent(data); case GBA_EVENT: return pullGbaEvent(data); case PER_SIM_STATUS: return pullPerSimStatus(data); default: Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag)); return StatsManager.PULL_SKIP; Loading Loading @@ -639,6 +655,70 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { } } private int pullPerSimStatus(List<StatsEvent> data) { SubscriptionController subscriptionController = SubscriptionController.getInstance(); if (subscriptionController == null) { return StatsManager.PULL_SKIP; } for (Phone phone : getPhonesIfAny()) { int subId = phone.getSubId(); String countryIso = Optional.ofNullable(subscriptionController.getSubscriptionInfo(subId)) .map(SubscriptionInfo::getCountryIso) .orElse(""); // numbersFromAllSources[]- Phone numbers from each sources // numberIds[] - Array of integer ids representing phone numbers. // If number is empty then id will be 0. Two same numbers will have same id, and // different numbers will have different ids. // For example, [1, 0, 1] means that uicc and ims numbers are the same while carrier // number is empty and [1, 2, 3] means all numbers are different. // index 0 - PHONE_NUMBER_SOURCE_UICC // index 1 - PHONE_NUMBER_SOURCE_CARRIER // index 2 - PHONE_NUMBER_SOURCE_IMS String[] numbersFromAllSources = new String[] { subscriptionController.getPhoneNumber( subId, PHONE_NUMBER_SOURCE_UICC, null, null), // 0 subscriptionController.getPhoneNumber( subId, PHONE_NUMBER_SOURCE_CARRIER, null, null), // 1 subscriptionController.getPhoneNumber( subId, PHONE_NUMBER_SOURCE_IMS, null, null), // 2 }; int[] numberIds = new int[numbersFromAllSources.length]; // default value 0 for (int i = 0, idForNextUniqueNumber = 1; i < numberIds.length; i++) { if (TextUtils.isEmpty(numbersFromAllSources[i])) { // keep id 0 if number not available continue; } // the number is available: // try to find the same number from other sources and reuse the id for (int j = 0; j < i; j++) { if (!TextUtils.isEmpty(numbersFromAllSources[j]) && areSamePhoneNumber( numbersFromAllSources[i], numbersFromAllSources[j], countryIso)) { numberIds[i] = numberIds[j]; } } // didn't find same number (otherwise should not be id 0), assign a new id if (numberIds[i] == 0) { numberIds[i] = idForNextUniqueNumber; idForNextUniqueNumber++; } } StatsEvent statsEvent = mTelephonyStatsLog.buildStatsEvent( PER_SIM_STATUS, phone.getPhoneId(), // simSlotIndex phone.getCarrierId(), // carrierId numberIds[0], // phoneNumberSourceUicc numberIds[1], // phoneNumberSourceCarrier numberIds[2]); // phoneNumberSourceIms data.add(statsEvent); } return StatsManager.PULL_SUCCESS; } /** Registers a pulled atom ID {@code atomId} with optional {@code policy} for pulling. */ private void registerAtom(int atomId, @Nullable StatsManager.PullAtomMetadata policy) { mStatsManager.setPullAtomCallback(atomId, policy, ConcurrentUtils.DIRECT_EXECUTOR, this); Loading
src/java/com/android/internal/telephony/metrics/TelephonyStatsLogHelper.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * 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.internal.telephony.metrics; import android.util.StatsEvent; import com.android.internal.telephony.TelephonyStatsLog; /** * Wrapper of generated TelephonyStatsLog class. Can be mocked during unit test. * * <p>Methods here have the same name/arguments/return as their counterparts in TelephonyStatsLog * and simply call their counterparts. Do not put any involved logic here as they cannot be * covered by unit test. */ public class TelephonyStatsLogHelper { /** Wraps TelephonyStatsLog.buildStatsEvent(...) for atom PER_SIM_STATUS. */ public StatsEvent buildStatsEvent( int atomId, int simSlotIndex, int carrierId, int phoneNumberSourceUicc, int phoneNumberSourceCarrier, int phoneNumberSourceIms) { return TelephonyStatsLog.buildStatsEvent( atomId, simSlotIndex, carrierId, phoneNumberSourceUicc, phoneNumberSourceCarrier, phoneNumberSourceIms); } }
tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java +73 −2 Original line number Diff line number Diff line Loading @@ -16,8 +16,13 @@ package com.android.internal.telephony.metrics; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_IMS; import static android.telephony.SubscriptionManager.PHONE_NUMBER_SOURCE_UICC; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH; import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE; import static com.android.internal.telephony.TelephonyStatsLog.PER_SIM_STATUS; import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE; import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE; Loading @@ -34,12 +39,14 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import android.app.StatsManager; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.util.StatsEvent; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.SubscriptionController; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch; import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState; Loading Loading @@ -84,6 +91,7 @@ public class MetricsCollectorTest extends TelephonyTest { // Mocked classes private Phone mSecondPhone; private TelephonyStatsLogHelper mTelephonyStatsLog; private UiccSlot mPhysicalSlot; private UiccSlot mEsimSlot; private UiccCard mActiveCard; Loading @@ -96,13 +104,14 @@ public class MetricsCollectorTest extends TelephonyTest { public void setUp() throws Exception { super.setUp(getClass().getSimpleName()); mSecondPhone = mock(Phone.class); mTelephonyStatsLog = mock(TelephonyStatsLogHelper.class); mPhysicalSlot = mock(UiccSlot.class); mEsimSlot = mock(UiccSlot.class); mActiveCard = mock(UiccCard.class); mActivePort = mock(UiccPort.class); mServiceStateStats = mock(ServiceStateStats.class); mMetricsCollector = new MetricsCollector(mContext); mMetricsCollector.setPersistAtomsStorage(mPersistAtomsStorage); mMetricsCollector = new MetricsCollector(mContext, mPersistAtomsStorage, mTelephonyStatsLog); doReturn(mSST).when(mSecondPhone).getServiceStateTracker(); doReturn(mServiceStateStats).when(mSST).getServiceStateStats(); } Loading Loading @@ -412,4 +421,66 @@ public class MetricsCollectorTest extends TelephonyTest { assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); // TODO(b/153196254): verify atom contents } @Test @SmallTest public void onPullAtom_perSimStatus() throws Exception { // Make PhoneFactory.getPhones() return an array of two replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mSecondPhone}); // phone 0 setup doReturn(0).when(mPhone).getPhoneId(); doReturn(1).when(mPhone).getSubId(); doReturn(100).when(mPhone).getCarrierId(); doReturn("6506953210") .when(mSubscriptionController) .getPhoneNumber(1, PHONE_NUMBER_SOURCE_UICC, null, null); doReturn("") .when(mSubscriptionController) .getPhoneNumber(1, PHONE_NUMBER_SOURCE_CARRIER, null, null); doReturn("+16506953210") .when(mSubscriptionController) .getPhoneNumber(1, PHONE_NUMBER_SOURCE_IMS, null, null); SubscriptionInfo subscriptionInfo1 = mock(SubscriptionInfo.class); doReturn("us").when(subscriptionInfo1).getCountryIso(); doReturn(subscriptionInfo1).when(mSubscriptionController).getSubscriptionInfo(1); // phone 1 setup doReturn(1).when(mSecondPhone).getPhoneId(); doReturn(2).when(mSecondPhone).getSubId(); doReturn(101).when(mSecondPhone).getCarrierId(); doReturn("0123") .when(mSubscriptionController) .getPhoneNumber(2, PHONE_NUMBER_SOURCE_UICC, null, null); doReturn("16506950123") .when(mSubscriptionController) .getPhoneNumber(2, PHONE_NUMBER_SOURCE_CARRIER, null, null); doReturn("+16506950123") .when(mSubscriptionController) .getPhoneNumber(2, PHONE_NUMBER_SOURCE_IMS, null, null); SubscriptionInfo subscriptionInfo2 = mock(SubscriptionInfo.class); doReturn("us").when(subscriptionInfo2).getCountryIso(); doReturn(subscriptionInfo2).when(mSubscriptionController).getSubscriptionInfo(2); List<StatsEvent> actualAtoms = new ArrayList<>(); int result = mMetricsCollector.onPullAtom(PER_SIM_STATUS, actualAtoms); verify(mTelephonyStatsLog).buildStatsEvent( PER_SIM_STATUS, 0, 100, 1, 0, 1); verify(mTelephonyStatsLog).buildStatsEvent( PER_SIM_STATUS, 1, 101, 1, 2, 2); assertThat(actualAtoms).hasSize(2); assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS); } @Test @SmallTest public void onPullAtom_perSimStatus_noSubscriptionController_skip() throws Exception { // Make SubscriptionController.getInstance() return null replaceInstance(SubscriptionController.class, "sInstance", null, null); List<StatsEvent> actualAtoms = new ArrayList<>(); int result = mMetricsCollector.onPullAtom(PER_SIM_STATUS, actualAtoms); assertThat(actualAtoms).isEmpty(); assertThat(result).isEqualTo(StatsManager.PULL_SKIP); } }