Add system monitor event class, set DataBroker priority when receives
event.
- The SystemMonitorEvent contains system status
- DataBrokerController uses the event to determine the appropriate task
priority to run for DataBroker
Bug: 187744195
Test: atest CarServiceUnitTest:DataBrokerControllerUnitTest
Test: atest CarServiceUnitTest:SystemMonitorEventUnitTest
Change-Id: I18087dc3f44e26000932afd3110f0ee6c5a38482
diff --git a/service/src/com/android/car/telemetry/databroker/DataBroker.java b/service/src/com/android/car/telemetry/databroker/DataBroker.java
index e26b113..44f2f61 100644
--- a/service/src/com/android/car/telemetry/databroker/DataBroker.java
+++ b/service/src/com/android/car/telemetry/databroker/DataBroker.java
@@ -48,4 +48,10 @@
* @param callback script finished callback.
*/
void setOnScriptFinishedCallback(DataBrokerController.ScriptFinishedCallback callback);
+
+ /**
+ * Invoked by controller to indicate system health state and which subscribers can be consumed.
+ * A smaller priority number indicates higher priority. Range 1 - 100.
+ */
+ void setTaskExecutionPriority(int priority);
}
diff --git a/service/src/com/android/car/telemetry/databroker/DataBrokerController.java b/service/src/com/android/car/telemetry/databroker/DataBrokerController.java
index 75bfd78..7663667 100644
--- a/service/src/com/android/car/telemetry/databroker/DataBrokerController.java
+++ b/service/src/com/android/car/telemetry/databroker/DataBrokerController.java
@@ -17,6 +17,8 @@
package com.android.car.telemetry.databroker;
import com.android.car.telemetry.TelemetryProto.MetricsConfig;
+import com.android.car.telemetry.systemmonitor.SystemMonitor;
+import com.android.car.telemetry.systemmonitor.SystemMonitorEvent;
/**
* DataBrokerController instantiates the DataBroker and manages what Publishers
@@ -24,8 +26,13 @@
*/
public class DataBrokerController {
+ public static final int TASK_PRIORITY_HI = 0;
+ public static final int TASK_PRIORITY_MED = 50;
+ public static final int TASK_PRIORITY_LOW = 100;
+
private MetricsConfig mMetricsConfig;
private final DataBroker mDataBroker;
+ private final SystemMonitor mSystemMonitor;
/**
* Interface for receiving notification that script finished.
@@ -39,21 +46,11 @@
void onScriptFinished(String configName);
}
- /**
- * Interface for receiving notification about metric config changes.
- */
- public interface MetricsConfigCallback {
- /**
- * Listens to new metrics config event.
- *
- * @param metricsConfig the new metrics config.
- */
- void onNewMetricsConfig(MetricsConfig metricsConfig);
- }
-
- public DataBrokerController(DataBroker dataBroker) {
+ public DataBrokerController(DataBroker dataBroker, SystemMonitor systemMonitor) {
mDataBroker = dataBroker;
mDataBroker.setOnScriptFinishedCallback(this::onScriptFinished);
+ mSystemMonitor = systemMonitor;
+ mSystemMonitor.setSystemMonitorCallback(this::onSystemMonitorEvent);
}
/**
@@ -72,6 +69,27 @@
* @param configName the name of the config of the finished script.
*/
public void onScriptFinished(String configName) {
- // TODO(b/187744195): remove finished config from config store
+ // TODO(b/192008783): remove finished config from config store
+ }
+
+ /**
+ * Listens to {@link SystemMonitorEvent} and changes the cut-off priority
+ * for {@link DataBroker} such that only tasks with the same or more urgent
+ * priority can be run.
+ *
+ * Highest priority is 0 and lowest is 100.
+ *
+ * @param event the {@link SystemMonitorEvent} received.
+ */
+ public void onSystemMonitorEvent(SystemMonitorEvent event) {
+ if (event.getCpuUsageLevel() == SystemMonitorEvent.USAGE_LEVEL_HI
+ || event.getMemoryUsageLevel() == SystemMonitorEvent.USAGE_LEVEL_HI) {
+ mDataBroker.setTaskExecutionPriority(TASK_PRIORITY_HI);
+ } else if (event.getCpuUsageLevel() == SystemMonitorEvent.USAGE_LEVEL_MED
+ || event.getMemoryUsageLevel() == SystemMonitorEvent.USAGE_LEVEL_MED) {
+ mDataBroker.setTaskExecutionPriority(TASK_PRIORITY_MED);
+ } else {
+ mDataBroker.setTaskExecutionPriority(TASK_PRIORITY_LOW);
+ }
}
}
diff --git a/service/src/com/android/car/telemetry/databroker/DataBrokerImpl.java b/service/src/com/android/car/telemetry/databroker/DataBrokerImpl.java
index 0a46536..86d725e 100644
--- a/service/src/com/android/car/telemetry/databroker/DataBrokerImpl.java
+++ b/service/src/com/android/car/telemetry/databroker/DataBrokerImpl.java
@@ -47,6 +47,9 @@
mPublisherFactory = publisherFactory;
}
+ // current task priority, used to determine which data can be processed
+ private int mTaskExecutionPriority;
+
@Override
public boolean addMetricsConfiguration(MetricsConfig metricsConfig) {
// if metricsConfig already exists, it should not be added again
@@ -104,6 +107,11 @@
mScriptFinishedCallback = callback;
}
+ @Override
+ public void setTaskExecutionPriority(int priority) {
+ mTaskExecutionPriority = priority;
+ }
+
@VisibleForTesting
Map<String, List<DataSubscriber>> getSubscriptionMap() {
return mSubscriptionMap;
diff --git a/service/src/com/android/car/telemetry/systemmonitor/SystemMonitor.java b/service/src/com/android/car/telemetry/systemmonitor/SystemMonitor.java
new file mode 100644
index 0000000..65bc45b
--- /dev/null
+++ b/service/src/com/android/car/telemetry/systemmonitor/SystemMonitor.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ * 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.car.telemetry.systemmonitor;
+
+/**
+ * SystemMonitor monitors system states and report to listeners when there are
+ * important changes.
+ */
+public class SystemMonitor {
+
+ private SystemMonitorCallback mCallback;
+
+ /**
+ * Interface for receiving notifications about system monitor changes.
+ */
+ public interface SystemMonitorCallback {
+ /**
+ * Listens to system monitor event.
+ *
+ * @param event the system monitor event.
+ */
+ void onSystemMonitorEvent(SystemMonitorEvent event);
+ }
+
+ /**
+ * Sets the callback to notify of system state changes.
+ *
+ * @param callback the callback to nofify state changes on.
+ */
+ public void setSystemMonitorCallback(SystemMonitorCallback callback) {
+ mCallback = callback;
+ }
+}
diff --git a/service/src/com/android/car/telemetry/systemmonitor/SystemMonitorEvent.java b/service/src/com/android/car/telemetry/systemmonitor/SystemMonitorEvent.java
new file mode 100644
index 0000000..67a7dbd
--- /dev/null
+++ b/service/src/com/android/car/telemetry/systemmonitor/SystemMonitorEvent.java
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ * 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.car.telemetry.systemmonitor;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * System health events emitted by the SystemMonitor.
+ */
+public class SystemMonitorEvent {
+
+ @IntDef(prefix = { "USAGE_LEVEL_" },
+ value = { USAGE_LEVEL_LOW, USAGE_LEVEL_MED, USAGE_LEVEL_HI })
+
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UsageLevel {}
+
+ public static final int USAGE_LEVEL_LOW = 0;
+
+ public static final int USAGE_LEVEL_MED = 1;
+
+ public static final int USAGE_LEVEL_HI = 2;
+
+ private @UsageLevel int mCpuUsageLevel;
+
+ private @UsageLevel int mMemoryUsageLevel;
+
+ public void setCpuUsageLevel(@UsageLevel int usageLevel) {
+ this.mCpuUsageLevel = usageLevel;
+ }
+
+ public void setMemoryUsageLevel(@UsageLevel int usageLevel) {
+ this.mMemoryUsageLevel = usageLevel;
+ }
+
+ public @UsageLevel int getCpuUsageLevel() {
+ return this.mCpuUsageLevel;
+ }
+
+ public @UsageLevel int getMemoryUsageLevel() {
+ return this.mMemoryUsageLevel;
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerControllerUnitTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerControllerUnitTest.java
index 4fe9ffe..931a557 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerControllerUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerControllerUnitTest.java
@@ -19,25 +19,28 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import com.android.car.telemetry.TelemetryProto;
+import com.android.car.telemetry.systemmonitor.SystemMonitor;
+import com.android.car.telemetry.systemmonitor.SystemMonitorEvent;
-import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
+import org.mockito.junit.MockitoJUnitRunner;
-
+@RunWith(MockitoJUnitRunner.class)
public class DataBrokerControllerUnitTest {
- @Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Mock private DataBroker mMockDataBroker;
+ @Mock private SystemMonitor mMockSystemMonitor;
+
@Captor ArgumentCaptor<TelemetryProto.MetricsConfig> mConfigCaptor;
@Captor ArgumentCaptor<Integer> mPriorityCaptor;
@@ -80,4 +83,74 @@
verify(mMockDataBroker).setOnScriptFinishedCallback(
any(DataBrokerController.ScriptFinishedCallback.class));
}
+
+ @Test
+ public void testOnSystemEvent_setDataBrokerPriorityCorrectlyForHighCpuUsage() {
+ SystemMonitorEvent highCpuEvent = new SystemMonitorEvent();
+ highCpuEvent.setCpuUsageLevel(SystemMonitorEvent.USAGE_LEVEL_HI);
+ highCpuEvent.setMemoryUsageLevel(SystemMonitorEvent.USAGE_LEVEL_LOW);
+
+ mController.onSystemMonitorEvent(highCpuEvent);
+
+ verify(mMockDataBroker, atLeastOnce())
+ .setTaskExecutionPriority(mPriorityCaptor.capture());
+ assertThat(mPriorityCaptor.getValue())
+ .isEqualTo(DataBrokerController.TASK_PRIORITY_HI);
+ }
+
+ @Test
+ public void testOnSystemEvent_setDataBrokerPriorityCorrectlyForHighMemUsage() {
+ SystemMonitorEvent highMemEvent = new SystemMonitorEvent();
+ highMemEvent.setCpuUsageLevel(SystemMonitorEvent.USAGE_LEVEL_LOW);
+ highMemEvent.setMemoryUsageLevel(SystemMonitorEvent.USAGE_LEVEL_HI);
+
+ mController.onSystemMonitorEvent(highMemEvent);
+
+ verify(mMockDataBroker, atLeastOnce())
+ .setTaskExecutionPriority(mPriorityCaptor.capture());
+ assertThat(mPriorityCaptor.getValue())
+ .isEqualTo(DataBrokerController.TASK_PRIORITY_HI);
+ }
+
+ @Test
+ public void testOnSystemEvent_setDataBrokerPriorityCorrectlyForMedCpuUsage() {
+ SystemMonitorEvent medCpuEvent = new SystemMonitorEvent();
+ medCpuEvent.setCpuUsageLevel(SystemMonitorEvent.USAGE_LEVEL_MED);
+ medCpuEvent.setMemoryUsageLevel(SystemMonitorEvent.USAGE_LEVEL_LOW);
+
+ mController.onSystemMonitorEvent(medCpuEvent);
+
+ verify(mMockDataBroker, atLeastOnce())
+ .setTaskExecutionPriority(mPriorityCaptor.capture());
+ assertThat(mPriorityCaptor.getValue())
+ .isEqualTo(DataBrokerController.TASK_PRIORITY_MED);
+ }
+
+ @Test
+ public void testOnSystemEvent_setDataBrokerPriorityCorrectlyForMedMemUsage() {
+ SystemMonitorEvent medMemEvent = new SystemMonitorEvent();
+ medMemEvent.setCpuUsageLevel(SystemMonitorEvent.USAGE_LEVEL_LOW);
+ medMemEvent.setMemoryUsageLevel(SystemMonitorEvent.USAGE_LEVEL_MED);
+
+ mController.onSystemMonitorEvent(medMemEvent);
+
+ verify(mMockDataBroker, atLeastOnce())
+ .setTaskExecutionPriority(mPriorityCaptor.capture());
+ assertThat(mPriorityCaptor.getValue())
+ .isEqualTo(DataBrokerController.TASK_PRIORITY_MED);
+ }
+
+ @Test
+ public void testOnSystemEvent_setDataBrokerPriorityCorrectlyForLowUsage() {
+ SystemMonitorEvent lowUsageEvent = new SystemMonitorEvent();
+ lowUsageEvent.setCpuUsageLevel(SystemMonitorEvent.USAGE_LEVEL_LOW);
+ lowUsageEvent.setMemoryUsageLevel(SystemMonitorEvent.USAGE_LEVEL_LOW);
+
+ mController.onSystemMonitorEvent(lowUsageEvent);
+
+ verify(mMockDataBroker, atLeastOnce())
+ .setTaskExecutionPriority(mPriorityCaptor.capture());
+ assertThat(mPriorityCaptor.getValue())
+ .isEqualTo(DataBrokerController.TASK_PRIORITY_LOW);
+ }
}
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/systemmonitor/SystemMonitorEventUnitTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/systemmonitor/SystemMonitorEventUnitTest.java
new file mode 100644
index 0000000..46b9992
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/systemmonitor/SystemMonitorEventUnitTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ * 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.car.telemetry.systemmonitor;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SystemMonitorEventUnitTest {
+
+ @Test
+ public void testCpuUsageLevelGetterSetter_correctlyGetSetCpuUsageLevel() {
+ SystemMonitorEvent event = new SystemMonitorEvent();
+ event.setCpuUsageLevel(SystemMonitorEvent.USAGE_LEVEL_HI);
+
+ assertThat(event.getCpuUsageLevel())
+ .isEqualTo(SystemMonitorEvent.USAGE_LEVEL_HI);
+ }
+
+ @Test
+ public void testMemUsageLevelGetterSetter_correctlyGetSetMemUsageLevel() {
+ SystemMonitorEvent event = new SystemMonitorEvent();
+ event.setMemoryUsageLevel(SystemMonitorEvent.USAGE_LEVEL_MED);
+
+ assertThat(event.getMemoryUsageLevel())
+ .isEqualTo(SystemMonitorEvent.USAGE_LEVEL_MED);
+ }
+}