Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9d8bb0f authored by Hyunho Shin's avatar Hyunho Shin Committed by Automerger Merge Worker
Browse files

Merge "RCS single registration metrics inconsistencies" am: f1f964eb

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/1931603

Change-Id: Ifd36e006c3769adfe1632865027af67dc5e018c7
parents e9c927ce f1f964eb
Loading
Loading
Loading
Loading
+148 −31
Original line number Diff line number Diff line
@@ -305,16 +305,9 @@ public class RcsStats {
    private static final int SUBSCRIBE_SUCCESS = 1;
    private static final int SUBSCRIBE_NOTIFY = 2;

    private enum QosEstablishStatus {none, establishing, established};
    private final List<ImsDedicatedBearerListenerEvent> mImsDedicatedBearerListenerEvent =
            new ArrayList<>();
    private final Map<ImsDedicatedBearerListenerEvent, QosEstablishStatus>
            mQosEstablishedStatusMap = new HashMap<>();
    @VisibleForTesting
    protected final Map<Integer, ImsDedicatedBearerListenerEvent>
            mDedicatedBearerListenerEventMap = new HashMap<>();


    protected final Map<Integer, ImsDedicatedBearerListenerEvent> mDedicatedBearerListenerEventMap =
            new HashMap<>();
    @VisibleForTesting
    protected final List<RcsAcsProvisioningStats> mRcsAcsProvisioningStatsList =
            new ArrayList<RcsAcsProvisioningStats>();
@@ -327,7 +320,8 @@ public class RcsStats {
            new ArrayList<>();

    // Maps service id -> ImsRegistrationServiceDescStats.
    private final List<ImsRegistrationServiceDescStats> mImsRegistrationServiceDescStatsList =
    @VisibleForTesting
    protected final List<ImsRegistrationServiceDescStats> mImsRegistrationServiceDescStatsList =
            new ArrayList<>();

    private List<LastSipDelegateStat> mLastSipDelegateStatList = new ArrayList<>();
@@ -739,8 +733,12 @@ public class RcsStats {
        private synchronized void addSipMessageStat(
                @NonNull int subId, @NonNull String sipMessageMethod,
                int sipMessageResponse, int sipMessageDirection, int messageError) {
            int carrierId = getCarrierId(subId);
            if (!isValidCarrierId(carrierId)) {
                return;
            }
            SipMessageResponse proto = new SipMessageResponse();
            proto.carrierId = getCarrierId(subId);
            proto.carrierId = carrierId;
            proto.slotId = getSlotId(subId);
            proto.sipMessageMethod = convertMessageTypeToValue(sipMessageMethod);
            proto.sipMessageResponse = sipMessageResponse;
@@ -767,8 +765,12 @@ public class RcsStats {
        private synchronized void addSipTransportSessionStat(
                @NonNull int subId, @NonNull String sessionMethod, int sipMessageDirection,
                int sipResponse, boolean isEndedGracefully) {
            int carrierId = getCarrierId(subId);
            if (!isValidCarrierId(carrierId)) {
                return;
            }
            SipTransportSession proto = new SipTransportSession();
            proto.carrierId = getCarrierId(subId);
            proto.carrierId = carrierId;
            proto.slotId = getSlotId(subId);
            proto.sessionMethod = convertMessageTypeToValue(sessionMethod);
            proto.sipMessageDirection = sipMessageDirection;
@@ -809,6 +811,12 @@ public class RcsStats {
    public void onImsRegistrationFeatureTagStats(int subId, List<String> featureTagList,
            int registrationTech) {
        synchronized (mImsRegistrationFeatureTagStatsList) {
            int carrierId = getCarrierId(subId);
            if (!isValidCarrierId(carrierId)) {
                flushImsRegistrationFeatureTagStatsInvalid();
                return;
            }

            // update cached atom if exists
            onStoreCompleteImsRegistrationFeatureTagStats(subId);

@@ -819,7 +827,7 @@ public class RcsStats {

            for (String featureTag : featureTagList) {
                ImsRegistrationFeatureTagStats proto = new ImsRegistrationFeatureTagStats();
                proto.carrierId = getCarrierId(subId);
                proto.carrierId = carrierId;
                proto.slotId = getSlotId(subId);
                proto.featureTagName = convertTagNameToValue(featureTag);
                proto.registrationTech = registrationTech;
@@ -865,8 +873,14 @@ public class RcsStats {

    /** Create a new atom when RCS client stat changed. */
    public synchronized void onRcsClientProvisioningStats(int subId, int event) {
        int carrierId = getCarrierId(subId);

        if (!isValidCarrierId(carrierId)) {
            return;
        }

        RcsClientProvisioningStats proto = new RcsClientProvisioningStats();
        proto.carrierId = getCarrierId(subId);
        proto.carrierId = carrierId;
        proto.slotId = getSlotId(subId);
        proto.event = event;
        proto.count = 1;
@@ -878,12 +892,18 @@ public class RcsStats {
            boolean enableSingleRegistration) {

        synchronized (mRcsAcsProvisioningStatsList) {
            int carrierId = getCarrierId(subId);
            if (!isValidCarrierId(carrierId)) {
                flushRcsAcsProvisioningStatsInvalid();
                return;
            }

            // update cached atom if exists
            onStoreCompleteRcsAcsProvisioningStats(subId);

            // create new stats to cache
            RcsAcsProvisioningStats newStats = new RcsAcsProvisioningStats();
            newStats.carrierId = getCarrierId(subId);
            newStats.carrierId = carrierId;
            newStats.slotId = getSlotId(subId);
            newStats.responseCode = responseCode;
            newStats.responseType = responseType;
@@ -1054,16 +1074,20 @@ public class RcsStats {
    public synchronized void onImsDedicatedBearerListenerAdded(@NonNull final int listenerId,
            @NonNull final int slotId, @NonNull final int ratAtEnd, @NonNull final int qci) {
        int subId = getSubId(slotId);
        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
        int carrierId = getCarrierId(subId);

        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
                || !isValidCarrierId(carrierId)) {
            return;
        }

        if (mDedicatedBearerListenerEventMap.containsKey(listenerId)) {
            return;
        }

        ImsDedicatedBearerListenerEvent preProto = new ImsDedicatedBearerListenerEvent();
        preProto.carrierId = getCarrierId(subId);
        preProto.slotId = getSlotId(subId);
        preProto.carrierId = carrierId;
        preProto.slotId = slotId;
        preProto.ratAtEnd = ratAtEnd;
        preProto.qci = qci;
        preProto.dedicatedBearerEstablished = false;
@@ -1078,7 +1102,10 @@ public class RcsStats {
            final int slotId, final int rat, final int qci,
            @NonNull final boolean dedicatedBearerEstablished) {
        int subId = getSubId(slotId);
        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
        int carrierId = getCarrierId(subId);

        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
                || !isValidCarrierId(carrierId)) {
            return;
        }

@@ -1093,8 +1120,8 @@ public class RcsStats {
            mDedicatedBearerListenerEventMap.replace(listenerId, preProto);
        } else {
            ImsDedicatedBearerListenerEvent preProto = new ImsDedicatedBearerListenerEvent();
            preProto.carrierId = getCarrierId(subId);
            preProto.slotId = getSlotId(subId);
            preProto.carrierId = carrierId;
            preProto.slotId = slotId;
            preProto.ratAtEnd = rat;
            preProto.qci = qci;
            preProto.dedicatedBearerEstablished = dedicatedBearerEstablished;
@@ -1146,6 +1173,11 @@ public class RcsStats {
    public void onImsRegistrationServiceDescStats(int subId, List<String> serviceIdList,
            List<String> serviceIdVersionList, int registrationTech) {
        synchronized (mImsRegistrationServiceDescStatsList) {
            int carrierId = getCarrierId(subId);
            if (!isValidCarrierId(carrierId)) {
                handleImsRegistrationServiceDescStats();
                return;
            }
            // update cached atom if exists
            onStoreCompleteImsRegistrationServiceDescStats(subId);

@@ -1153,15 +1185,14 @@ public class RcsStats {
                Rlog.d(TAG, "serviceIds is null or empty");
                return;
            }
            int carrierid = getCarrierId(subId);
            int slotid = getSlotId(subId);

            int index = 0;
            for (String serviceId : serviceIdList) {
                ImsRegistrationServiceDescStats mImsRegistrationServiceDescStats =
                        new ImsRegistrationServiceDescStats();

                mImsRegistrationServiceDescStats.carrierId = carrierid;
                mImsRegistrationServiceDescStats.slotId = slotid;
                mImsRegistrationServiceDescStats.carrierId = carrierId;
                mImsRegistrationServiceDescStats.slotId = getSlotId(subId);
                mImsRegistrationServiceDescStats.serviceIdName = convertServiceIdToValue(serviceId);
                mImsRegistrationServiceDescStats.serviceIdVersion =
                        Float.parseFloat(serviceIdVersionList.get(index++));
@@ -1192,7 +1223,12 @@ public class RcsStats {
            int commandCode, int networkResponse) {
        UceEventStats proto = new UceEventStats();

        proto.carrierId = getCarrierId(subId);
        int carrierId = getCarrierId(subId);
        if (!isValidCarrierId(carrierId)) {
            handleImsRegistrationServiceDescStats();
            return;
        }
        proto.carrierId = carrierId;
        proto.slotId = getSlotId(subId);
        proto.type = type;
        proto.successful = successful;
@@ -1221,7 +1257,13 @@ public class RcsStats {
            boolean contentBodyReceived, boolean rcsCaps, boolean mmtelCaps, boolean noCaps) {
        PresenceNotifyEvent proto = new PresenceNotifyEvent();

        proto.carrierId = getCarrierId(subId);
        int carrierId = getCarrierId(subId);
        if (!isValidCarrierId(carrierId)) {
            handleImsRegistrationServiceDescStats();
            return;
        }

        proto.carrierId = carrierId;
        proto.slotId = getSlotId(subId);
        proto.reason = convertPresenceNotifyReason(reason);
        proto.contentBodyReceived = contentBodyReceived;
@@ -1252,8 +1294,13 @@ public class RcsStats {

    /** Create a new atom when GBA Success Event changed. */
    public synchronized void onGbaSuccessEvent(int subId) {
        int carrierId = getCarrierId(subId);
        if (!isValidCarrierId(carrierId)) {
            return;
        }

        GbaEvent proto = new GbaEvent();
        proto.carrierId = getCarrierId(subId);
        proto.carrierId = carrierId;
        proto.slotId = getSlotId(subId);
        proto.successful = true;
        proto.failedReason = -1;
@@ -1263,8 +1310,13 @@ public class RcsStats {

    /** Create a new atom when GBA Failure Event changed. */
    public synchronized void onGbaFailureEvent(int subId, int reason) {
        int carrierId = getCarrierId(subId);
        if (!isValidCarrierId(carrierId)) {
            return;
        }

        GbaEvent proto = new GbaEvent();
        proto.carrierId = getCarrierId(subId);
        proto.carrierId = carrierId;
        proto.slotId = getSlotId(subId);
        proto.successful = false;
        proto.failedReason = reason;
@@ -1363,6 +1415,26 @@ public class RcsStats {
        }
    }

    private void handleImsRegistrationServiceDescStats() {
        synchronized (mImsRegistrationServiceDescStatsList) {
            List<ImsRegistrationServiceDescStats> deleteList = new ArrayList<>();
            for (ImsRegistrationServiceDescStats proto : mImsRegistrationServiceDescStatsList) {
                int subId = getSubId(proto.slotId);
                int newCarrierId = getCarrierId(subId);
                if (proto.carrierId != newCarrierId) {
                    deleteList.add(proto);
                    if (proto.publishedMillis != 0) {
                        proto.publishedMillis = getWallTimeMillis() - proto.publishedMillis;
                        mAtomsStorage.addImsRegistrationServiceDescStats(proto);
                    }
                }
            }
            for (ImsRegistrationServiceDescStats stats : deleteList) {
                mImsRegistrationServiceDescStatsList.remove(stats);
            }
        }
    }

    private RcsAcsProvisioningStats getRcsAcsProvisioningStats(int subId) {
        int carrierId = getCarrierId(subId);
        int slotId = getSlotId(subId);
@@ -1378,6 +1450,51 @@ public class RcsStats {
        return null;
    }

    private void flushRcsAcsProvisioningStatsInvalid() {
        List<RcsAcsProvisioningStats> inValidList = new ArrayList<RcsAcsProvisioningStats>();

        int subId;
        int newCarrierId;

        for (RcsAcsProvisioningStats stats : mRcsAcsProvisioningStatsList) {
            subId = getSubId(stats.slotId);
            newCarrierId = getCarrierId(subId);
            if (stats.carrierId != newCarrierId) {
                inValidList.add(stats);
            }
        }

        for (RcsAcsProvisioningStats inValid : inValidList) {
            inValid.stateTimerMillis = getWallTimeMillis() - inValid.stateTimerMillis;
            mAtomsStorage.addRcsAcsProvisioningStats(inValid);
            mRcsAcsProvisioningStatsList.remove(inValid);
        }
        inValidList.clear();
    }

    private void flushImsRegistrationFeatureTagStatsInvalid() {
        List<ImsRegistrationFeatureTagStats> inValidList =
                new ArrayList<ImsRegistrationFeatureTagStats>();

        int subId;
        int newCarrierId;

        for (ImsRegistrationFeatureTagStats stats : mImsRegistrationFeatureTagStatsList) {
            subId = getSubId(stats.slotId);
            newCarrierId = getCarrierId(subId);
            if (stats.carrierId != newCarrierId) {
                inValidList.add(stats);
            }
        }

        for (ImsRegistrationFeatureTagStats inValid : inValidList) {
            inValid.registeredMillis = getWallTimeMillis() - inValid.registeredMillis;
            mAtomsStorage.addImsRegistrationFeatureTagStats(inValid);
            mImsRegistrationFeatureTagStatsList.remove(inValid);
        }
        inValidList.clear();
    }

    private LastSipDelegateStat getLastSipDelegateStat(int subId, Set<String> supportedTags) {
        LastSipDelegateStat stat = null;
        for (LastSipDelegateStat lastStat : mLastSipDelegateStatList) {
@@ -1419,8 +1536,8 @@ public class RcsStats {
        }
        return sipTransportFeatureTags;
    }

    private boolean isValidCarrierId(int carrierId) {
    @VisibleForTesting
    protected boolean isValidCarrierId(int carrierId) {
        return carrierId > TelephonyManager.UNKNOWN_CARRIER_ID;
    }

+154 −5
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.internal.telephony.metrics;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -64,6 +67,7 @@ public class RcsStatsTest extends TelephonyTest {
    private static final long START_TIME_MILLIS = 2000L;
    private static final int SLOT_ID = 0;
    private static final int SLOT2_ID = 1;
    private static final int INVALID_SLOT_ID = -1;
    private static final int CARRIER_ID = 100;
    private static final int CARRIER2_ID = 200;
    private static final int INVALID_CARRIER_ID = -1;
@@ -92,6 +96,7 @@ public class RcsStatsTest extends TelephonyTest {

    private class TestableRcsStats extends RcsStats {
        private long mTimeMillis = START_TIME_MILLIS;
        private boolean mEnabledInvalidSubId = false;

        TestableRcsStats() {
            super();
@@ -99,21 +104,38 @@ public class RcsStatsTest extends TelephonyTest {

        @Override
        protected int getSlotId(int subId) {
            if (mEnabledInvalidSubId) {
                return INVALID_SLOT_ID;
            }

            if (subId == mSubId) {
                return SLOT_ID;
            } else if (subId == mSubId2) {
                return SLOT2_ID;
            }
            return SLOT2_ID;
        }

        @Override
        protected int getCarrierId(int subId) {
            if (subId == INVALID_SUB_ID) {
            if (mEnabledInvalidSubId) {
                return INVALID_CARRIER_ID;
            } else if (subId == mSubId) {
            }

            if (subId == mSubId) {
                return CARRIER_ID;
            } else {
            } else if (subId == mSubId2) {
                return CARRIER2_ID;
            }
            return INVALID_CARRIER_ID;
        }

        @Override
        protected boolean isValidCarrierId(int carrierId) {
            if (carrierId == INVALID_CARRIER_ID) {
                return false;
            }
            return true;
        }

        @Override
@@ -131,12 +153,21 @@ public class RcsStatsTest extends TelephonyTest {

        @Override
        protected int getSubId(int slotId) {
            if (mEnabledInvalidSubId) {
                return INVALID_SUB_ID;
            }

            if (slotId == SLOT_ID) {
                return mSubId;
            }
            } else if (slotId == SLOT2_ID) {
                return mSubId2;
            }
            return INVALID_SUB_ID;
        }

        public void setEnableInvalidSubId() {
            mEnabledInvalidSubId = true;
        }
        private void setTimeMillis(long timeMillis) {
            mTimeMillis = timeMillis;
        }
@@ -150,6 +181,10 @@ public class RcsStatsTest extends TelephonyTest {
            return mRcsAcsProvisioningStatsList.size();
        }

        public int getImsRegistrationServiceDescCachedSize() {
            return mImsRegistrationServiceDescStatsList.size();
        }

        public long getRcsAcsProvisioningCachedTime(int carreirId, int slotId) {
            for (RcsAcsProvisioningStats stats : mRcsAcsProvisioningStatsList) {
                if (stats.carrierId == carreirId && stats.slotId == slotId) {
@@ -285,6 +320,50 @@ public class RcsStatsTest extends TelephonyTest {
        assertEquals(responseType[0], stats.responseType);
        assertEquals(isSingleRegistrationEnabled, stats.isSingleRegistrationEnabled);
        assertEquals(timeGap, stats.stateTimerMillis);

        // the last atoms will be cached
        assertEquals(1, mRcsStats.getRcsAcsProvisioningCachedSize());
        verifyNoMoreInteractions(mPersistAtomsStorage);
    }

    @Test
    @SmallTest
    public void onRcsAcsProvisioningStats_withAtomsInvalidSubId() throws Exception {
        boolean isSingleRegistrationEnabled = true;
        int[] responseCode = {200, 401};
        int[] responseType = {
                TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML,
                TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__ERROR};
        int[] slotIds = {SLOT_ID, SLOT_ID};
        int[] carrierIds = {CARRIER_ID, CARRIER_ID};

        // this will be cached
        mRcsStats.onRcsAcsProvisioningStats(
                mSubId, responseCode[0], responseType[0], isSingleRegistrationEnabled);

        long timeGap = 6000L;
        mRcsStats.incTimeMillis(timeGap);

        // slotId and carrierId are invalid based on subId
        mRcsStats.setEnableInvalidSubId();

        // this will not be cached, previous will be stored
        mRcsStats.onRcsAcsProvisioningStats(
                mSubId, responseCode[1], responseType[1], isSingleRegistrationEnabled);

        ArgumentCaptor<RcsAcsProvisioningStats> captor =
                ArgumentCaptor.forClass(RcsAcsProvisioningStats.class);
        verify(mPersistAtomsStorage).addRcsAcsProvisioningStats(captor.capture());
        RcsAcsProvisioningStats stats = captor.getValue();
        assertEquals(carrierIds[0], stats.carrierId);
        assertEquals(slotIds[0], stats.slotId);
        assertEquals(responseCode[0], stats.responseCode);
        assertEquals(responseType[0], stats.responseType);
        assertEquals(isSingleRegistrationEnabled, stats.isSingleRegistrationEnabled);
        assertEquals(timeGap, stats.stateTimerMillis);
        // the last atoms will not be cached
        assertEquals(0, mRcsStats.getRcsAcsProvisioningCachedSize());

        verifyNoMoreInteractions(mPersistAtomsStorage);
    }

@@ -1027,6 +1106,76 @@ public class RcsStatsTest extends TelephonyTest {
        verifyNoMoreInteractions(mPersistAtomsStorage);
    }

    @Test
    @SmallTest
    public void onImsRegistrationServiceDescStats_withAtomsInvalidSubId() throws Exception {
        int registrationTech  = 0; //ImsRegistrationImplBase.REGISTRATION_TECH_LTE
        ArrayList<String> serviceIdList = new ArrayList<>();
        serviceIdList.add("org.openmobilealliance:File-Transfer-HTTP");
        serviceIdList.add("org.openmobilealliance:IM-session");
        serviceIdList.add("Unknown1");
        ArrayList<String> serviceIdVersionList = new ArrayList<>();
        serviceIdVersionList.add("1.0");
        serviceIdVersionList.add("1.0");
        serviceIdVersionList.add("3.0");

        mRcsStats.onImsRegistrationServiceDescStats(mSubId, serviceIdList, serviceIdVersionList,
                registrationTech);

        // getWallTimeMillis
        /*
         * UCE_EVENT__TYPE__PUBLISH = 0;
         * UCE_EVENT__TYPE__SUBSCRIBE = 1;
         * UCE_EVENT__TYPE__INCOMING_OPTION = 2;
         * UCE_EVENT__TYPE__OUTGOING_OPTION = 3;
         */
        int type = TelephonyStatsLog.UCE_EVENT_STATS__TYPE__PUBLISH;
        boolean successful = true;
        /*
         * UCE_EVENT__COMMAND_CODE__SERVICE_UNKNOWN = 0;
         * UCE_EVENT__COMMAND_CODE__GENERIC_FAILURE = 1;
         * UCE_EVENT__COMMAND_CODE__INVALID_PARAM = 2;
         * UCE_EVENT__COMMAND_CODE__FETCH_ERROR = 3;
         * UCE_EVENT__COMMAND_CODE__REQUEST_TIMEOUT = 4;
         * UCE_EVENT__COMMAND_CODE__INSUFFICIENT_MEMORY = 5;
         * UCE_EVENT__COMMAND_CODE__LOST_NETWORK_CONNECTION = 6;
         * UCE_EVENT__COMMAND_CODE__NOT_SUPPORTED = 7;
         * UCE_EVENT__COMMAND_CODE__NOT_FOUND = 8;
         * UCE_EVENT__COMMAND_CODE__SERVICE_UNAVAILABLE = 9;
         * UCE_EVENT__COMMAND_CODE__NO_CHANGE = 10;
         */
        int commandCode = TelephonyStatsLog.UCE_EVENT_STATS__COMMAND_CODE__SERVICE_UNAVAILABLE;
        int networkResponse = 200;
        mRcsStats.onUceEventStats(mSubId, type, successful, commandCode, networkResponse);

        // slotId and carrierId are invalid based on subId
        mRcsStats.setEnableInvalidSubId();
        long timeGap = 6000L;
        mRcsStats.incTimeMillis(timeGap);
        mRcsStats.onUceEventStats(mSubId, type, successful, commandCode, networkResponse);

        ArgumentCaptor<ImsRegistrationServiceDescStats> captor =
                ArgumentCaptor.forClass(ImsRegistrationServiceDescStats.class);
        verify(mPersistAtomsStorage, times(3))
                .addImsRegistrationServiceDescStats(captor.capture());
        List<ImsRegistrationServiceDescStats> captorValues = captor.getAllValues();

        assertEquals(captorValues.size(), serviceIdList.size());

        for (int index = 0; index < captorValues.size(); index++) {
            ImsRegistrationServiceDescStats stats = captorValues.get(index);
            assertEquals(CARRIER_ID, stats.carrierId);
            assertEquals(SLOT_ID, stats.slotId);
            int serviceId = mRcsStats.convertServiceIdToValue(serviceIdList.get(index));
            assertEquals(serviceId, stats.serviceIdName);
            float serviceVersionFloat = Float.parseFloat(serviceIdVersionList.get(index));
            assertEquals(serviceVersionFloat, stats.serviceIdVersion, 0.1f);
            assertEquals(registrationTech, stats.registrationTech);
            assertEquals(timeGap, stats.publishedMillis);
        }
        assertEquals(0, mRcsStats.getImsRegistrationServiceDescCachedSize());
    }

    @Test
    @SmallTest
    public void onUceEventStats_withAtoms() throws Exception {