Refactoring: Move code to StatsPullAtomService
Refactoring: Move time zone detection metrics byte[] generation code to StatsPullAtomService so it's clearer what information is sent off of the device. Previously, the byte[] was generated in service code (MetricsTimeZoneDetectorState), which means that changes don't require metrics team OWNERS approval and changes could be missed. This change is a refactoring before an upcoming addition to the byte[] content is actually made. Bug: 200279201 Test: build only Change-Id: I79a03580b204b78cfb9f969f460d1fd8475befdb
This commit is contained in:
@@ -64,6 +64,8 @@ import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines;
|
||||
import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
|
||||
import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
|
||||
|
||||
import static libcore.io.IoUtils.closeQuietly;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
import static java.util.concurrent.TimeUnit.HOURS;
|
||||
import static java.util.concurrent.TimeUnit.MICROSECONDS;
|
||||
@@ -222,6 +224,7 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -3413,9 +3416,12 @@ public class StatsPullAtomService extends SystemService {
|
||||
metricsState.getGeoDetectionEnabledSetting(),
|
||||
convertToMetricsDetectionMode(metricsState.getDetectionMode()),
|
||||
metricsState.getDeviceTimeZoneIdOrdinal(),
|
||||
metricsState.getLatestManualSuggestionProtoBytes(),
|
||||
metricsState.getLatestTelephonySuggestionProtoBytes(),
|
||||
metricsState.getLatestGeolocationSuggestionProtoBytes()
|
||||
convertTimeZoneSuggestionToProtoBytes(
|
||||
metricsState.getLatestManualSuggestion()),
|
||||
convertTimeZoneSuggestionToProtoBytes(
|
||||
metricsState.getLatestTelephonySuggestion()),
|
||||
convertTimeZoneSuggestionToProtoBytes(
|
||||
metricsState.getLatestGeolocationSuggestion())
|
||||
));
|
||||
} catch (RuntimeException e) {
|
||||
Slog.e(TAG, "Getting time zone detection state failed: ", e);
|
||||
@@ -3426,7 +3432,8 @@ public class StatsPullAtomService extends SystemService {
|
||||
return StatsManager.PULL_SUCCESS;
|
||||
}
|
||||
|
||||
private int convertToMetricsDetectionMode(int detectionMode) {
|
||||
private static int convertToMetricsDetectionMode(
|
||||
@MetricsTimeZoneDetectorState.DetectionMode int detectionMode) {
|
||||
switch (detectionMode) {
|
||||
case MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL:
|
||||
return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
|
||||
@@ -3439,6 +3446,34 @@ public class StatsPullAtomService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static byte[] convertTimeZoneSuggestionToProtoBytes(
|
||||
@Nullable MetricsTimeZoneDetectorState.MetricsTimeZoneSuggestion suggestion) {
|
||||
if (suggestion == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// We don't get access to the atoms.proto definition for nested proto fields, so we use
|
||||
// an identically specified proto.
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
|
||||
int typeProtoValue = suggestion.isCertain()
|
||||
? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
|
||||
: android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
|
||||
protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
|
||||
typeProtoValue);
|
||||
if (suggestion.isCertain()) {
|
||||
for (int zoneIdOrdinal : suggestion.getZoneIdOrdinals()) {
|
||||
protoOutputStream.write(
|
||||
android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
|
||||
zoneIdOrdinal);
|
||||
}
|
||||
}
|
||||
protoOutputStream.flush();
|
||||
closeQuietly(byteArrayOutputStream);
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
private void registerExternalStorageInfo() {
|
||||
int tagId = FrameworkStatsLog.EXTERNAL_STORAGE_INFO;
|
||||
mStatsManager.setPullAtomCallback(
|
||||
|
||||
@@ -16,16 +16,12 @@
|
||||
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
import static libcore.io.IoUtils.closeQuietly;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.timezonedetector.ManualTimeZoneSuggestion;
|
||||
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -50,7 +46,7 @@ public final class MetricsTimeZoneDetectorState {
|
||||
value = { DETECTION_MODE_MANUAL, DETECTION_MODE_GEO, DETECTION_MODE_TELEPHONY})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
|
||||
@interface DetectionMode {};
|
||||
public @interface DetectionMode {};
|
||||
|
||||
public static final @DetectionMode int DETECTION_MODE_MANUAL = 0;
|
||||
public static final @DetectionMode int DETECTION_MODE_GEO = 1;
|
||||
@@ -89,16 +85,16 @@ public final class MetricsTimeZoneDetectorState {
|
||||
|
||||
int deviceTimeZoneIdOrdinal =
|
||||
tzIdOrdinalGenerator.ordinal(Objects.requireNonNull(deviceTimeZoneId));
|
||||
MetricsTimeZoneSuggestion latestObfuscatedManualSuggestion =
|
||||
MetricsTimeZoneSuggestion latestCanonicalManualSuggestion =
|
||||
createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestManualSuggestion);
|
||||
MetricsTimeZoneSuggestion latestObfuscatedTelephonySuggestion =
|
||||
MetricsTimeZoneSuggestion latestCanonicalTelephonySuggestion =
|
||||
createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestTelephonySuggestion);
|
||||
MetricsTimeZoneSuggestion latestObfuscatedGeolocationSuggestion =
|
||||
MetricsTimeZoneSuggestion latestCanonicalGeolocationSuggestion =
|
||||
createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestGeolocationSuggestion);
|
||||
|
||||
return new MetricsTimeZoneDetectorState(
|
||||
configurationInternal, deviceTimeZoneIdOrdinal, latestObfuscatedManualSuggestion,
|
||||
latestObfuscatedTelephonySuggestion, latestObfuscatedGeolocationSuggestion);
|
||||
configurationInternal, deviceTimeZoneIdOrdinal, latestCanonicalManualSuggestion,
|
||||
latestCanonicalTelephonySuggestion, latestCanonicalGeolocationSuggestion);
|
||||
}
|
||||
|
||||
/** Returns true if the device supports telephony time zone detection. */
|
||||
@@ -154,30 +150,27 @@ public final class MetricsTimeZoneDetectorState {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last manual
|
||||
* suggestion received.
|
||||
* Returns a canonical form of the last manual suggestion received.
|
||||
*/
|
||||
@Nullable
|
||||
public byte[] getLatestManualSuggestionProtoBytes() {
|
||||
return suggestionProtoBytes(mLatestManualSuggestion);
|
||||
public MetricsTimeZoneSuggestion getLatestManualSuggestion() {
|
||||
return mLatestManualSuggestion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last, best
|
||||
* telephony suggestion received.
|
||||
* Returns a canonical form of the last telephony suggestion received.
|
||||
*/
|
||||
@Nullable
|
||||
public byte[] getLatestTelephonySuggestionProtoBytes() {
|
||||
return suggestionProtoBytes(mLatestTelephonySuggestion);
|
||||
public MetricsTimeZoneSuggestion getLatestTelephonySuggestion() {
|
||||
return mLatestTelephonySuggestion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last geolocation
|
||||
* suggestion received.
|
||||
* Returns a canonical form of last geolocation suggestion received.
|
||||
*/
|
||||
@Nullable
|
||||
public byte[] getLatestGeolocationSuggestionProtoBytes() {
|
||||
return suggestionProtoBytes(mLatestGeolocationSuggestion);
|
||||
public MetricsTimeZoneSuggestion getLatestGeolocationSuggestion() {
|
||||
return mLatestGeolocationSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,14 +206,6 @@ public final class MetricsTimeZoneDetectorState {
|
||||
+ '}';
|
||||
}
|
||||
|
||||
private static byte[] suggestionProtoBytes(
|
||||
@Nullable MetricsTimeZoneSuggestion suggestion) {
|
||||
if (suggestion == null) {
|
||||
return null;
|
||||
}
|
||||
return suggestion.toBytes();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static MetricsTimeZoneSuggestion createMetricsTimeZoneSuggestion(
|
||||
@NonNull OrdinalGenerator<String> zoneIdOrdinalGenerator,
|
||||
@@ -264,10 +249,11 @@ public final class MetricsTimeZoneDetectorState {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Java class that closely matches the android.app.time.MetricsTimeZoneSuggestion
|
||||
* proto definition.
|
||||
* A Java class that represents a generic time zone suggestion, i.e. one that is independent of
|
||||
* origin-specific information. This closely matches the metrics atoms.proto
|
||||
* MetricsTimeZoneSuggestion proto definition.
|
||||
*/
|
||||
private static final class MetricsTimeZoneSuggestion {
|
||||
public static final class MetricsTimeZoneSuggestion {
|
||||
@Nullable
|
||||
private final int[] mZoneIdOrdinals;
|
||||
|
||||
@@ -281,42 +267,20 @@ public final class MetricsTimeZoneDetectorState {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static MetricsTimeZoneSuggestion createCertain(
|
||||
static MetricsTimeZoneSuggestion createCertain(
|
||||
@NonNull int[] zoneIdOrdinals) {
|
||||
return new MetricsTimeZoneSuggestion(zoneIdOrdinals);
|
||||
}
|
||||
|
||||
boolean isCertain() {
|
||||
public boolean isCertain() {
|
||||
return mZoneIdOrdinals != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
int[] getZoneIdOrdinals() {
|
||||
public int[] getZoneIdOrdinals() {
|
||||
return mZoneIdOrdinals;
|
||||
}
|
||||
|
||||
byte[] toBytes() {
|
||||
// We don't get access to the atoms.proto definition for nested proto fields, so we use
|
||||
// an identically specified proto.
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
|
||||
int typeProtoValue = isCertain()
|
||||
? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
|
||||
: android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
|
||||
protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
|
||||
typeProtoValue);
|
||||
if (isCertain()) {
|
||||
for (int zoneIdOrdinal : getZoneIdOrdinals()) {
|
||||
protoOutputStream.write(
|
||||
android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
|
||||
zoneIdOrdinal);
|
||||
}
|
||||
}
|
||||
protoOutputStream.flush();
|
||||
closeQuietly(byteArrayOutputStream);
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
||||
Reference in New Issue
Block a user