Add filtering and aggregate stats to log

Store and dump some aggregate stats in the location event log, and add
the ability to filter dumpsys output by provider.

Bug: 179416865
Bug: 174260507
Test: manual
Change-Id: I8ce8c2fb2526e9ef7cdd4b231db32124d62b8608
This commit is contained in:
Soonil Nagarkar
2021-02-05 10:57:29 -08:00
parent f6b292cc0f
commit ce0260e28b
12 changed files with 373 additions and 160 deletions

View File

@@ -79,6 +79,7 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.stats.location.LocationStatsEnums;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -87,6 +88,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.location.eventlog.LocationEventLog;
import com.android.server.location.geofence.GeofenceManager;
import com.android.server.location.geofence.GeofenceProxy;
import com.android.server.location.gnss.GnssConfiguration;
@@ -98,7 +100,6 @@ import com.android.server.location.injector.AppOpsHelper;
import com.android.server.location.injector.EmergencyHelper;
import com.android.server.location.injector.Injector;
import com.android.server.location.injector.LocationAttributionHelper;
import com.android.server.location.injector.LocationEventLog;
import com.android.server.location.injector.LocationPermissionsHelper;
import com.android.server.location.injector.LocationPowerSaveModeHelper;
import com.android.server.location.injector.LocationUsageLogger;
@@ -147,9 +148,10 @@ public class LocationManagerService extends ILocationManager.Stub {
public Lifecycle(Context context) {
super(context);
LocationEventLog eventLog = new LocationEventLog();
mUserInfoHelper = new LifecycleUserInfoHelper(context);
mSystemInjector = new SystemInjector(context, mUserInfoHelper);
mService = new LocationManagerService(context, mSystemInjector);
mSystemInjector = new SystemInjector(context, mUserInfoHelper, eventLog);
mService = new LocationManagerService(context, mSystemInjector, eventLog);
}
@Override
@@ -159,7 +161,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// client caching behavior is only enabled after seeing the first invalidate
LocationManager.invalidateLocalLocationEnabledCaches();
// disable caching for our own process
Objects.requireNonNull(mService.mContext.getSystemService(LocationManager.class))
Objects.requireNonNull(getContext().getSystemService(LocationManager.class))
.disableLocalLocationEnabledCaches();
}
@@ -221,6 +223,7 @@ public class LocationManagerService extends ILocationManager.Stub {
private final Context mContext;
private final Injector mInjector;
private final LocationEventLog mEventLog;
private final LocalService mLocalService;
private final GeofenceManager mGeofenceManager;
@@ -245,10 +248,10 @@ public class LocationManagerService extends ILocationManager.Stub {
private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
new CopyOnWriteArrayList<>();
LocationManagerService(Context context, Injector injector) {
LocationManagerService(Context context, Injector injector, LocationEventLog eventLog) {
mContext = context.createAttributionContext(ATTRIBUTION_TAG);
mInjector = injector;
mEventLog = eventLog;
mLocalService = new LocalService();
LocalServices.addService(LocationManagerInternal.class, mLocalService);
@@ -256,7 +259,7 @@ public class LocationManagerService extends ILocationManager.Stub {
// set up passive provider first since it will be required for all other location providers,
// which are loaded later once the system is ready.
mPassiveManager = new PassiveLocationProviderManager(mContext, injector);
mPassiveManager = new PassiveLocationProviderManager(mContext, injector, mEventLog);
addLocationProviderManager(mPassiveManager, new PassiveLocationProvider(mContext));
// TODO: load the gps provider here as well, which will require refactoring
@@ -297,7 +300,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
LocationProviderManager manager = new LocationProviderManager(mContext, mInjector,
providerName, mPassiveManager);
mEventLog, providerName, mPassiveManager);
addLocationProviderManager(manager, null);
return manager;
}
@@ -341,7 +344,7 @@ public class LocationManagerService extends ILocationManager.Stub {
com.android.internal.R.string.config_networkLocationProviderPackageName);
if (networkProvider != null) {
LocationProviderManager networkManager = new LocationProviderManager(mContext,
mInjector, NETWORK_PROVIDER, mPassiveManager);
mInjector, mEventLog, NETWORK_PROVIDER, mPassiveManager);
addLocationProviderManager(networkManager, networkProvider);
} else {
Log.w(TAG, "no network location provider found");
@@ -360,7 +363,7 @@ public class LocationManagerService extends ILocationManager.Stub {
com.android.internal.R.string.config_fusedLocationProviderPackageName);
if (fusedProvider != null) {
LocationProviderManager fusedManager = new LocationProviderManager(mContext, mInjector,
FUSED_PROVIDER, mPassiveManager);
mEventLog, FUSED_PROVIDER, mPassiveManager);
addLocationProviderManager(fusedManager, fusedProvider);
} else {
Log.wtf(TAG, "no fused location provider found");
@@ -375,7 +378,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mGnssManagerService.onSystemReady();
LocationProviderManager gnssManager = new LocationProviderManager(mContext, mInjector,
GPS_PROVIDER, mPassiveManager);
mEventLog, GPS_PROVIDER, mPassiveManager);
addLocationProviderManager(gnssManager, mGnssManagerService.getGnssLocationProvider());
}
@@ -431,7 +434,7 @@ public class LocationManagerService extends ILocationManager.Stub {
Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
}
mInjector.getLocationEventLog().logLocationEnabled(userId, enabled);
mEventLog.logLocationEnabled(userId, enabled);
Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
@@ -1193,9 +1196,27 @@ public class LocationManagerService extends ILocationManager.Stub {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
mGnssManagerService.dump(fd, ipw, args);
return;
if (args.length > 0) {
LocationProviderManager manager = getLocationProviderManager(args[0]);
if (manager != null) {
ipw.println("Provider:");
ipw.increaseIndent();
manager.dump(fd, ipw, args);
ipw.decreaseIndent();
ipw.println("Event Log:");
ipw.increaseIndent();
mEventLog.iterate(manager.getName(), ipw::println);
ipw.decreaseIndent();
return;
}
if ("--gnssmetrics".equals(args[0])) {
if (mGnssManagerService != null) {
mGnssManagerService.dump(fd, ipw, args);
}
return;
}
}
ipw.println("Location Manager State:");
@@ -1227,6 +1248,25 @@ public class LocationManagerService extends ILocationManager.Stub {
}
ipw.decreaseIndent();
ipw.println("Historical Aggregate Location Provider Data:");
ipw.increaseIndent();
ArrayMap<String, ArrayMap<String, LocationEventLog.AggregateStats>> aggregateStats =
mEventLog.copyAggregateStats();
for (int i = 0; i < aggregateStats.size(); i++) {
ipw.println(aggregateStats.keyAt(i));
ipw.increaseIndent();
ArrayMap<String, LocationEventLog.AggregateStats> providerStats =
aggregateStats.valueAt(i);
for (int j = 0; j < providerStats.size(); j++) {
ipw.print(providerStats.keyAt(j));
ipw.print(": ");
providerStats.valueAt(j).updateTotals();
ipw.println(providerStats.valueAt(j));
}
ipw.decreaseIndent();
}
ipw.decreaseIndent();
if (mGnssManagerService != null) {
ipw.println("GNSS Manager:");
ipw.increaseIndent();
@@ -1241,7 +1281,7 @@ public class LocationManagerService extends ILocationManager.Stub {
ipw.println("Event Log:");
ipw.increaseIndent();
mInjector.getLocationEventLog().iterate(ipw::println);
mEventLog.iterate(ipw::println);
ipw.decreaseIndent();
}
@@ -1320,7 +1360,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private final Context mContext;
private final UserInfoHelper mUserInfoHelper;
private final LocationEventLog mLocationEventLog;
private final AlarmHelper mAlarmHelper;
private final SystemAppOpsHelper mAppOpsHelper;
private final SystemLocationPermissionsHelper mLocationPermissionsHelper;
@@ -1339,19 +1378,17 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("this")
private boolean mSystemReady;
SystemInjector(Context context, UserInfoHelper userInfoHelper) {
SystemInjector(Context context, UserInfoHelper userInfoHelper, LocationEventLog eventLog) {
mContext = context;
mUserInfoHelper = userInfoHelper;
mLocationEventLog = new LocationEventLog();
mAlarmHelper = new SystemAlarmHelper(context);
mAppOpsHelper = new SystemAppOpsHelper(context);
mLocationPermissionsHelper = new SystemLocationPermissionsHelper(context,
mAppOpsHelper);
mSettingsHelper = new SystemSettingsHelper(context);
mAppForegroundHelper = new SystemAppForegroundHelper(context);
mLocationPowerSaveModeHelper = new SystemLocationPowerSaveModeHelper(context,
mLocationEventLog);
mLocationPowerSaveModeHelper = new SystemLocationPowerSaveModeHelper(context, eventLog);
mScreenInteractiveHelper = new SystemScreenInteractiveHelper(context);
mLocationAttributionHelper = new LocationAttributionHelper(mAppOpsHelper);
mLocationUsageLogger = new LocationUsageLogger();
@@ -1429,11 +1466,6 @@ public class LocationManagerService extends ILocationManager.Stub {
return mEmergencyCallHelper;
}
@Override
public LocationEventLog getLocationEventLog() {
return mLocationEventLog;
}
@Override
public LocationUsageLogger getLocationUsageLogger() {
return mLocationUsageLogger;

View File

@@ -16,12 +16,13 @@
package com.android.server.location.eventlog;
import android.annotation.Nullable;
import android.os.SystemClock;
import android.util.TimeUtils;
import com.android.internal.util.Preconditions;
import java.util.ListIterator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
@@ -35,6 +36,7 @@ public abstract class LocalEventLog {
boolean isFiller();
long getTimeDeltaMs();
String getLogString();
boolean filter(@Nullable String filter);
}
private static final class FillerEvent implements Log {
@@ -62,6 +64,11 @@ public abstract class LocalEventLog {
public String getLogString() {
throw new AssertionError();
}
@Override
public boolean filter(String filter) {
return false;
}
}
/**
@@ -87,6 +94,11 @@ public abstract class LocalEventLog {
public final long getTimeDeltaMs() {
return Integer.toUnsignedLong(mTimeDelta);
}
@Override
public boolean filter(String filter) {
return false;
}
}
// circular buffer of log entries
@@ -198,6 +210,17 @@ public abstract class LocalEventLog {
}
}
/**
* Iterates over the event log, passing each filter-matching log string to the given
* consumer.
*/
public synchronized void iterate(String filter, Consumer<String> consumer) {
LogIterator it = new LogIterator(filter);
while (it.hasNext()) {
consumer.accept(it.next());
}
}
// returns the index of the first element
private int startIndex() {
return wrapIndex(mLogEndIndex - mLogSize);
@@ -205,12 +228,13 @@ public abstract class LocalEventLog {
// returns the index after this one
private int incrementIndex(int index) {
return wrapIndex(index + 1);
}
// returns the index before this one
private int decrementIndex(int index) {
return wrapIndex(index - 1);
if (index == -1) {
return startIndex();
} else if (index >= 0) {
return wrapIndex(index + 1);
} else {
throw new IllegalArgumentException();
}
}
// rolls over the given index if necessary
@@ -219,7 +243,9 @@ public abstract class LocalEventLog {
return (index % mLog.length + mLog.length) % mLog.length;
}
private class LogIterator implements ListIterator<String> {
private class LogIterator implements Iterator<String> {
private final @Nullable String mFilter;
private final long mSystemTimeDeltaMs;
@@ -228,10 +254,17 @@ public abstract class LocalEventLog {
private int mCount;
LogIterator() {
this(null);
}
LogIterator(@Nullable String filter) {
mFilter = filter;
mSystemTimeDeltaMs = System.currentTimeMillis() - SystemClock.elapsedRealtime();
mCurrentRealtimeMs = mStartRealtimeMs;
mIndex = startIndex();
mCount = 0;
mIndex = -1;
mCount = -1;
increment();
}
@Override
@@ -239,75 +272,17 @@ public abstract class LocalEventLog {
return mCount < mLogSize;
}
@Override
public boolean hasPrevious() {
return mCount > 0;
}
@Override
// return then increment
public String next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Log log = mLog[mIndex];
long nextDeltaMs = log.getTimeDeltaMs();
long realtimeMs = mCurrentRealtimeMs + nextDeltaMs;
long timeMs = mCurrentRealtimeMs + log.getTimeDeltaMs() + mSystemTimeDeltaMs;
// calculate next index, skipping filler events
do {
mCurrentRealtimeMs += nextDeltaMs;
mIndex = incrementIndex(mIndex);
if (++mCount < mLogSize) {
nextDeltaMs = mLog[mIndex].getTimeDeltaMs();
}
} while (mCount < mLogSize && mLog[mIndex].isFiller());
increment();
return getTimePrefix(realtimeMs + mSystemTimeDeltaMs) + log.getLogString();
}
@Override
// decrement then return
public String previous() {
Log log;
long currentDeltaMs;
long realtimeMs;
// calculate previous index, skipping filler events with MAX_TIME_DELTA
do {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
mIndex = decrementIndex(mIndex);
mCount--;
log = mLog[mIndex];
realtimeMs = mCurrentRealtimeMs;
if (mCount > 0) {
currentDeltaMs = log.getTimeDeltaMs();
mCurrentRealtimeMs -= currentDeltaMs;
}
} while (mCount >= 0 && log.isFiller());
return getTimePrefix(realtimeMs + mSystemTimeDeltaMs) + log.getLogString();
}
@Override
public int nextIndex() {
throw new UnsupportedOperationException();
}
@Override
public int previousIndex() {
throw new UnsupportedOperationException();
}
@Override
public void add(String s) {
throw new UnsupportedOperationException();
return getTimePrefix(timeMs) + log.getLogString();
}
@Override
@@ -315,9 +290,16 @@ public abstract class LocalEventLog {
throw new UnsupportedOperationException();
}
@Override
public void set(String s) {
throw new UnsupportedOperationException();
private void increment() {
long nextDeltaMs = mIndex == -1 ? 0 : mLog[mIndex].getTimeDeltaMs();
do {
mCurrentRealtimeMs += nextDeltaMs;
mIndex = incrementIndex(mIndex);
if (++mCount < mLogSize) {
nextDeltaMs = mLog[mIndex].getTimeDeltaMs();
}
} while (mCount < mLogSize && (mLog[mIndex].isFiller() || (mFilter != null
&& !mLog[mIndex].filter(mFilter))));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2021 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.
@@ -14,24 +14,32 @@
* limitations under the License.
*/
package com.android.server.location.injector;
package com.android.server.location.eventlog;
import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
import static android.os.PowerManager.LOCATION_MODE_NO_CHANGE;
import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static android.util.TimeUtils.formatDuration;
import static com.android.server.location.LocationManagerService.D;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.annotation.Nullable;
import android.location.LocationRequest;
import android.location.provider.ProviderRequest;
import android.location.util.identity.CallerIdentity;
import android.os.Build;
import android.os.PowerManager.LocationPowerSaveMode;
import android.os.SystemClock;
import android.util.ArrayMap;
import com.android.server.location.eventlog.LocalEventLog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
/** In memory event log for location events. */
public class LocationEventLog extends LocalEventLog {
@@ -54,8 +62,39 @@ public class LocationEventLog extends LocalEventLog {
private static final int EVENT_PROVIDER_DELIVER_LOCATION = 8;
private static final int EVENT_LOCATION_POWER_SAVE_MODE_CHANGE = 9;
@GuardedBy("mAggregateStats")
private final ArrayMap<String, ArrayMap<String, AggregateStats>> mAggregateStats;
public LocationEventLog() {
super(getLogSize());
mAggregateStats = new ArrayMap<>(4);
}
public ArrayMap<String, ArrayMap<String, AggregateStats>> copyAggregateStats() {
synchronized (mAggregateStats) {
ArrayMap<String, ArrayMap<String, AggregateStats>> copy = new ArrayMap<>(
mAggregateStats);
for (int i = 0; i < copy.size(); i++) {
copy.setValueAt(i, new ArrayMap<>(copy.valueAt(i)));
}
return copy;
}
}
private AggregateStats getAggregateStats(String provider, String packageName) {
synchronized (mAggregateStats) {
ArrayMap<String, AggregateStats> packageMap = mAggregateStats.get(provider);
if (packageMap == null) {
packageMap = new ArrayMap<>(2);
mAggregateStats.put(provider, packageMap);
}
AggregateStats stats = packageMap.get(packageName);
if (stats == null) {
stats = new AggregateStats();
packageMap.put(packageName, stats);
}
return stats;
}
}
/** Logs a location enabled/disabled event. */
@@ -77,12 +116,34 @@ public class LocationEventLog extends LocalEventLog {
public void logProviderClientRegistered(String provider, CallerIdentity identity,
LocationRequest request) {
addLogEvent(EVENT_PROVIDER_REGISTER_CLIENT, provider, identity, request);
getAggregateStats(provider, identity.getPackageName())
.markRequestAdded(request.getIntervalMillis());
}
/** Logs a client unregistration for a location provider. */
public void logProviderClientUnregistered(String provider,
CallerIdentity identity) {
public void logProviderClientUnregistered(String provider, CallerIdentity identity) {
addLogEvent(EVENT_PROVIDER_UNREGISTER_CLIENT, provider, identity);
getAggregateStats(provider, identity.getPackageName()).markRequestRemoved();
}
/** Logs a client for a location provider entering the active state. */
public void logProviderClientActive(String provider, CallerIdentity identity) {
getAggregateStats(provider, identity.getPackageName()).markRequestActive();
}
/** Logs a client for a location provider leaving the active state. */
public void logProviderClientInactive(String provider, CallerIdentity identity) {
getAggregateStats(provider, identity.getPackageName()).markRequestInactive();
}
/** Logs a client for a location provider entering the foreground state. */
public void logProviderClientForeground(String provider, CallerIdentity identity) {
getAggregateStats(provider, identity.getPackageName()).markRequestForeground();
}
/** Logs a client for a location provider leaving the foreground state. */
public void logProviderClientBackground(String provider, CallerIdentity identity) {
getAggregateStats(provider, identity.getPackageName()).markRequestBackground();
}
/** Logs a change to the provider request for a location provider. */
@@ -143,16 +204,29 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class ProviderEnabledEvent extends LogEvent {
private abstract static class ProviderEvent extends LogEvent {
protected final String mProvider;
protected ProviderEvent(long timeDelta, String provider) {
super(timeDelta);
mProvider = provider;
}
@Override
public boolean filter(String filter) {
return mProvider.equals(filter);
}
}
private static final class ProviderEnabledEvent extends ProviderEvent {
private final String mProvider;
private final int mUserId;
private final boolean mEnabled;
protected ProviderEnabledEvent(long timeDelta, String provider, int userId,
boolean enabled) {
super(timeDelta);
mProvider = provider;
super(timeDelta, provider);
mUserId = userId;
mEnabled = enabled;
}
@@ -164,14 +238,12 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class ProviderMockedEvent extends LogEvent {
private static final class ProviderMockedEvent extends ProviderEvent {
private final String mProvider;
private final boolean mMocked;
protected ProviderMockedEvent(long timeDelta, String provider, boolean mocked) {
super(timeDelta);
mProvider = provider;
super(timeDelta, provider);
mMocked = mocked;
}
@@ -185,17 +257,15 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class ProviderRegisterEvent extends LogEvent {
private static final class ProviderRegisterEvent extends ProviderEvent {
private final String mProvider;
private final boolean mRegistered;
private final CallerIdentity mIdentity;
@Nullable private final LocationRequest mLocationRequest;
private ProviderRegisterEvent(long timeDelta, String provider, boolean registered,
CallerIdentity identity, @Nullable LocationRequest locationRequest) {
super(timeDelta);
mProvider = provider;
super(timeDelta, provider);
mRegistered = registered;
mIdentity = identity;
mLocationRequest = locationRequest;
@@ -212,14 +282,12 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class ProviderUpdateEvent extends LogEvent {
private static final class ProviderUpdateEvent extends ProviderEvent {
private final String mProvider;
private final ProviderRequest mRequest;
private ProviderUpdateEvent(long timeDelta, String provider, ProviderRequest request) {
super(timeDelta);
mProvider = provider;
super(timeDelta, provider);
mRequest = request;
}
@@ -229,14 +297,12 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class ProviderReceiveLocationEvent extends LogEvent {
private static final class ProviderReceiveLocationEvent extends ProviderEvent {
private final String mProvider;
private final int mNumLocations;
private ProviderReceiveLocationEvent(long timeDelta, String provider, int numLocations) {
super(timeDelta);
mProvider = provider;
super(timeDelta, provider);
mNumLocations = numLocations;
}
@@ -246,16 +312,14 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class ProviderDeliverLocationEvent extends LogEvent {
private static final class ProviderDeliverLocationEvent extends ProviderEvent {
private final String mProvider;
private final int mNumLocations;
@Nullable private final CallerIdentity mIdentity;
private ProviderDeliverLocationEvent(long timeDelta, String provider, int numLocations,
@Nullable CallerIdentity identity) {
super(timeDelta);
mProvider = provider;
super(timeDelta, provider);
mNumLocations = numLocations;
mIdentity = identity;
}
@@ -267,7 +331,7 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class LocationPowerSaveModeEvent extends LogEvent {
private static final class LocationPowerSaveModeEvent extends LogEvent {
@LocationPowerSaveMode
private final int mLocationPowerSaveMode;
@@ -305,7 +369,7 @@ public class LocationEventLog extends LocalEventLog {
}
}
private static class LocationEnabledEvent extends LogEvent {
private static final class LocationEnabledEvent extends LogEvent {
private final int mUserId;
private final boolean mEnabled;
@@ -321,4 +385,118 @@ public class LocationEventLog extends LocalEventLog {
return "[u" + mUserId + "] location setting " + (mEnabled ? "enabled" : "disabled");
}
}
/**
* Aggregate statistics for a single package under a single provider.
*/
public static final class AggregateStats {
@GuardedBy("this")
private int mAddedRequestCount;
@GuardedBy("this")
private int mActiveRequestCount;
@GuardedBy("this")
private int mForegroundRequestCount;
@GuardedBy("this")
private long mFastestIntervalMs = Long.MAX_VALUE;
@GuardedBy("this")
private long mSlowestIntervalMs = 0;
@GuardedBy("this")
private long mAddedTimeTotalMs;
@GuardedBy("this")
private long mAddedTimeLastUpdateRealtimeMs;
@GuardedBy("this")
private long mActiveTimeTotalMs;
@GuardedBy("this")
private long mActiveTimeLastUpdateRealtimeMs;
@GuardedBy("this")
private long mForegroundTimeTotalMs;
@GuardedBy("this")
private long mForegroundTimeLastUpdateRealtimeMs;
AggregateStats() {}
synchronized void markRequestAdded(long intervalMillis) {
if (mAddedRequestCount++ == 0) {
mAddedTimeLastUpdateRealtimeMs = SystemClock.elapsedRealtime();
}
mFastestIntervalMs = min(intervalMillis, mFastestIntervalMs);
mSlowestIntervalMs = max(intervalMillis, mSlowestIntervalMs);
}
synchronized void markRequestRemoved() {
updateTotals();
--mAddedRequestCount;
Preconditions.checkState(mAddedRequestCount >= 0);
mActiveRequestCount = min(mAddedRequestCount, mActiveRequestCount);
mForegroundRequestCount = min(mAddedRequestCount, mForegroundRequestCount);
}
synchronized void markRequestActive() {
Preconditions.checkState(mAddedRequestCount > 0);
if (mActiveRequestCount++ == 0) {
mActiveTimeLastUpdateRealtimeMs = SystemClock.elapsedRealtime();
}
}
synchronized void markRequestInactive() {
updateTotals();
--mActiveRequestCount;
Preconditions.checkState(mActiveRequestCount >= 0);
}
synchronized void markRequestForeground() {
Preconditions.checkState(mAddedRequestCount > 0);
if (mForegroundRequestCount++ == 0) {
mForegroundTimeLastUpdateRealtimeMs = SystemClock.elapsedRealtime();
}
}
synchronized void markRequestBackground() {
updateTotals();
--mForegroundRequestCount;
Preconditions.checkState(mForegroundRequestCount >= 0);
}
public synchronized void updateTotals() {
if (mAddedRequestCount > 0) {
long realtimeMs = SystemClock.elapsedRealtime();
mAddedTimeTotalMs += realtimeMs - mAddedTimeLastUpdateRealtimeMs;
mAddedTimeLastUpdateRealtimeMs = realtimeMs;
}
if (mActiveRequestCount > 0) {
long realtimeMs = SystemClock.elapsedRealtime();
mActiveTimeTotalMs += realtimeMs - mActiveTimeLastUpdateRealtimeMs;
mActiveTimeLastUpdateRealtimeMs = realtimeMs;
}
if (mForegroundRequestCount > 0) {
long realtimeMs = SystemClock.elapsedRealtime();
mForegroundTimeTotalMs += realtimeMs - mForegroundTimeLastUpdateRealtimeMs;
mForegroundTimeLastUpdateRealtimeMs = realtimeMs;
}
}
@Override
public synchronized String toString() {
return "min/max interval = " + intervalToString(mFastestIntervalMs) + "/"
+ intervalToString(mSlowestIntervalMs)
+ ", total/active/foreground duration = " + formatDuration(mAddedTimeTotalMs)
+ "/" + formatDuration(mActiveTimeTotalMs) + "/"
+ formatDuration(mForegroundTimeTotalMs);
}
private static String intervalToString(long intervalMs) {
if (intervalMs == LocationRequest.PASSIVE_INTERVAL) {
return "passive";
} else {
return MILLISECONDS.toSeconds(intervalMs) + "s";
}
}
}
}

View File

@@ -56,7 +56,4 @@ public interface Injector {
/** Returns a LocationUsageLogger. */
LocationUsageLogger getLocationUsageLogger();
/** Returns a LocationEventLog. */
LocationEventLog getLocationEventLog();
}

View File

@@ -24,6 +24,8 @@ import static com.android.server.location.LocationManagerService.TAG;
import android.os.PowerManager.LocationPowerSaveMode;
import android.util.Log;
import com.android.server.location.eventlog.LocationEventLog;
import java.util.concurrent.CopyOnWriteArrayList;
/**

View File

@@ -25,6 +25,7 @@ import android.os.PowerSaveState;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.location.eventlog.LocationEventLog;
import java.util.Objects;
import java.util.function.Consumer;

View File

@@ -89,6 +89,7 @@ import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.location.LocationPermissions;
import com.android.server.location.LocationPermissions.PermissionLevel;
import com.android.server.location.eventlog.LocationEventLog;
import com.android.server.location.fudger.LocationFudger;
import com.android.server.location.injector.AlarmHelper;
import com.android.server.location.injector.AppForegroundHelper;
@@ -96,7 +97,6 @@ import com.android.server.location.injector.AppForegroundHelper.AppForegroundLis
import com.android.server.location.injector.AppOpsHelper;
import com.android.server.location.injector.Injector;
import com.android.server.location.injector.LocationAttributionHelper;
import com.android.server.location.injector.LocationEventLog;
import com.android.server.location.injector.LocationPermissionsHelper;
import com.android.server.location.injector.LocationPermissionsHelper.LocationPermissionsListener;
import com.android.server.location.injector.LocationPowerSaveModeHelper;
@@ -323,7 +323,7 @@ public class LocationProviderManager extends
+ getRequest());
}
mLocationEventLog.logProviderClientRegistered(mName, getIdentity(), super.getRequest());
mEventLog.logProviderClientRegistered(mName, getIdentity(), super.getRequest());
// initialization order is important as there are ordering dependencies
mPermitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel,
@@ -333,6 +333,10 @@ public class LocationProviderManager extends
mIsUsingHighPower = isUsingHighPower();
onProviderListenerRegister();
if (mForeground) {
mEventLog.logProviderClientForeground(mName, getIdentity());
}
}
@GuardedBy("mLock")
@@ -344,7 +348,7 @@ public class LocationProviderManager extends
onProviderListenerUnregister();
mLocationEventLog.logProviderClientUnregistered(mName, getIdentity());
mEventLog.logProviderClientUnregistered(mName, getIdentity());
if (D) {
Log.d(TAG, mName + " provider removed registration from " + getIdentity());
@@ -369,6 +373,8 @@ public class LocationProviderManager extends
Preconditions.checkState(Thread.holdsLock(mLock));
}
mEventLog.logProviderClientActive(mName, getIdentity());
if (!getRequest().isHiddenFromAppOps()) {
mLocationAttributionHelper.reportLocationStart(getIdentity(), getName(), getKey());
}
@@ -389,6 +395,8 @@ public class LocationProviderManager extends
}
onProviderListenerInactive();
mEventLog.logProviderClientInactive(mName, getIdentity());
}
/**
@@ -524,6 +532,12 @@ public class LocationProviderManager extends
mForeground = foreground;
if (mForeground) {
mEventLog.logProviderClientForeground(mName, getIdentity());
} else {
mEventLog.logProviderClientBackground(mName, getIdentity());
}
// note that onProviderLocationRequestChanged() is always called
return onProviderLocationRequestChanged()
|| mLocationPowerSaveModeHelper.getLocationPowerSaveMode()
@@ -855,7 +869,7 @@ public class LocationProviderManager extends
listener.deliverOnLocationChanged(deliverLocationResult,
mUseWakeLock ? mWakeLock::release : null);
mLocationEventLog.logProviderDeliveredLocations(mName, locationResult.size(),
mEventLog.logProviderDeliveredLocations(mName, locationResult.size(),
getIdentity());
}
@@ -1154,7 +1168,7 @@ public class LocationProviderManager extends
// we currently don't hold a wakelock for getCurrentLocation deliveries
listener.deliverOnLocationChanged(deliverLocationResult, null);
mLocationEventLog.logProviderDeliveredLocations(mName,
mEventLog.logProviderDeliveredLocations(mName,
locationResult != null ? locationResult.size() : 0, getIdentity());
}
@@ -1223,6 +1237,7 @@ public class LocationProviderManager extends
private final CopyOnWriteArrayList<IProviderRequestListener> mProviderRequestListeners;
protected final LocationEventLog mEventLog;
protected final LocationManagerInternal mLocationManagerInternal;
protected final SettingsHelper mSettingsHelper;
protected final UserInfoHelper mUserHelper;
@@ -1235,7 +1250,6 @@ public class LocationProviderManager extends
protected final LocationAttributionHelper mLocationAttributionHelper;
protected final LocationUsageLogger mLocationUsageLogger;
protected final LocationFudger mLocationFudger;
protected final LocationEventLog mLocationEventLog;
private final UserListener mUserChangedListener = this::onUserChanged;
private final UserSettingChangedListener mLocationEnabledChangedListener =
@@ -1273,8 +1287,8 @@ public class LocationProviderManager extends
@GuardedBy("mLock")
private @Nullable OnAlarmListener mDelayedRegister;
public LocationProviderManager(Context context, Injector injector, String name,
@Nullable PassiveLocationProviderManager passiveManager) {
public LocationProviderManager(Context context, Injector injector, LocationEventLog eventLog,
String name, @Nullable PassiveLocationProviderManager passiveManager) {
mContext = context;
mName = Objects.requireNonNull(name);
mPassiveManager = passiveManager;
@@ -1285,6 +1299,7 @@ public class LocationProviderManager extends
mEnabledListeners = new ArrayList<>();
mProviderRequestListeners = new CopyOnWriteArrayList<>();
mEventLog = eventLog;
mLocationManagerInternal = Objects.requireNonNull(
LocalServices.getService(LocationManagerInternal.class));
mSettingsHelper = injector.getSettingsHelper();
@@ -1297,7 +1312,6 @@ public class LocationProviderManager extends
mScreenInteractiveHelper = injector.getScreenInteractiveHelper();
mLocationAttributionHelper = injector.getLocationAttributionHelper();
mLocationUsageLogger = injector.getLocationUsageLogger();
mLocationEventLog = injector.getLocationEventLog();
mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
mProvider = new MockableLocationProvider(mLock);
@@ -1437,7 +1451,7 @@ public class LocationProviderManager extends
synchronized (mLock) {
Preconditions.checkState(mState != STATE_STOPPED);
mLocationEventLog.logProviderMocked(mName, provider != null);
mEventLog.logProviderMocked(mName, provider != null);
final long identity = Binder.clearCallingIdentity();
try {
@@ -1925,7 +1939,7 @@ public class LocationProviderManager extends
@GuardedBy("mLock")
private void setProviderRequest(ProviderRequest request) {
mLocationEventLog.logProviderUpdateRequest(mName, request);
mEventLog.logProviderUpdateRequest(mName, request);
mProvider.getController().setRequest(request);
FgThread.getHandler().post(() -> {
@@ -2261,7 +2275,7 @@ public class LocationProviderManager extends
}
// don't log location received for passive provider because it's spammy
mLocationEventLog.logProviderReceivedLocations(mName, filtered.size());
mEventLog.logProviderReceivedLocations(mName, filtered.size());
} else {
// passive provider should get already filtered results as input
filtered = locationResult;
@@ -2361,7 +2375,7 @@ public class LocationProviderManager extends
if (D) {
Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
}
mLocationEventLog.logProviderEnabled(mName, userId, enabled);
mEventLog.logProviderEnabled(mName, userId, enabled);
}
// clear last locations if we become disabled

View File

@@ -24,6 +24,7 @@ import android.location.provider.ProviderRequest;
import android.os.Binder;
import com.android.internal.util.Preconditions;
import com.android.server.location.eventlog.LocationEventLog;
import com.android.server.location.injector.Injector;
import java.util.Collection;
@@ -33,8 +34,9 @@ import java.util.Collection;
*/
public class PassiveLocationProviderManager extends LocationProviderManager {
public PassiveLocationProviderManager(Context context, Injector injector) {
super(context, injector, LocationManager.PASSIVE_PROVIDER, null);
public PassiveLocationProviderManager(Context context, Injector injector,
LocationEventLog eventLog) {
super(context, injector, eventLog, LocationManager.PASSIVE_PROVIDER, null);
}
@Override

View File

@@ -19,6 +19,8 @@ package com.android.server.location.injector;
import android.os.IPowerManager;
import android.os.PowerManager.LocationPowerSaveMode;
import com.android.server.location.eventlog.LocationEventLog;
/**
* Version of LocationPowerSaveModeHelper for testing. Power save mode is initialized as "no
* change".

View File

@@ -43,6 +43,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
import com.android.server.location.eventlog.LocationEventLog;
import com.android.server.location.injector.LocationPowerSaveModeHelper.LocationPowerSaveModeChangedListener;
import org.junit.After;

View File

@@ -16,9 +16,10 @@
package com.android.server.location.injector;
import com.android.server.location.eventlog.LocationEventLog;
public class TestInjector implements Injector {
private final LocationEventLog mLocationEventLog;
private final FakeUserInfoHelper mUserInfoHelper;
private final FakeAlarmHelper mAlarmHelper;
private final FakeAppOpsHelper mAppOpsHelper;
@@ -32,14 +33,17 @@ public class TestInjector implements Injector {
private final LocationUsageLogger mLocationUsageLogger;
public TestInjector() {
mLocationEventLog = new LocationEventLog();
this(new LocationEventLog());
}
public TestInjector(LocationEventLog eventLog) {
mUserInfoHelper = new FakeUserInfoHelper();
mAlarmHelper = new FakeAlarmHelper();
mAppOpsHelper = new FakeAppOpsHelper();
mLocationPermissionsHelper = new FakeLocationPermissionsHelper(mAppOpsHelper);
mSettingsHelper = new FakeSettingsHelper();
mAppForegroundHelper = new FakeAppForegroundHelper();
mLocationPowerSaveModeHelper = new FakeLocationPowerSaveModeHelper(mLocationEventLog);
mLocationPowerSaveModeHelper = new FakeLocationPowerSaveModeHelper(eventLog);
mScreenInteractiveHelper = new FakeScreenInteractiveHelper();
mLocationAttributionHelper = new LocationAttributionHelper(mAppOpsHelper);
mEmergencyHelper = new FakeEmergencyHelper();
@@ -100,9 +104,4 @@ public class TestInjector implements Injector {
public LocationUsageLogger getLocationUsageLogger() {
return mLocationUsageLogger;
}
@Override
public LocationEventLog getLocationEventLog() {
return mLocationEventLog;
}
}

View File

@@ -83,6 +83,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.location.eventlog.LocationEventLog;
import com.android.server.location.injector.FakeUserInfoHelper;
import com.android.server.location.injector.TestInjector;
@@ -159,17 +160,19 @@ public class LocationProviderManagerTest {
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
mInjector = new TestInjector();
LocationEventLog eventLog = new LocationEventLog();
mInjector = new TestInjector(eventLog);
mInjector.getUserInfoHelper().startUser(OTHER_USER);
mPassive = new PassiveLocationProviderManager(mContext, mInjector);
mPassive = new PassiveLocationProviderManager(mContext, mInjector, eventLog);
mPassive.startManager();
mPassive.setRealProvider(new PassiveLocationProvider(mContext));
mProvider = new TestProvider(PROPERTIES, IDENTITY);
mProvider.setProviderAllowed(true);
mManager = new LocationProviderManager(mContext, mInjector, NAME, mPassive);
mManager = new LocationProviderManager(mContext, mInjector, eventLog, NAME, mPassive);
mManager.startManager();
mManager.setRealProvider(mProvider);
}