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

Commit 2537e164 authored by Kunal Malhotra's avatar Kunal Malhotra Committed by Android (Google) Code Review
Browse files

Merge "Updating foreground service type logger to log the duration of APIs and...

Merge "Updating foreground service type logger to log the duration of APIs and adding additional logging of FGS starts." into udc-dev
parents 7a91a429 4cfda378
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -8253,12 +8253,14 @@ public final class ActiveServices {
                r.mFgsDelegation != null ? r.mFgsDelegation.mOptions.mDelegationService
                        : ForegroundServiceDelegationOptions.DELEGATION_SERVICE_DEFAULT,
                0 /* api_sate */,
                null /* api_type */,
                null /* api_timestamp */,
                0 /* api_type */,
                0 /* api_timestamp */,
                mAm.getUidStateLocked(r.appInfo.uid),
                mAm.getUidProcessCapabilityLocked(r.appInfo.uid),
                mAm.getUidStateLocked(r.mRecentCallingUid),
                mAm.getUidProcessCapabilityLocked(r.mRecentCallingUid));
                mAm.getUidProcessCapabilityLocked(r.mRecentCallingUid),
                0,
                0);

        int event = 0;
        if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
@@ -8433,6 +8435,9 @@ public final class ActiveServices {
                true, false, null, false,
                AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
        registerAppOpCallbackLocked(r);
        synchronized (mFGSLogger) {
            mFGSLogger.logForegroundServiceStart(r.appInfo.uid, 0, r);
        }
        logFGSStateChangeLocked(r,
                FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
                0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
+41 −29
Original line number Diff line number Diff line
@@ -105,6 +105,11 @@ public class ForegroundServiceTypeLoggerModule {
        // to another ordered map, keyed by the component name
        // to facilitate removing the record from the structure
        final SparseArray<ArrayMap<ComponentName, ServiceRecord>> mRunningFgs = new SparseArray<>();

        // A map of API types to last FGS stop call timestamps
        // We use this to get the duration an API was active after
        // the stop call.
        final SparseArray<Long> mLastFgsTimeStamp = new SparseArray<>();
    }

    // SparseArray that tracks all UIDs that have made various
@@ -167,17 +172,13 @@ public class ForegroundServiceTypeLoggerModule {
        }
        if (!apiTypesFound.isEmpty()) {
            // log a state change
            int[] types = new int[apiTypesFound.size()];
            long[] timestamps = new long[apiTypesFound.size()];
            for (int i = 0, size = apiTypesFound.size(); i < size; i++) {
                types[i] = apiTypesFound.get(i);
                timestamps[i] = timestampsFound.get(i);
            }
                logFgsApiEvent(record,
                        FGS_STATE_CHANGED_API_CALL,
                        FGS_API_BEGIN_WITH_FGS,
                    types,
                    timestamps);
                        apiTypesFound.get(i),
                        timestampsFound.get(i));
            }
        }
    }

@@ -192,7 +193,7 @@ public class ForegroundServiceTypeLoggerModule {
        final ArrayList<Integer> apiTypes = convertFgsTypeToApiTypes(record.foregroundServiceType);
        final UidState uidState = mUids.get(uid);
        if (uidState == null) {
            Slog.wtfStack(TAG, "FGS stop call being logged with no start call for UID for UID "
            Slog.w(TAG, "FGS stop call being logged with no start call for UID for UID "
                    + uid
                    + " in package " + record.packageName);
            return;
@@ -202,7 +203,7 @@ public class ForegroundServiceTypeLoggerModule {
        for (int i = 0, size = apiTypes.size(); i < size; i++) {
            final int apiType = apiTypes.get(i);
            if (!uidState.mOpenWithFgsCount.contains(apiType)) {
                Slog.wtfStack(TAG, "Logger should be tracking FGS types correctly for UID " + uid
                Slog.w(TAG, "Logger should be tracking FGS types correctly for UID " + uid
                        + " in package " + record.packageName);
                continue;
            }
@@ -231,19 +232,17 @@ public class ForegroundServiceTypeLoggerModule {
            if (runningFgsOfType.size() == 0) {
                // there's no more FGS running for this type, just get rid of it
                uidState.mRunningFgs.remove(apiType);
                // but we need to keep track of the timestamp in case an API stops
                uidState.mLastFgsTimeStamp.put(apiType, record.mFgsExitTime);
            }
        }
        if (!apisFound.isEmpty()) {
            // time to log the call
            int[] types = new int[apisFound.size()];
            long[] timestamps = new long[apisFound.size()];
            for (int i = 0; i < apisFound.size(); i++) {
                types[i] = apisFound.get(i);
                timestamps[i] = timestampsFound.get(i);
            }
                logFgsApiEvent(record,
                        FGS_STATE_CHANGED_API_CALL,
                    FGS_API_END_WITH_FGS, types, timestamps);
                        FGS_API_END_WITH_FGS, apisFound.get(i), timestampsFound.get(i));
            }
        }
    }

@@ -303,8 +302,8 @@ public class ForegroundServiceTypeLoggerModule {
        final ArrayMap<ComponentName, ServiceRecord> fgsListMap = uidState.mRunningFgs.get(apiType);

        // now we get the relevant FGS to log with
        final int[] apiTypes = {apiType};
        final long[] timestamps = {callStart.mTimeStart};
        final int apiTypes = apiType;
        final long timestamps = callStart.mTimeStart;
        if (uidState.mOpenWithFgsCount.valueAt(openWithFgsIndex) == 1) {
            for (ServiceRecord record : fgsListMap.values()) {
                logFgsApiEvent(record,
@@ -347,13 +346,13 @@ public class ForegroundServiceTypeLoggerModule {
                // we just log that an event happened w/ no
                // FGS associated. This is to avoid dangling
                // events
                final long[] timestamp = {System.currentTimeMillis()};
                final int[] apiTypes = {apiType};
                final long timestamp = System.currentTimeMillis();
                final int apiTypes = apiType;
                logFgsApiEventWithNoFgs(uid, FGS_API_END_WITHOUT_FGS, apiTypes, timestamp);
                // we should now remove the count, so as to signal that
                // there was never an FGS called that can be associated
                uidState.mOpenWithFgsCount.remove(apiType);
                return timestamp[0];
                return timestamp;
            }
        }
        // we know now that this call is not coming from an
@@ -392,8 +391,8 @@ public class ForegroundServiceTypeLoggerModule {
            return;
        }
        final ArrayMap<ComponentName, ServiceRecord> fgsRecords = uidState.mRunningFgs.get(apiType);
        final int[] apiTypes = {apiType};
        final long[] timestamp = {System.currentTimeMillis()};
        final int apiTypes = apiType;
        final long timestamp = System.currentTimeMillis();
        for (ServiceRecord record : fgsRecords.values()) {
            logFgsApiEvent(record,
                    FGS_STATE_CHANGED_API_CALL,
@@ -449,7 +448,9 @@ public class ForegroundServiceTypeLoggerModule {
    @VisibleForTesting
    public void logFgsApiEvent(ServiceRecord r, int fgsState,
            @FgsApiState int apiState,
            @ForegroundServiceApiType int[] apiType, long[] timestamp) {
            @ForegroundServiceApiType int apiType, long timestamp) {
        final long apiDurationBeforeFgsStart = r.mFgsEnterTime - timestamp;
        final long apiDurationAfterFgsEnd = timestamp - r.mFgsExitTime;
        FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                r.appInfo.uid,
                r.shortInstanceName,
@@ -479,7 +480,9 @@ public class ForegroundServiceTypeLoggerModule {
                ActivityManager.PROCESS_STATE_UNKNOWN,
                ActivityManager.PROCESS_CAPABILITY_NONE,
                ActivityManager.PROCESS_STATE_UNKNOWN,
                ActivityManager.PROCESS_CAPABILITY_NONE);
                ActivityManager.PROCESS_CAPABILITY_NONE,
                apiDurationBeforeFgsStart,
                apiDurationAfterFgsEnd);
    }

    /**
@@ -489,7 +492,14 @@ public class ForegroundServiceTypeLoggerModule {
    @VisibleForTesting
    public void logFgsApiEventWithNoFgs(int uid,
            @FgsApiState int apiState,
            @ForegroundServiceApiType int[] apiType, long[] timestamp) {
            @ForegroundServiceApiType int apiType, long timestamp) {
        long apiDurationAfterFgsEnd = 0;
        UidState uidState = mUids.get(uid);
        if (uidState != null) {
            if (uidState.mLastFgsTimeStamp.contains(apiType)) {
                apiDurationAfterFgsEnd = timestamp - uidState.mLastFgsTimeStamp.get(apiType);
            }
        }
        FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                uid,
                null,
@@ -517,7 +527,9 @@ public class ForegroundServiceTypeLoggerModule {
                ActivityManager.PROCESS_STATE_UNKNOWN,
                ActivityManager.PROCESS_CAPABILITY_NONE,
                ActivityManager.PROCESS_STATE_UNKNOWN,
                ActivityManager.PROCESS_CAPABILITY_NONE);
                ActivityManager.PROCESS_CAPABILITY_NONE,
                0,
                apiDurationAfterFgsEnd);
    }

    /**
+82 −67
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.server.am.ForegroundServiceTypeLoggerModule.FGS_STATE_

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
@@ -41,7 +42,6 @@ import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.mockito.AdditionalMatchers;

/**
 * Test class for {@link ForegroundServiceTypeLoggerModule}.
@@ -61,10 +61,10 @@ public class FgsLoggerTest {
        mFgsLogger = spy(logger);
        doNothing().when(mFgsLogger)
                .logFgsApiEvent(any(ServiceRecord.class),
                        anyInt(), anyInt(), any(int[].class), any(long[].class));
                        anyInt(), anyInt(), anyInt(), anyLong());
        doNothing().when(mFgsLogger)
                .logFgsApiEventWithNoFgs(anyInt(),
                        anyInt(), any(int[].class), any(long[].class));
                        anyInt(), anyInt(), anyLong());
    }

    @Test
@@ -73,10 +73,10 @@ public class FgsLoggerTest {
        record.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
        mFgsLogger.logForegroundServiceStart(1, 1, record);
        mFgsLogger.logForegroundServiceApiEventBegin(1, 1, 1, "aPackageHasNoName");
        int[] expectedTypes = {1};
        int expectedTypes = 1;
        verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
                eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS),
                AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                eq(expectedTypes), anyLong());
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1);

@@ -85,7 +85,7 @@ public class FgsLoggerTest {
        mFgsLogger.logForegroundServiceStop(1, record);
        verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
                eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_END_WITH_FGS),
                AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                eq(expectedTypes), anyLong());
    }

    @Test
@@ -97,10 +97,10 @@ public class FgsLoggerTest {
        resetAndVerifyZeroInteractions();

        mFgsLogger.logForegroundServiceStart(1, 1, record);
        int[] expectedTypes = {1};
        int expectedTypes = 1;
        verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
                eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS),
                AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                eq(expectedTypes), anyLong());
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1);

@@ -109,7 +109,7 @@ public class FgsLoggerTest {
        mFgsLogger.logForegroundServiceStop(1, record);
        verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
                eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_END_WITH_FGS),
                AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                eq(expectedTypes), anyLong());
    }

    @Test
@@ -122,12 +122,12 @@ public class FgsLoggerTest {

        resetAndVerifyZeroInteractions();

        int[] expectedTypes = {1};
        int expectedTypes = 1;

        mFgsLogger.logForegroundServiceStart(1, 1, record);
        verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
                eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS),
                AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                eq(expectedTypes), anyLong());
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceStop(1, record);

@@ -135,7 +135,7 @@ public class FgsLoggerTest {

        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        verify(mFgsLogger).logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
                AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                eq(expectedTypes), anyLong());
    }

    @Test
@@ -176,15 +176,15 @@ public class FgsLoggerTest {
        // now we should see exactly one call logged
        // and this should be the very first call
        // we also try to verify the time as being the very first call
        int[] expectedTypes = {1};
        long[] expectedTimestamp = {timeStamp};
        int expectedTypes = 1;
        long expectedTimestamp = timeStamp;

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        reset(mFgsLogger);
        // now we do multiple stops
        // only the last one should be logged
@@ -201,11 +201,11 @@ public class FgsLoggerTest {
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        timeStamp = mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA,
                1, 1);
        expectedTimestamp[0] = timeStamp;
        expectedTimestamp = timeStamp;
        verify(mFgsLogger, times(1))
                .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
    }

    @Test
@@ -239,15 +239,15 @@ public class FgsLoggerTest {
        // now we should see exactly one call logged
        // and this should be the very first call
        // we also try to verify the time as being the very first call
        int[] expectedTypes = {1};
        long[] expectedTimestamp = {timeStamp};
        int expectedTypes = 1;
        long expectedTimestamp = timeStamp;

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        reset(mFgsLogger);
        // now we do multiple stops
        // only the last one should be logged
@@ -269,11 +269,11 @@ public class FgsLoggerTest {
                1, 1);
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        expectedTimestamp[0] = timeStamp;
        expectedTimestamp = timeStamp;
        verify(mFgsLogger, times(1))
                .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
    }

    @Test
@@ -304,15 +304,15 @@ public class FgsLoggerTest {
        // now we should see exactly one call logged
        // and this should be the very first call
        // we also try to verify the time as being the very first call
        int[] expectedTypes = {1};
        long[] expectedTimestamp = {timeStamp};
        int expectedTypes = 1;
        long expectedTimestamp = timeStamp;

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
                "aPackageHasNoName");
@@ -338,11 +338,11 @@ public class FgsLoggerTest {
                1, 1);
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        expectedTimestamp[0] = timeStamp;
        expectedTimestamp = timeStamp;
        verify(mFgsLogger, times(1))
                .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
    }

    @Test
@@ -375,15 +375,15 @@ public class FgsLoggerTest {
        // now we should see exactly one call logged
        // and this should be the very first call
        // we also try to verify the time as being the very first call
        int[] expectedTypes = {1};
        long[] expectedTimestamp = {timeStamp};
        int expectedTypes = 1;
        long expectedTimestamp = timeStamp;

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
                "aPackageHasNoName");
@@ -410,16 +410,16 @@ public class FgsLoggerTest {
        timeStamp = mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1);
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
        expectedTimestamp[0] = timeStamp;
        expectedTimestamp = timeStamp;
        verify(mFgsLogger, times(1))
                .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
    }

    @Test
    public void testMultipleUid() throws InterruptedException {
        int[] expectedTypes = {1};
        int expectedTypes = 1;
        ServiceRecord record = ServiceRecord.newEmptyInstanceForTest(null);
        record.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
        ActivityManagerService ams = mock(ActivityManagerService.class);
@@ -477,7 +477,7 @@ public class FgsLoggerTest {
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes), any(long[].class));
                        eq(expectedTypes), anyLong());
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
                "aPackageHasNoName");
@@ -511,16 +511,16 @@ public class FgsLoggerTest {
        mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 2, 1);
        timeStamp2 = mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA,
                2, 1);
        long[] expectedTimestamp = {timeStamp};
        long[] expectedTimestamp2 = {timeStamp2};
        long expectedTimestamp = timeStamp;
        long expectedTimestamp2 = timeStamp2;
        verify(mFgsLogger, times(1))
                .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        verify(mFgsLogger, times(1))
                .logFgsApiEventWithNoFgs(eq(2), eq(FGS_API_END_WITHOUT_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp2));
                        eq(expectedTypes),
                        eq(expectedTimestamp2));
    }

    @Test
@@ -551,15 +551,15 @@ public class FgsLoggerTest {
        // now we should see exactly one call logged
        // and this should be the very first call
        // we also try to verify the time as being the very first call
        int[] expectedTypes = {1};
        long[] expectedTimestamp = {timeStamp};
        int expectedTypes = 1;
        long expectedTimestamp = timeStamp;

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        reset(mFgsLogger);
        mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
                "aPackageHasNoName");
@@ -590,13 +590,13 @@ public class FgsLoggerTest {
        // now we do multiple stops
        // only the last one should be logged
        mFgsLogger.logForegroundServiceStop(1, record);
        expectedTimestamp[0] = timeStamp;
        expectedTimestamp = timeStamp;
        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_END_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
    }

    @Test
@@ -610,16 +610,25 @@ public class FgsLoggerTest {
        long timestamp2 = mFgsLogger.logForegroundServiceApiEventBegin(
                FOREGROUND_SERVICE_API_TYPE_MICROPHONE,
                1, 1, "aPackageHasNoName");
        int[] expectedTypes = {1, FOREGROUND_SERVICE_API_TYPE_MICROPHONE};
        long[] expectedTimestamp = {timestamp1, timestamp2};
        int expectedTypes = 1;
        int expectedType2 = FOREGROUND_SERVICE_API_TYPE_MICROPHONE;
        long expectedTimestamp = timestamp1;
        long expectedTimestamp2 = timestamp2;
        mFgsLogger.logForegroundServiceStart(1, 1, record);

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_BEGIN_WITH_FGS),
                        eq(expectedType2),
                        eq(expectedTimestamp2));

        reset(mFgsLogger);
        resetAndVerifyZeroInteractions();
@@ -632,28 +641,34 @@ public class FgsLoggerTest {

        mFgsLogger.logForegroundServiceStop(1, record);

        expectedTimestamp[0] = timestamp1;
        expectedTimestamp[1] = timestamp2;
        expectedTimestamp = timestamp1;
        expectedTimestamp2 = timestamp2;

        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_END_WITH_FGS),
                        AdditionalMatchers.aryEq(expectedTypes),
                        AdditionalMatchers.aryEq(expectedTimestamp));
                        eq(expectedTypes),
                        eq(expectedTimestamp));
        verify(mFgsLogger, times(1))
                .logFgsApiEvent(any(ServiceRecord.class),
                        eq(FGS_STATE_CHANGED_API_CALL),
                        eq(FGS_API_END_WITH_FGS),
                        eq(expectedType2),
                        eq(expectedTimestamp2));

    }

    private void resetAndVerifyZeroInteractions() {
        doNothing().when(mFgsLogger)
                .logFgsApiEvent(any(ServiceRecord.class),
                        anyInt(), anyInt(), any(int[].class), any(long[].class));
                        anyInt(), anyInt(), anyInt(), anyLong());
        doNothing().when(mFgsLogger)
                .logFgsApiEventWithNoFgs(anyInt(), anyInt(), any(int[].class), any(long[].class));
                .logFgsApiEventWithNoFgs(anyInt(), anyInt(), anyInt(), anyLong());
        verify(mFgsLogger, times(0))
                .logFgsApiEvent(any(ServiceRecord.class),
                        anyInt(), anyInt(), any(int[].class), any(long[].class));
                        anyInt(), anyInt(), anyInt(), anyLong());
        verify(mFgsLogger, times(0))
                .logFgsApiEventWithNoFgs(anyInt(), anyInt(), any(int[].class), any(long[].class));
                .logFgsApiEventWithNoFgs(anyInt(), anyInt(), anyInt(), anyLong());
    }
}