Loading services/core/java/com/android/server/LocationManagerService.java +2 −0 Original line number Diff line number Diff line Loading @@ -3192,6 +3192,8 @@ public class LocationManagerService extends ILocationManager.Stub { } ipw.decreaseIndent(); mRequestStatistics.history.dump(ipw); ipw.println("Last Known Locations:"); ipw.increaseIndent(); for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { Loading services/core/java/com/android/server/location/LocationRequestStatistics.java +124 −1 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.location; import android.os.SystemClock; import android.util.Log; import android.util.TimeUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import java.util.ArrayList; import java.util.HashMap; /** Loading @@ -17,6 +38,8 @@ public class LocationRequestStatistics { public final HashMap<PackageProviderKey, PackageStatistics> statistics = new HashMap<PackageProviderKey, PackageStatistics>(); public final RequestSummaryLimitedHistory history = new RequestSummaryLimitedHistory(); /** * Signals that a package has started requesting locations. * Loading @@ -34,6 +57,7 @@ public class LocationRequestStatistics { } stats.startRequesting(intervalMs); stats.updateForeground(isForeground); history.addRequest(packageName, providerName, intervalMs); } /** Loading @@ -48,6 +72,7 @@ public class LocationRequestStatistics { if (stats != null) { stats.stopRequesting(); } history.removeRequest(packageName, providerName); } /** Loading Loading @@ -77,7 +102,7 @@ public class LocationRequestStatistics { */ public final String providerName; public PackageProviderKey(String packageName, String providerName) { PackageProviderKey(String packageName, String providerName) { this.packageName = packageName; this.providerName = providerName; } Loading @@ -99,6 +124,104 @@ public class LocationRequestStatistics { } } /** * A data structure to hold past requests */ public static class RequestSummaryLimitedHistory { @VisibleForTesting static final int MAX_SIZE = 100; final ArrayList<RequestSummary> mList = new ArrayList<>(MAX_SIZE); /** * Append an added location request to the history */ @VisibleForTesting void addRequest(String packageName, String providerName, long intervalMs) { addRequestSummary(new RequestSummary(packageName, providerName, intervalMs)); } /** * Append a removed location request to the history */ @VisibleForTesting void removeRequest(String packageName, String providerName) { addRequestSummary(new RequestSummary( packageName, providerName, RequestSummary.REQUEST_ENDED_INTERVAL)); } private void addRequestSummary(RequestSummary summary) { while (mList.size() >= MAX_SIZE) { mList.remove(0); } mList.add(summary); } /** * Dump history to a printwriter (for dumpsys location) */ public void dump(IndentingPrintWriter ipw) { long systemElapsedOffsetMillis = System.currentTimeMillis() - SystemClock.elapsedRealtime(); ipw.println("Last Several Location Requests:"); ipw.increaseIndent(); for (RequestSummary requestSummary : mList) { requestSummary.dump(ipw, systemElapsedOffsetMillis); } ipw.decreaseIndent(); } } /** * A data structure to hold a single request */ static class RequestSummary { /** * Name of package requesting location. */ private final String mPackageName; /** * Name of provider being requested (e.g. "gps"). */ private final String mProviderName; /** * Interval Requested, or REQUEST_ENDED_INTERVAL indicating request has ended */ private final long mIntervalMillis; /** * Elapsed time of request */ private final long mElapsedRealtimeMillis; /** * Placeholder for requested ending (other values indicate request started/changed) */ static final long REQUEST_ENDED_INTERVAL = -1; RequestSummary(String packageName, String providerName, long intervalMillis) { this.mPackageName = packageName; this.mProviderName = providerName; this.mIntervalMillis = intervalMillis; this.mElapsedRealtimeMillis = SystemClock.elapsedRealtime(); } void dump(IndentingPrintWriter ipw, long systemElapsedOffsetMillis) { StringBuilder s = new StringBuilder(); long systemTimeMillis = systemElapsedOffsetMillis + mElapsedRealtimeMillis; s.append("At ").append(TimeUtils.formatForLogging(systemTimeMillis)).append(": ") .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ") .append(String.format("%7s", mProviderName)).append(" request from ") .append(mPackageName); if (mIntervalMillis != REQUEST_ENDED_INTERVAL) { s.append(" at interval ").append(mIntervalMillis / 1000).append(" seconds"); } ipw.println(s); } } /** * Usage statistics for a package/provider pair. */ Loading services/robotests/src/com/android/server/location/LocationRequestStatisticsTest.java 0 → 100644 +74 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.location; import static com.google.common.truth.Truth.assertThat; import android.platform.test.annotations.Presubmit; import com.android.internal.util.IndentingPrintWriter; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import java.io.PrintWriter; import java.io.StringWriter; /** * Unit tests for {@link LocationRequestStatistics}. */ @RunWith(RobolectricTestRunner.class) @Presubmit public class LocationRequestStatisticsTest { /** * Check adding and removing requests & strings */ @Test public void testRequestSummary() { LocationRequestStatistics.RequestSummary summary = new LocationRequestStatistics.RequestSummary( "com.example", "gps", 1000); StringWriter stringWriter = new StringWriter(); summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriter), " "), 1234); assertThat(stringWriter.toString()).startsWith("At"); StringWriter stringWriterRemove = new StringWriter(); summary = new LocationRequestStatistics.RequestSummary( "com.example", "gps", LocationRequestStatistics.RequestSummary.REQUEST_ENDED_INTERVAL); summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriterRemove), " "), 2345); assertThat(stringWriterRemove.toString()).contains("-"); } /** * Check summary list size capping */ @Test public void testSummaryList() { LocationRequestStatistics statistics = new LocationRequestStatistics(); statistics.history.addRequest("com.example", "gps", 1000); assertThat(statistics.history.mList.size()).isEqualTo(1); // Try (not) to overflow for (int i = 0; i < LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE; i++) { statistics.history.addRequest("com.example", "gps", 1000); } assertThat(statistics.history.mList.size()).isEqualTo( LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE); } } Loading
services/core/java/com/android/server/LocationManagerService.java +2 −0 Original line number Diff line number Diff line Loading @@ -3192,6 +3192,8 @@ public class LocationManagerService extends ILocationManager.Stub { } ipw.decreaseIndent(); mRequestStatistics.history.dump(ipw); ipw.println("Last Known Locations:"); ipw.increaseIndent(); for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { Loading
services/core/java/com/android/server/location/LocationRequestStatistics.java +124 −1 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.location; import android.os.SystemClock; import android.util.Log; import android.util.TimeUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import java.util.ArrayList; import java.util.HashMap; /** Loading @@ -17,6 +38,8 @@ public class LocationRequestStatistics { public final HashMap<PackageProviderKey, PackageStatistics> statistics = new HashMap<PackageProviderKey, PackageStatistics>(); public final RequestSummaryLimitedHistory history = new RequestSummaryLimitedHistory(); /** * Signals that a package has started requesting locations. * Loading @@ -34,6 +57,7 @@ public class LocationRequestStatistics { } stats.startRequesting(intervalMs); stats.updateForeground(isForeground); history.addRequest(packageName, providerName, intervalMs); } /** Loading @@ -48,6 +72,7 @@ public class LocationRequestStatistics { if (stats != null) { stats.stopRequesting(); } history.removeRequest(packageName, providerName); } /** Loading Loading @@ -77,7 +102,7 @@ public class LocationRequestStatistics { */ public final String providerName; public PackageProviderKey(String packageName, String providerName) { PackageProviderKey(String packageName, String providerName) { this.packageName = packageName; this.providerName = providerName; } Loading @@ -99,6 +124,104 @@ public class LocationRequestStatistics { } } /** * A data structure to hold past requests */ public static class RequestSummaryLimitedHistory { @VisibleForTesting static final int MAX_SIZE = 100; final ArrayList<RequestSummary> mList = new ArrayList<>(MAX_SIZE); /** * Append an added location request to the history */ @VisibleForTesting void addRequest(String packageName, String providerName, long intervalMs) { addRequestSummary(new RequestSummary(packageName, providerName, intervalMs)); } /** * Append a removed location request to the history */ @VisibleForTesting void removeRequest(String packageName, String providerName) { addRequestSummary(new RequestSummary( packageName, providerName, RequestSummary.REQUEST_ENDED_INTERVAL)); } private void addRequestSummary(RequestSummary summary) { while (mList.size() >= MAX_SIZE) { mList.remove(0); } mList.add(summary); } /** * Dump history to a printwriter (for dumpsys location) */ public void dump(IndentingPrintWriter ipw) { long systemElapsedOffsetMillis = System.currentTimeMillis() - SystemClock.elapsedRealtime(); ipw.println("Last Several Location Requests:"); ipw.increaseIndent(); for (RequestSummary requestSummary : mList) { requestSummary.dump(ipw, systemElapsedOffsetMillis); } ipw.decreaseIndent(); } } /** * A data structure to hold a single request */ static class RequestSummary { /** * Name of package requesting location. */ private final String mPackageName; /** * Name of provider being requested (e.g. "gps"). */ private final String mProviderName; /** * Interval Requested, or REQUEST_ENDED_INTERVAL indicating request has ended */ private final long mIntervalMillis; /** * Elapsed time of request */ private final long mElapsedRealtimeMillis; /** * Placeholder for requested ending (other values indicate request started/changed) */ static final long REQUEST_ENDED_INTERVAL = -1; RequestSummary(String packageName, String providerName, long intervalMillis) { this.mPackageName = packageName; this.mProviderName = providerName; this.mIntervalMillis = intervalMillis; this.mElapsedRealtimeMillis = SystemClock.elapsedRealtime(); } void dump(IndentingPrintWriter ipw, long systemElapsedOffsetMillis) { StringBuilder s = new StringBuilder(); long systemTimeMillis = systemElapsedOffsetMillis + mElapsedRealtimeMillis; s.append("At ").append(TimeUtils.formatForLogging(systemTimeMillis)).append(": ") .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ") .append(String.format("%7s", mProviderName)).append(" request from ") .append(mPackageName); if (mIntervalMillis != REQUEST_ENDED_INTERVAL) { s.append(" at interval ").append(mIntervalMillis / 1000).append(" seconds"); } ipw.println(s); } } /** * Usage statistics for a package/provider pair. */ Loading
services/robotests/src/com/android/server/location/LocationRequestStatisticsTest.java 0 → 100644 +74 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.location; import static com.google.common.truth.Truth.assertThat; import android.platform.test.annotations.Presubmit; import com.android.internal.util.IndentingPrintWriter; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import java.io.PrintWriter; import java.io.StringWriter; /** * Unit tests for {@link LocationRequestStatistics}. */ @RunWith(RobolectricTestRunner.class) @Presubmit public class LocationRequestStatisticsTest { /** * Check adding and removing requests & strings */ @Test public void testRequestSummary() { LocationRequestStatistics.RequestSummary summary = new LocationRequestStatistics.RequestSummary( "com.example", "gps", 1000); StringWriter stringWriter = new StringWriter(); summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriter), " "), 1234); assertThat(stringWriter.toString()).startsWith("At"); StringWriter stringWriterRemove = new StringWriter(); summary = new LocationRequestStatistics.RequestSummary( "com.example", "gps", LocationRequestStatistics.RequestSummary.REQUEST_ENDED_INTERVAL); summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriterRemove), " "), 2345); assertThat(stringWriterRemove.toString()).contains("-"); } /** * Check summary list size capping */ @Test public void testSummaryList() { LocationRequestStatistics statistics = new LocationRequestStatistics(); statistics.history.addRequest("com.example", "gps", 1000); assertThat(statistics.history.mList.size()).isEqualTo(1); // Try (not) to overflow for (int i = 0; i < LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE; i++) { statistics.history.addRequest("com.example", "gps", 1000); } assertThat(statistics.history.mList.size()).isEqualTo( LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE); } }