Loading core/java/com/android/internal/util/LatencyTracker.java +109 −10 Original line number Diff line number Diff line Loading @@ -37,12 +37,17 @@ import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPOR import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_UDFPS_ILLUMINATE; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__UNKNOWN_ACTION; import static com.android.internal.util.LatencyTracker.ActionProperties.ENABLE_SUFFIX; import static com.android.internal.util.LatencyTracker.ActionProperties.LEGACY_TRACE_THRESHOLD_SUFFIX; import static com.android.internal.util.LatencyTracker.ActionProperties.SAMPLE_INTERVAL_SUFFIX; import static com.android.internal.util.LatencyTracker.ActionProperties.TRACE_THRESHOLD_SUFFIX; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.Build; import android.os.ConditionVariable; import android.os.SystemClock; import android.os.Trace; import android.provider.DeviceConfig; Loading @@ -58,6 +63,7 @@ import com.android.internal.os.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Locale; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; Loading Loading @@ -261,11 +267,11 @@ public class LatencyTracker { @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); @GuardedBy("mLock") private final int[] mTraceThresholdPerAction = new int[ACTIONS_ALL.length]; @GuardedBy("mLock") private int mSamplingInterval; private final SparseArray<ActionProperties> mActionPropertiesMap = new SparseArray<>(); @GuardedBy("mLock") private boolean mEnabled; @VisibleForTesting public final ConditionVariable mDeviceConfigPropertiesUpdated = new ConditionVariable(); public static LatencyTracker getInstance(Context context) { if (sLatencyTracker == null) { Loading @@ -278,9 +284,9 @@ public class LatencyTracker { return sLatencyTracker; } private LatencyTracker() { @VisibleForTesting public LatencyTracker() { mEnabled = DEFAULT_ENABLED; mSamplingInterval = DEFAULT_SAMPLING_INTERVAL; // Post initialization to the background in case we're running on the main thread. BackgroundThread.getHandler().post(() -> this.updateProperties( Loading @@ -291,14 +297,24 @@ public class LatencyTracker { private void updateProperties(DeviceConfig.Properties properties) { synchronized (mLock) { mSamplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, int samplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL); mEnabled = properties.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED); for (int action : ACTIONS_ALL) { mTraceThresholdPerAction[action] = properties.getInt(getNameOfAction(STATSD_ACTION[action]), -1); String actionName = getNameOfAction(STATSD_ACTION[action]).toLowerCase(Locale.ROOT); int legacyActionTraceThreshold = properties.getInt( actionName + LEGACY_TRACE_THRESHOLD_SUFFIX, -1); mActionPropertiesMap.put(action, new ActionProperties(action, properties.getBoolean(actionName + ENABLE_SUFFIX, mEnabled), properties.getInt(actionName + SAMPLE_INTERVAL_SUFFIX, samplingInterval), properties.getInt(actionName + TRACE_THRESHOLD_SUFFIX, legacyActionTraceThreshold))); } if (DEBUG) { Log.d(TAG, "updated action properties: " + mActionPropertiesMap); } } mDeviceConfigPropertiesUpdated.open(); } /** Loading Loading @@ -369,16 +385,38 @@ public class LatencyTracker { return "com.android.telemetry.latency-tracker-" + getNameOfAction(STATSD_ACTION[action]); } /** * @deprecated Use {@link #isEnabled(Context, int)} */ @Deprecated public static boolean isEnabled(Context ctx) { return getInstance(ctx).isEnabled(); } /** * @deprecated Used {@link #isEnabled(int)} */ @Deprecated public boolean isEnabled() { synchronized (mLock) { return mEnabled; } } public static boolean isEnabled(Context ctx, int action) { return getInstance(ctx).isEnabled(action); } public boolean isEnabled(int action) { synchronized (mLock) { ActionProperties actionProperties = mActionPropertiesMap.get(action); if (actionProperties != null) { return actionProperties.isEnabled(); } return false; } } /** * Notifies that an action is starting. <s>This needs to be called from the main thread.</s> * Loading Loading @@ -468,8 +506,14 @@ public class LatencyTracker { boolean shouldSample; int traceThreshold; synchronized (mLock) { shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; traceThreshold = mTraceThresholdPerAction[action]; ActionProperties actionProperties = mActionPropertiesMap.get(action); if (actionProperties == null) { return; } int nextRandNum = ThreadLocalRandom.current().nextInt( actionProperties.getSamplingInterval()); shouldSample = nextRandNum == 0; traceThreshold = actionProperties.getTraceThreshold(); } if (traceThreshold > 0 && duration >= traceThreshold) { Loading Loading @@ -549,4 +593,59 @@ public class LatencyTracker { return (int) (mEndRtc - mStartRtc); } } @VisibleForTesting static class ActionProperties { static final String ENABLE_SUFFIX = "_enable"; static final String SAMPLE_INTERVAL_SUFFIX = "_sample_interval"; // TODO: migrate all usages of the legacy trace theshold property static final String LEGACY_TRACE_THRESHOLD_SUFFIX = ""; static final String TRACE_THRESHOLD_SUFFIX = "_trace_threshold"; @Action private final int mAction; private final boolean mEnabled; private final int mSamplingInterval; private final int mTraceThreshold; ActionProperties( @Action int action, boolean enabled, int samplingInterval, int traceThreshold) { this.mAction = action; com.android.internal.util.AnnotationValidations.validate( Action.class, null, mAction); this.mEnabled = enabled; this.mSamplingInterval = samplingInterval; this.mTraceThreshold = traceThreshold; } @Action int getAction() { return mAction; } boolean isEnabled() { return mEnabled; } int getSamplingInterval() { return mSamplingInterval; } int getTraceThreshold() { return mTraceThreshold; } @Override public String toString() { return "ActionProperties{" + " mAction=" + mAction + ", mEnabled=" + mEnabled + ", mSamplingInterval=" + mSamplingInterval + ", mTraceThreshold=" + mTraceThreshold + "}"; } } } core/tests/coretests/src/com/android/internal/util/LatencyTrackerTest.java +113 −13 Original line number Diff line number Diff line Loading @@ -23,36 +23,53 @@ import static com.android.internal.util.LatencyTracker.STATSD_ACTION; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.provider.DeviceConfig; import android.util.Log; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.google.common.truth.Expect; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.time.Duration; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @SmallTest @RunWith(AndroidJUnit4.class) public class LatencyTrackerTest { private static final String TAG = LatencyTrackerTest.class.getSimpleName(); private static final String ENUM_NAME_PREFIX = "UIACTION_LATENCY_REPORTED__ACTION__"; private static final String ACTION_ENABLE_SUFFIX = "_enable"; private static final Duration TEST_TIMEOUT = Duration.ofMillis(500); @Rule public final Expect mExpect = Expect.create(); @Before public void setUp() { DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY); getAllActions().forEach(action -> { DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, action.getName().toLowerCase() + ACTION_ENABLE_SUFFIX); }); } @Test public void testCujsMapToEnumsCorrectly() { List<Field> actions = Arrays.stream(LatencyTracker.class.getDeclaredFields()) .filter(f -> f.getName().startsWith("ACTION_") && Modifier.isStatic(f.getModifiers()) && f.getType() == int.class) .collect(Collectors.toList()); List<Field> actions = getAllActions(); Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields()) .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX) && Modifier.isStatic(f.getModifiers()) Loading Loading @@ -84,13 +101,7 @@ public class LatencyTrackerTest { @Test public void testCujTypeEnumCorrectlyDefined() throws Exception { List<Field> cujEnumFields = Arrays.stream(LatencyTracker.class.getDeclaredFields()) .filter(field -> field.getName().startsWith("ACTION_") && Modifier.isStatic(field.getModifiers()) && field.getType() == int.class) .collect(Collectors.toList()); List<Field> cujEnumFields = getAllActions(); HashSet<Integer> allValues = new HashSet<>(); for (Field field : cujEnumFields) { int fieldValue = field.getInt(null); Loading @@ -106,6 +117,95 @@ public class LatencyTrackerTest { } } @Test public void testIsEnabled_globalEnabled() { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "true", false); LatencyTracker latencyTracker = new LatencyTracker(); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled()).isTrue(); } @Test public void testIsEnabled_globalDisabled() { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "false", false); LatencyTracker latencyTracker = new LatencyTracker(); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled()).isFalse(); } @Test public void testIsEnabledAction_useGlobalValueWhenActionEnableIsNotSet() { LatencyTracker latencyTracker = new LatencyTracker(); // using a single test action, but this applies to all actions int action = LatencyTracker.ACTION_SHOW_VOICE_INTERACTION; Log.i(TAG, "setting property=" + LatencyTracker.SETTINGS_ENABLED_KEY + ", value=true"); latencyTracker.mDeviceConfigPropertiesUpdated.close(); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "true", false); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat( latencyTracker.isEnabled(action)).isTrue(); Log.i(TAG, "setting property=" + LatencyTracker.SETTINGS_ENABLED_KEY + ", value=false"); latencyTracker.mDeviceConfigPropertiesUpdated.close(); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "false", false); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled(action)).isFalse(); } @Test public void testIsEnabledAction_actionPropertyOverridesGlobalProperty() throws DeviceConfig.BadConfigException { LatencyTracker latencyTracker = new LatencyTracker(); // using a single test action, but this applies to all actions int action = LatencyTracker.ACTION_SHOW_VOICE_INTERACTION; String actionEnableProperty = "action_show_voice_interaction" + ACTION_ENABLE_SUFFIX; Log.i(TAG, "setting property=" + actionEnableProperty + ", value=true"); latencyTracker.mDeviceConfigPropertiesUpdated.close(); Map<String, String> properties = new HashMap<String, String>() {{ put(LatencyTracker.SETTINGS_ENABLED_KEY, "false"); put(actionEnableProperty, "true"); }}; DeviceConfig.setProperties( new DeviceConfig.Properties(DeviceConfig.NAMESPACE_LATENCY_TRACKER, properties)); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled(action)).isTrue(); latencyTracker.mDeviceConfigPropertiesUpdated.close(); Log.i(TAG, "setting property=" + actionEnableProperty + ", value=false"); properties.put(LatencyTracker.SETTINGS_ENABLED_KEY, "true"); properties.put(actionEnableProperty, "false"); DeviceConfig.setProperties( new DeviceConfig.Properties(DeviceConfig.NAMESPACE_LATENCY_TRACKER, properties)); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled(action)).isFalse(); } private void waitForLatencyTrackerToUpdateProperties(LatencyTracker latencyTracker) { try { Thread.sleep(TEST_TIMEOUT.toMillis()); } catch (InterruptedException e) { e.printStackTrace(); } assertThat(latencyTracker.mDeviceConfigPropertiesUpdated.block( TEST_TIMEOUT.toMillis())).isTrue(); } private List<Field> getAllActions() { return Arrays.stream(LatencyTracker.class.getDeclaredFields()) .filter(field -> field.getName().startsWith("ACTION_") && Modifier.isStatic(field.getModifiers()) && field.getType() == int.class) .collect(Collectors.toList()); } private int getIntFieldChecked(Field field) { try { return field.getInt(null); Loading Loading
core/java/com/android/internal/util/LatencyTracker.java +109 −10 Original line number Diff line number Diff line Loading @@ -37,12 +37,17 @@ import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPOR import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_UDFPS_ILLUMINATE; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH; import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__UNKNOWN_ACTION; import static com.android.internal.util.LatencyTracker.ActionProperties.ENABLE_SUFFIX; import static com.android.internal.util.LatencyTracker.ActionProperties.LEGACY_TRACE_THRESHOLD_SUFFIX; import static com.android.internal.util.LatencyTracker.ActionProperties.SAMPLE_INTERVAL_SUFFIX; import static com.android.internal.util.LatencyTracker.ActionProperties.TRACE_THRESHOLD_SUFFIX; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.Build; import android.os.ConditionVariable; import android.os.SystemClock; import android.os.Trace; import android.provider.DeviceConfig; Loading @@ -58,6 +63,7 @@ import com.android.internal.os.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Locale; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; Loading Loading @@ -261,11 +267,11 @@ public class LatencyTracker { @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); @GuardedBy("mLock") private final int[] mTraceThresholdPerAction = new int[ACTIONS_ALL.length]; @GuardedBy("mLock") private int mSamplingInterval; private final SparseArray<ActionProperties> mActionPropertiesMap = new SparseArray<>(); @GuardedBy("mLock") private boolean mEnabled; @VisibleForTesting public final ConditionVariable mDeviceConfigPropertiesUpdated = new ConditionVariable(); public static LatencyTracker getInstance(Context context) { if (sLatencyTracker == null) { Loading @@ -278,9 +284,9 @@ public class LatencyTracker { return sLatencyTracker; } private LatencyTracker() { @VisibleForTesting public LatencyTracker() { mEnabled = DEFAULT_ENABLED; mSamplingInterval = DEFAULT_SAMPLING_INTERVAL; // Post initialization to the background in case we're running on the main thread. BackgroundThread.getHandler().post(() -> this.updateProperties( Loading @@ -291,14 +297,24 @@ public class LatencyTracker { private void updateProperties(DeviceConfig.Properties properties) { synchronized (mLock) { mSamplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, int samplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL); mEnabled = properties.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED); for (int action : ACTIONS_ALL) { mTraceThresholdPerAction[action] = properties.getInt(getNameOfAction(STATSD_ACTION[action]), -1); String actionName = getNameOfAction(STATSD_ACTION[action]).toLowerCase(Locale.ROOT); int legacyActionTraceThreshold = properties.getInt( actionName + LEGACY_TRACE_THRESHOLD_SUFFIX, -1); mActionPropertiesMap.put(action, new ActionProperties(action, properties.getBoolean(actionName + ENABLE_SUFFIX, mEnabled), properties.getInt(actionName + SAMPLE_INTERVAL_SUFFIX, samplingInterval), properties.getInt(actionName + TRACE_THRESHOLD_SUFFIX, legacyActionTraceThreshold))); } if (DEBUG) { Log.d(TAG, "updated action properties: " + mActionPropertiesMap); } } mDeviceConfigPropertiesUpdated.open(); } /** Loading Loading @@ -369,16 +385,38 @@ public class LatencyTracker { return "com.android.telemetry.latency-tracker-" + getNameOfAction(STATSD_ACTION[action]); } /** * @deprecated Use {@link #isEnabled(Context, int)} */ @Deprecated public static boolean isEnabled(Context ctx) { return getInstance(ctx).isEnabled(); } /** * @deprecated Used {@link #isEnabled(int)} */ @Deprecated public boolean isEnabled() { synchronized (mLock) { return mEnabled; } } public static boolean isEnabled(Context ctx, int action) { return getInstance(ctx).isEnabled(action); } public boolean isEnabled(int action) { synchronized (mLock) { ActionProperties actionProperties = mActionPropertiesMap.get(action); if (actionProperties != null) { return actionProperties.isEnabled(); } return false; } } /** * Notifies that an action is starting. <s>This needs to be called from the main thread.</s> * Loading Loading @@ -468,8 +506,14 @@ public class LatencyTracker { boolean shouldSample; int traceThreshold; synchronized (mLock) { shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; traceThreshold = mTraceThresholdPerAction[action]; ActionProperties actionProperties = mActionPropertiesMap.get(action); if (actionProperties == null) { return; } int nextRandNum = ThreadLocalRandom.current().nextInt( actionProperties.getSamplingInterval()); shouldSample = nextRandNum == 0; traceThreshold = actionProperties.getTraceThreshold(); } if (traceThreshold > 0 && duration >= traceThreshold) { Loading Loading @@ -549,4 +593,59 @@ public class LatencyTracker { return (int) (mEndRtc - mStartRtc); } } @VisibleForTesting static class ActionProperties { static final String ENABLE_SUFFIX = "_enable"; static final String SAMPLE_INTERVAL_SUFFIX = "_sample_interval"; // TODO: migrate all usages of the legacy trace theshold property static final String LEGACY_TRACE_THRESHOLD_SUFFIX = ""; static final String TRACE_THRESHOLD_SUFFIX = "_trace_threshold"; @Action private final int mAction; private final boolean mEnabled; private final int mSamplingInterval; private final int mTraceThreshold; ActionProperties( @Action int action, boolean enabled, int samplingInterval, int traceThreshold) { this.mAction = action; com.android.internal.util.AnnotationValidations.validate( Action.class, null, mAction); this.mEnabled = enabled; this.mSamplingInterval = samplingInterval; this.mTraceThreshold = traceThreshold; } @Action int getAction() { return mAction; } boolean isEnabled() { return mEnabled; } int getSamplingInterval() { return mSamplingInterval; } int getTraceThreshold() { return mTraceThreshold; } @Override public String toString() { return "ActionProperties{" + " mAction=" + mAction + ", mEnabled=" + mEnabled + ", mSamplingInterval=" + mSamplingInterval + ", mTraceThreshold=" + mTraceThreshold + "}"; } } }
core/tests/coretests/src/com/android/internal/util/LatencyTrackerTest.java +113 −13 Original line number Diff line number Diff line Loading @@ -23,36 +23,53 @@ import static com.android.internal.util.LatencyTracker.STATSD_ACTION; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.provider.DeviceConfig; import android.util.Log; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.google.common.truth.Expect; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.time.Duration; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @SmallTest @RunWith(AndroidJUnit4.class) public class LatencyTrackerTest { private static final String TAG = LatencyTrackerTest.class.getSimpleName(); private static final String ENUM_NAME_PREFIX = "UIACTION_LATENCY_REPORTED__ACTION__"; private static final String ACTION_ENABLE_SUFFIX = "_enable"; private static final Duration TEST_TIMEOUT = Duration.ofMillis(500); @Rule public final Expect mExpect = Expect.create(); @Before public void setUp() { DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY); getAllActions().forEach(action -> { DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, action.getName().toLowerCase() + ACTION_ENABLE_SUFFIX); }); } @Test public void testCujsMapToEnumsCorrectly() { List<Field> actions = Arrays.stream(LatencyTracker.class.getDeclaredFields()) .filter(f -> f.getName().startsWith("ACTION_") && Modifier.isStatic(f.getModifiers()) && f.getType() == int.class) .collect(Collectors.toList()); List<Field> actions = getAllActions(); Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields()) .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX) && Modifier.isStatic(f.getModifiers()) Loading Loading @@ -84,13 +101,7 @@ public class LatencyTrackerTest { @Test public void testCujTypeEnumCorrectlyDefined() throws Exception { List<Field> cujEnumFields = Arrays.stream(LatencyTracker.class.getDeclaredFields()) .filter(field -> field.getName().startsWith("ACTION_") && Modifier.isStatic(field.getModifiers()) && field.getType() == int.class) .collect(Collectors.toList()); List<Field> cujEnumFields = getAllActions(); HashSet<Integer> allValues = new HashSet<>(); for (Field field : cujEnumFields) { int fieldValue = field.getInt(null); Loading @@ -106,6 +117,95 @@ public class LatencyTrackerTest { } } @Test public void testIsEnabled_globalEnabled() { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "true", false); LatencyTracker latencyTracker = new LatencyTracker(); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled()).isTrue(); } @Test public void testIsEnabled_globalDisabled() { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "false", false); LatencyTracker latencyTracker = new LatencyTracker(); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled()).isFalse(); } @Test public void testIsEnabledAction_useGlobalValueWhenActionEnableIsNotSet() { LatencyTracker latencyTracker = new LatencyTracker(); // using a single test action, but this applies to all actions int action = LatencyTracker.ACTION_SHOW_VOICE_INTERACTION; Log.i(TAG, "setting property=" + LatencyTracker.SETTINGS_ENABLED_KEY + ", value=true"); latencyTracker.mDeviceConfigPropertiesUpdated.close(); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "true", false); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat( latencyTracker.isEnabled(action)).isTrue(); Log.i(TAG, "setting property=" + LatencyTracker.SETTINGS_ENABLED_KEY + ", value=false"); latencyTracker.mDeviceConfigPropertiesUpdated.close(); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_LATENCY_TRACKER, LatencyTracker.SETTINGS_ENABLED_KEY, "false", false); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled(action)).isFalse(); } @Test public void testIsEnabledAction_actionPropertyOverridesGlobalProperty() throws DeviceConfig.BadConfigException { LatencyTracker latencyTracker = new LatencyTracker(); // using a single test action, but this applies to all actions int action = LatencyTracker.ACTION_SHOW_VOICE_INTERACTION; String actionEnableProperty = "action_show_voice_interaction" + ACTION_ENABLE_SUFFIX; Log.i(TAG, "setting property=" + actionEnableProperty + ", value=true"); latencyTracker.mDeviceConfigPropertiesUpdated.close(); Map<String, String> properties = new HashMap<String, String>() {{ put(LatencyTracker.SETTINGS_ENABLED_KEY, "false"); put(actionEnableProperty, "true"); }}; DeviceConfig.setProperties( new DeviceConfig.Properties(DeviceConfig.NAMESPACE_LATENCY_TRACKER, properties)); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled(action)).isTrue(); latencyTracker.mDeviceConfigPropertiesUpdated.close(); Log.i(TAG, "setting property=" + actionEnableProperty + ", value=false"); properties.put(LatencyTracker.SETTINGS_ENABLED_KEY, "true"); properties.put(actionEnableProperty, "false"); DeviceConfig.setProperties( new DeviceConfig.Properties(DeviceConfig.NAMESPACE_LATENCY_TRACKER, properties)); waitForLatencyTrackerToUpdateProperties(latencyTracker); assertThat(latencyTracker.isEnabled(action)).isFalse(); } private void waitForLatencyTrackerToUpdateProperties(LatencyTracker latencyTracker) { try { Thread.sleep(TEST_TIMEOUT.toMillis()); } catch (InterruptedException e) { e.printStackTrace(); } assertThat(latencyTracker.mDeviceConfigPropertiesUpdated.block( TEST_TIMEOUT.toMillis())).isTrue(); } private List<Field> getAllActions() { return Arrays.stream(LatencyTracker.class.getDeclaredFields()) .filter(field -> field.getName().startsWith("ACTION_") && Modifier.isStatic(field.getModifiers()) && field.getType() == int.class) .collect(Collectors.toList()); } private int getIntFieldChecked(Field field) { try { return field.getInt(null); Loading