Merge "Updating foreground service type logger to log the duration of APIs and adding additional logging of FGS starts." into udc-dev am: 2537e16492

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23121783

Change-Id: If823a0d5c54ca1351e34194eb36576567dec020f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Kunal Malhotra
2023-05-16 23:57:01 +00:00
committed by Automerger Merge Worker
3 changed files with 131 additions and 99 deletions

View File

@@ -8253,12 +8253,14 @@ public final class ActiveServices {
r.mFgsDelegation != null ? r.mFgsDelegation.mOptions.mDelegationService r.mFgsDelegation != null ? r.mFgsDelegation.mOptions.mDelegationService
: ForegroundServiceDelegationOptions.DELEGATION_SERVICE_DEFAULT, : ForegroundServiceDelegationOptions.DELEGATION_SERVICE_DEFAULT,
0 /* api_sate */, 0 /* api_sate */,
null /* api_type */, 0 /* api_type */,
null /* api_timestamp */, 0 /* api_timestamp */,
mAm.getUidStateLocked(r.appInfo.uid), mAm.getUidStateLocked(r.appInfo.uid),
mAm.getUidProcessCapabilityLocked(r.appInfo.uid), mAm.getUidProcessCapabilityLocked(r.appInfo.uid),
mAm.getUidStateLocked(r.mRecentCallingUid), mAm.getUidStateLocked(r.mRecentCallingUid),
mAm.getUidProcessCapabilityLocked(r.mRecentCallingUid)); mAm.getUidProcessCapabilityLocked(r.mRecentCallingUid),
0,
0);
int event = 0; int event = 0;
if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) { if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
@@ -8433,6 +8435,9 @@ public final class ActiveServices {
true, false, null, false, true, false, null, false,
AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
registerAppOpCallbackLocked(r); registerAppOpCallbackLocked(r);
synchronized (mFGSLogger) {
mFGSLogger.logForegroundServiceStart(r.appInfo.uid, 0, r);
}
logFGSStateChangeLocked(r, logFGSStateChangeLocked(r,
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER, FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN); 0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);

View File

@@ -105,6 +105,11 @@ public class ForegroundServiceTypeLoggerModule {
// to another ordered map, keyed by the component name // to another ordered map, keyed by the component name
// to facilitate removing the record from the structure // to facilitate removing the record from the structure
final SparseArray<ArrayMap<ComponentName, ServiceRecord>> mRunningFgs = new SparseArray<>(); 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 // SparseArray that tracks all UIDs that have made various
@@ -167,17 +172,13 @@ public class ForegroundServiceTypeLoggerModule {
} }
if (!apiTypesFound.isEmpty()) { if (!apiTypesFound.isEmpty()) {
// log a state change // 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++) { for (int i = 0, size = apiTypesFound.size(); i < size; i++) {
types[i] = apiTypesFound.get(i); logFgsApiEvent(record,
timestamps[i] = timestampsFound.get(i); FGS_STATE_CHANGED_API_CALL,
FGS_API_BEGIN_WITH_FGS,
apiTypesFound.get(i),
timestampsFound.get(i));
} }
logFgsApiEvent(record,
FGS_STATE_CHANGED_API_CALL,
FGS_API_BEGIN_WITH_FGS,
types,
timestamps);
} }
} }
@@ -192,7 +193,7 @@ public class ForegroundServiceTypeLoggerModule {
final ArrayList<Integer> apiTypes = convertFgsTypeToApiTypes(record.foregroundServiceType); final ArrayList<Integer> apiTypes = convertFgsTypeToApiTypes(record.foregroundServiceType);
final UidState uidState = mUids.get(uid); final UidState uidState = mUids.get(uid);
if (uidState == null) { 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 + uid
+ " in package " + record.packageName); + " in package " + record.packageName);
return; return;
@@ -202,7 +203,7 @@ public class ForegroundServiceTypeLoggerModule {
for (int i = 0, size = apiTypes.size(); i < size; i++) { for (int i = 0, size = apiTypes.size(); i < size; i++) {
final int apiType = apiTypes.get(i); final int apiType = apiTypes.get(i);
if (!uidState.mOpenWithFgsCount.contains(apiType)) { 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); + " in package " + record.packageName);
continue; continue;
} }
@@ -231,19 +232,17 @@ public class ForegroundServiceTypeLoggerModule {
if (runningFgsOfType.size() == 0) { if (runningFgsOfType.size() == 0) {
// there's no more FGS running for this type, just get rid of it // there's no more FGS running for this type, just get rid of it
uidState.mRunningFgs.remove(apiType); 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()) { if (!apisFound.isEmpty()) {
// time to log the call // 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++) { for (int i = 0; i < apisFound.size(); i++) {
types[i] = apisFound.get(i); logFgsApiEvent(record,
timestamps[i] = timestampsFound.get(i); FGS_STATE_CHANGED_API_CALL,
FGS_API_END_WITH_FGS, apisFound.get(i), timestampsFound.get(i));
} }
logFgsApiEvent(record,
FGS_STATE_CHANGED_API_CALL,
FGS_API_END_WITH_FGS, types, timestamps);
} }
} }
@@ -303,8 +302,8 @@ public class ForegroundServiceTypeLoggerModule {
final ArrayMap<ComponentName, ServiceRecord> fgsListMap = uidState.mRunningFgs.get(apiType); final ArrayMap<ComponentName, ServiceRecord> fgsListMap = uidState.mRunningFgs.get(apiType);
// now we get the relevant FGS to log with // now we get the relevant FGS to log with
final int[] apiTypes = {apiType}; final int apiTypes = apiType;
final long[] timestamps = {callStart.mTimeStart}; final long timestamps = callStart.mTimeStart;
if (uidState.mOpenWithFgsCount.valueAt(openWithFgsIndex) == 1) { if (uidState.mOpenWithFgsCount.valueAt(openWithFgsIndex) == 1) {
for (ServiceRecord record : fgsListMap.values()) { for (ServiceRecord record : fgsListMap.values()) {
logFgsApiEvent(record, logFgsApiEvent(record,
@@ -347,13 +346,13 @@ public class ForegroundServiceTypeLoggerModule {
// we just log that an event happened w/ no // we just log that an event happened w/ no
// FGS associated. This is to avoid dangling // FGS associated. This is to avoid dangling
// events // events
final long[] timestamp = {System.currentTimeMillis()}; final long timestamp = System.currentTimeMillis();
final int[] apiTypes = {apiType}; final int apiTypes = apiType;
logFgsApiEventWithNoFgs(uid, FGS_API_END_WITHOUT_FGS, apiTypes, timestamp); logFgsApiEventWithNoFgs(uid, FGS_API_END_WITHOUT_FGS, apiTypes, timestamp);
// we should now remove the count, so as to signal that // we should now remove the count, so as to signal that
// there was never an FGS called that can be associated // there was never an FGS called that can be associated
uidState.mOpenWithFgsCount.remove(apiType); uidState.mOpenWithFgsCount.remove(apiType);
return timestamp[0]; return timestamp;
} }
} }
// we know now that this call is not coming from an // we know now that this call is not coming from an
@@ -392,8 +391,8 @@ public class ForegroundServiceTypeLoggerModule {
return; return;
} }
final ArrayMap<ComponentName, ServiceRecord> fgsRecords = uidState.mRunningFgs.get(apiType); final ArrayMap<ComponentName, ServiceRecord> fgsRecords = uidState.mRunningFgs.get(apiType);
final int[] apiTypes = {apiType}; final int apiTypes = apiType;
final long[] timestamp = {System.currentTimeMillis()}; final long timestamp = System.currentTimeMillis();
for (ServiceRecord record : fgsRecords.values()) { for (ServiceRecord record : fgsRecords.values()) {
logFgsApiEvent(record, logFgsApiEvent(record,
FGS_STATE_CHANGED_API_CALL, FGS_STATE_CHANGED_API_CALL,
@@ -449,7 +448,9 @@ public class ForegroundServiceTypeLoggerModule {
@VisibleForTesting @VisibleForTesting
public void logFgsApiEvent(ServiceRecord r, int fgsState, public void logFgsApiEvent(ServiceRecord r, int fgsState,
@FgsApiState int apiState, @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, FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid, r.appInfo.uid,
r.shortInstanceName, r.shortInstanceName,
@@ -479,7 +480,9 @@ public class ForegroundServiceTypeLoggerModule {
ActivityManager.PROCESS_STATE_UNKNOWN, ActivityManager.PROCESS_STATE_UNKNOWN,
ActivityManager.PROCESS_CAPABILITY_NONE, ActivityManager.PROCESS_CAPABILITY_NONE,
ActivityManager.PROCESS_STATE_UNKNOWN, ActivityManager.PROCESS_STATE_UNKNOWN,
ActivityManager.PROCESS_CAPABILITY_NONE); ActivityManager.PROCESS_CAPABILITY_NONE,
apiDurationBeforeFgsStart,
apiDurationAfterFgsEnd);
} }
/** /**
@@ -489,7 +492,14 @@ public class ForegroundServiceTypeLoggerModule {
@VisibleForTesting @VisibleForTesting
public void logFgsApiEventWithNoFgs(int uid, public void logFgsApiEventWithNoFgs(int uid,
@FgsApiState int apiState, @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, FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
uid, uid,
null, null,
@@ -517,7 +527,9 @@ public class ForegroundServiceTypeLoggerModule {
ActivityManager.PROCESS_STATE_UNKNOWN, ActivityManager.PROCESS_STATE_UNKNOWN,
ActivityManager.PROCESS_CAPABILITY_NONE, ActivityManager.PROCESS_CAPABILITY_NONE,
ActivityManager.PROCESS_STATE_UNKNOWN, ActivityManager.PROCESS_STATE_UNKNOWN,
ActivityManager.PROCESS_CAPABILITY_NONE); ActivityManager.PROCESS_CAPABILITY_NONE,
0,
apiDurationAfterFgsEnd);
} }
/** /**

View File

@@ -26,6 +26,7 @@ import static com.android.server.am.ForegroundServiceTypeLoggerModule.FGS_STATE_
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -41,7 +42,6 @@ import androidx.test.filters.SmallTest;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.AdditionalMatchers;
/** /**
* Test class for {@link ForegroundServiceTypeLoggerModule}. * Test class for {@link ForegroundServiceTypeLoggerModule}.
@@ -61,10 +61,10 @@ public class FgsLoggerTest {
mFgsLogger = spy(logger); mFgsLogger = spy(logger);
doNothing().when(mFgsLogger) doNothing().when(mFgsLogger)
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
anyInt(), anyInt(), any(int[].class), any(long[].class)); anyInt(), anyInt(), anyInt(), anyLong());
doNothing().when(mFgsLogger) doNothing().when(mFgsLogger)
.logFgsApiEventWithNoFgs(anyInt(), .logFgsApiEventWithNoFgs(anyInt(),
anyInt(), any(int[].class), any(long[].class)); anyInt(), anyInt(), anyLong());
} }
@Test @Test
@@ -73,10 +73,10 @@ public class FgsLoggerTest {
record.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; record.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
mFgsLogger.logForegroundServiceStart(1, 1, record); mFgsLogger.logForegroundServiceStart(1, 1, record);
mFgsLogger.logForegroundServiceApiEventBegin(1, 1, 1, "aPackageHasNoName"); mFgsLogger.logForegroundServiceApiEventBegin(1, 1, 1, "aPackageHasNoName");
int[] expectedTypes = {1}; int expectedTypes = 1;
verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class), verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1);
@@ -85,7 +85,7 @@ public class FgsLoggerTest {
mFgsLogger.logForegroundServiceStop(1, record); mFgsLogger.logForegroundServiceStop(1, record);
verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class), verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_END_WITH_FGS), eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_END_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
} }
@Test @Test
@@ -97,10 +97,10 @@ public class FgsLoggerTest {
resetAndVerifyZeroInteractions(); resetAndVerifyZeroInteractions();
mFgsLogger.logForegroundServiceStart(1, 1, record); mFgsLogger.logForegroundServiceStart(1, 1, record);
int[] expectedTypes = {1}; int expectedTypes = 1;
verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class), verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1);
@@ -109,7 +109,7 @@ public class FgsLoggerTest {
mFgsLogger.logForegroundServiceStop(1, record); mFgsLogger.logForegroundServiceStop(1, record);
verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class), verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_END_WITH_FGS), eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_END_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
} }
@Test @Test
@@ -122,12 +122,12 @@ public class FgsLoggerTest {
resetAndVerifyZeroInteractions(); resetAndVerifyZeroInteractions();
int[] expectedTypes = {1}; int expectedTypes = 1;
mFgsLogger.logForegroundServiceStart(1, 1, record); mFgsLogger.logForegroundServiceStart(1, 1, record);
verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class), verify(mFgsLogger).logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceStop(1, record); mFgsLogger.logForegroundServiceStop(1, record);
@@ -135,7 +135,7 @@ public class FgsLoggerTest {
mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
verify(mFgsLogger).logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS), verify(mFgsLogger).logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
} }
@Test @Test
@@ -176,15 +176,15 @@ public class FgsLoggerTest {
// now we should see exactly one call logged // now we should see exactly one call logged
// and this should be the very first call // and this should be the very first call
// we also try to verify the time as being the very first call // we also try to verify the time as being the very first call
int[] expectedTypes = {1}; int expectedTypes = 1;
long[] expectedTimestamp = {timeStamp}; long expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
reset(mFgsLogger); reset(mFgsLogger);
// now we do multiple stops // now we do multiple stops
// only the last one should be logged // only the last one should be logged
@@ -201,11 +201,11 @@ public class FgsLoggerTest {
mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1);
timeStamp = mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, timeStamp = mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA,
1, 1); 1, 1);
expectedTimestamp[0] = timeStamp; expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS), .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
} }
@Test @Test
@@ -239,15 +239,15 @@ public class FgsLoggerTest {
// now we should see exactly one call logged // now we should see exactly one call logged
// and this should be the very first call // and this should be the very first call
// we also try to verify the time as being the very first call // we also try to verify the time as being the very first call
int[] expectedTypes = {1}; int expectedTypes = 1;
long[] expectedTimestamp = {timeStamp}; long expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
reset(mFgsLogger); reset(mFgsLogger);
// now we do multiple stops // now we do multiple stops
// only the last one should be logged // only the last one should be logged
@@ -269,11 +269,11 @@ public class FgsLoggerTest {
1, 1); 1, 1);
mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 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)) verify(mFgsLogger, times(1))
.logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS), .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
} }
@Test @Test
@@ -304,15 +304,15 @@ public class FgsLoggerTest {
// now we should see exactly one call logged // now we should see exactly one call logged
// and this should be the very first call // and this should be the very first call
// we also try to verify the time as being the very first call // we also try to verify the time as being the very first call
int[] expectedTypes = {1}; int expectedTypes = 1;
long[] expectedTimestamp = {timeStamp}; long expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1, mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
"aPackageHasNoName"); "aPackageHasNoName");
@@ -338,11 +338,11 @@ public class FgsLoggerTest {
1, 1); 1, 1);
mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 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)) verify(mFgsLogger, times(1))
.logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS), .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
} }
@Test @Test
@@ -375,15 +375,15 @@ public class FgsLoggerTest {
// now we should see exactly one call logged // now we should see exactly one call logged
// and this should be the very first call // and this should be the very first call
// we also try to verify the time as being the very first call // we also try to verify the time as being the very first call
int[] expectedTypes = {1}; int expectedTypes = 1;
long[] expectedTimestamp = {timeStamp}; long expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1, mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
"aPackageHasNoName"); "aPackageHasNoName");
@@ -410,16 +410,16 @@ public class FgsLoggerTest {
timeStamp = mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1); timeStamp = mFgsLogger.logForegroundServiceApiEventEnd(1, 1, 1);
mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1); mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 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)) verify(mFgsLogger, times(1))
.logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS), .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
} }
@Test @Test
public void testMultipleUid() throws InterruptedException { public void testMultipleUid() throws InterruptedException {
int[] expectedTypes = {1}; int expectedTypes = 1;
ServiceRecord record = ServiceRecord.newEmptyInstanceForTest(null); ServiceRecord record = ServiceRecord.newEmptyInstanceForTest(null);
record.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; record.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
ActivityManagerService ams = mock(ActivityManagerService.class); ActivityManagerService ams = mock(ActivityManagerService.class);
@@ -477,7 +477,7 @@ public class FgsLoggerTest {
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), any(long[].class)); eq(expectedTypes), anyLong());
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1, mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
"aPackageHasNoName"); "aPackageHasNoName");
@@ -511,16 +511,16 @@ public class FgsLoggerTest {
mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 2, 1); mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, 2, 1);
timeStamp2 = mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA, timeStamp2 = mFgsLogger.logForegroundServiceApiEventEnd(FOREGROUND_SERVICE_API_TYPE_CAMERA,
2, 1); 2, 1);
long[] expectedTimestamp = {timeStamp}; long expectedTimestamp = timeStamp;
long[] expectedTimestamp2 = {timeStamp2}; long expectedTimestamp2 = timeStamp2;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS), .logFgsApiEventWithNoFgs(eq(1), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEventWithNoFgs(eq(2), eq(FGS_API_END_WITHOUT_FGS), .logFgsApiEventWithNoFgs(eq(2), eq(FGS_API_END_WITHOUT_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp2)); eq(expectedTimestamp2));
} }
@Test @Test
@@ -551,15 +551,15 @@ public class FgsLoggerTest {
// now we should see exactly one call logged // now we should see exactly one call logged
// and this should be the very first call // and this should be the very first call
// we also try to verify the time as being the very first call // we also try to verify the time as being the very first call
int[] expectedTypes = {1}; int expectedTypes = 1;
long[] expectedTimestamp = {timeStamp}; long expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
reset(mFgsLogger); reset(mFgsLogger);
mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1, mFgsLogger.logForegroundServiceApiEventBegin(FOREGROUND_SERVICE_API_TYPE_CAMERA, 1, 1,
"aPackageHasNoName"); "aPackageHasNoName");
@@ -590,13 +590,13 @@ public class FgsLoggerTest {
// now we do multiple stops // now we do multiple stops
// only the last one should be logged // only the last one should be logged
mFgsLogger.logForegroundServiceStop(1, record); mFgsLogger.logForegroundServiceStop(1, record);
expectedTimestamp[0] = timeStamp; expectedTimestamp = timeStamp;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_END_WITH_FGS), eq(FGS_API_END_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); eq(expectedTimestamp));
} }
@Test @Test
@@ -610,16 +610,25 @@ public class FgsLoggerTest {
long timestamp2 = mFgsLogger.logForegroundServiceApiEventBegin( long timestamp2 = mFgsLogger.logForegroundServiceApiEventBegin(
FOREGROUND_SERVICE_API_TYPE_MICROPHONE, FOREGROUND_SERVICE_API_TYPE_MICROPHONE,
1, 1, "aPackageHasNoName"); 1, 1, "aPackageHasNoName");
int[] expectedTypes = {1, FOREGROUND_SERVICE_API_TYPE_MICROPHONE}; int expectedTypes = 1;
long[] expectedTimestamp = {timestamp1, timestamp2}; int expectedType2 = FOREGROUND_SERVICE_API_TYPE_MICROPHONE;
long expectedTimestamp = timestamp1;
long expectedTimestamp2 = timestamp2;
mFgsLogger.logForegroundServiceStart(1, 1, record); mFgsLogger.logForegroundServiceStart(1, 1, record);
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_BEGIN_WITH_FGS), eq(FGS_API_BEGIN_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); 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); reset(mFgsLogger);
resetAndVerifyZeroInteractions(); resetAndVerifyZeroInteractions();
@@ -632,28 +641,34 @@ public class FgsLoggerTest {
mFgsLogger.logForegroundServiceStop(1, record); mFgsLogger.logForegroundServiceStop(1, record);
expectedTimestamp[0] = timestamp1; expectedTimestamp = timestamp1;
expectedTimestamp[1] = timestamp2; expectedTimestamp2 = timestamp2;
verify(mFgsLogger, times(1)) verify(mFgsLogger, times(1))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
eq(FGS_STATE_CHANGED_API_CALL), eq(FGS_STATE_CHANGED_API_CALL),
eq(FGS_API_END_WITH_FGS), eq(FGS_API_END_WITH_FGS),
AdditionalMatchers.aryEq(expectedTypes), eq(expectedTypes),
AdditionalMatchers.aryEq(expectedTimestamp)); 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() { private void resetAndVerifyZeroInteractions() {
doNothing().when(mFgsLogger) doNothing().when(mFgsLogger)
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
anyInt(), anyInt(), any(int[].class), any(long[].class)); anyInt(), anyInt(), anyInt(), anyLong());
doNothing().when(mFgsLogger) doNothing().when(mFgsLogger)
.logFgsApiEventWithNoFgs(anyInt(), anyInt(), any(int[].class), any(long[].class)); .logFgsApiEventWithNoFgs(anyInt(), anyInt(), anyInt(), anyLong());
verify(mFgsLogger, times(0)) verify(mFgsLogger, times(0))
.logFgsApiEvent(any(ServiceRecord.class), .logFgsApiEvent(any(ServiceRecord.class),
anyInt(), anyInt(), any(int[].class), any(long[].class)); anyInt(), anyInt(), anyInt(), anyLong());
verify(mFgsLogger, times(0)) verify(mFgsLogger, times(0))
.logFgsApiEventWithNoFgs(anyInt(), anyInt(), any(int[].class), any(long[].class)); .logFgsApiEventWithNoFgs(anyInt(), anyInt(), anyInt(), anyLong());
} }
} }