Merge "Support temporary disabling watchdog killing" into sc-v2-dev
diff --git a/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl b/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl
index 57d82ca..c9ece21 100644
--- a/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl
+++ b/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl
@@ -128,4 +128,12 @@
* @param actions List of actions take on resource overusing packages.
*/
void actionTakenOnResourceOveruse(in List<PackageResourceOveruseAction> actions);
+
+ /**
+ * Enable/disable the internal client health check process.
+ * Disabling would stop the ANR killing process.
+ *
+ * @param isEnabled New enabled state.
+ */
+ void controlProcessHealthCheck(in boolean disable);
}
diff --git a/cpp/watchdog/car-watchdog-lib/src/android/car/watchdoglib/CarWatchdogDaemonHelper.java b/cpp/watchdog/car-watchdog-lib/src/android/car/watchdoglib/CarWatchdogDaemonHelper.java
index 1810c92..e7229ba 100644
--- a/cpp/watchdog/car-watchdog-lib/src/android/car/watchdoglib/CarWatchdogDaemonHelper.java
+++ b/cpp/watchdog/car-watchdog-lib/src/android/car/watchdoglib/CarWatchdogDaemonHelper.java
@@ -291,6 +291,16 @@
invokeDaemonMethod((daemon) -> daemon.actionTakenOnResourceOveruse(actions));
}
+ /**
+ * Enable/disable the internal client health check process.
+ * Disabling would stop the ANR killing process.
+ *
+ * @param disable True to disable watchdog's health check process.
+ */
+ public void controlProcessHealthCheck(boolean disable) throws RemoteException {
+ invokeDaemonMethod((daemon) -> daemon.controlProcessHealthCheck(disable));
+ }
+
private void invokeDaemonMethod(Invokable r) throws RemoteException {
ICarWatchdog daemon;
synchronized (mLock) {
diff --git a/cpp/watchdog/server/src/WatchdogInternalHandler.cpp b/cpp/watchdog/server/src/WatchdogInternalHandler.cpp
index 6da5fb5..be49ff9 100644
--- a/cpp/watchdog/server/src/WatchdogInternalHandler.cpp
+++ b/cpp/watchdog/server/src/WatchdogInternalHandler.cpp
@@ -268,6 +268,15 @@
return Status::ok();
}
+Status WatchdogInternalHandler::controlProcessHealthCheck(bool disable) {
+ Status status = checkSystemUser();
+ if (!status.isOk()) {
+ return status;
+ }
+ mWatchdogProcessService->setEnabled(!disable);
+ return Status::ok();
+}
+
} // namespace watchdog
} // namespace automotive
} // namespace android
diff --git a/cpp/watchdog/server/src/WatchdogInternalHandler.h b/cpp/watchdog/server/src/WatchdogInternalHandler.h
index a2b4892..e23620e 100644
--- a/cpp/watchdog/server/src/WatchdogInternalHandler.h
+++ b/cpp/watchdog/server/src/WatchdogInternalHandler.h
@@ -91,8 +91,9 @@
configs) override;
android::binder::Status actionTakenOnResourceOveruse(
const std::vector<
- android::automotive::watchdog::internal::PackageResourceOveruseAction>&
- actions);
+ android::automotive::watchdog::internal::PackageResourceOveruseAction>& actions)
+ override;
+ android::binder::Status controlProcessHealthCheck(bool disable) override;
protected:
void terminate() {
diff --git a/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp b/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
index efa9eef..4646a11 100644
--- a/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
+++ b/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
@@ -470,6 +470,19 @@
ASSERT_FALSE(status.isOk()) << status;
}
+TEST_F(WatchdogInternalHandlerTest, TestControlProcessHealthCheck) {
+ setSystemCallingUid();
+ EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/true)).Times(1);
+ Status status = mWatchdogInternalHandler->controlProcessHealthCheck(false);
+ ASSERT_TRUE(status.isOk()) << status;
+}
+
+TEST_F(WatchdogInternalHandlerTest, TestErrorOnControlProcessHealthCheckWithNonSystemCallingUid) {
+ EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(_)).Times(0);
+ Status status = mWatchdogInternalHandler->controlProcessHealthCheck(false);
+ ASSERT_FALSE(status.isOk()) << status;
+}
+
} // namespace watchdog
} // namespace automotive
} // namespace android
diff --git a/service/src/com/android/car/CarShellCommand.java b/service/src/com/android/car/CarShellCommand.java
index bad6b71..576aad2 100644
--- a/service/src/com/android/car/CarShellCommand.java
+++ b/service/src/com/android/car/CarShellCommand.java
@@ -18,6 +18,7 @@
import static android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME;
import static android.car.Car.PERMISSION_CAR_POWER;
import static android.car.Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG;
+import static android.car.Car.PERMISSION_USE_CAR_WATCHDOG;
import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.ASSOCIATE_CURRENT_USER;
import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.DISASSOCIATE_ALL_USERS;
import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.DISASSOCIATE_CURRENT_USER;
@@ -197,6 +198,8 @@
"watchdog-io-set-3p-foreground-bytes";
private static final String COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES =
"watchdog-io-get-3p-foreground-bytes";
+ private static final String COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK =
+ "watchdog-control-health-check";
private static final String[] CREATE_OR_MANAGE_USERS_PERMISSIONS = new String[] {
android.Manifest.permission.CREATE_USERS,
@@ -269,6 +272,8 @@
PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG);
USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES,
PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG);
+ USER_BUILD_COMMAND_TO_PERMISSION_MAP.put(COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK,
+ PERMISSION_USE_CAR_WATCHDOG);
}
private static final String PARAM_DAY_MODE = "day";
@@ -612,6 +617,10 @@
pw.printf("\t%s\n", COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES);
pw.println("\t Gets third-party apps foreground I/O overuse threshold");
+
+ pw.printf("\t%s true|false\n", COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK);
+ pw.println("\t Enables/disables car watchdog process health check.");
+ pw.println("\t Set to true to disable the process health check.");
}
private static int showInvalidArguments(IndentingPrintWriter pw) {
@@ -940,7 +949,9 @@
case COMMAND_WATCHDOG_IO_GET_3P_FOREGROUND_BYTES:
getWatchdogIoThirdPartyForegroundBytes(writer);
break;
-
+ case COMMAND_WATCHDOG_CONTROL_PROCESS_HEALTH_CHECK:
+ controlWatchdogProcessHealthCheck(args, writer);
+ break;
default:
writer.println("Unknown command: \"" + cmd + "\"");
showHelp(writer);
@@ -2200,6 +2211,19 @@
.setIoOveruseConfiguration(configuration.getIoOveruseConfiguration());
}
+ private void controlWatchdogProcessHealthCheck(String[] args, IndentingPrintWriter writer) {
+ if (args.length != 2) {
+ showInvalidArguments(writer);
+ return;
+ }
+ boolean newState = Boolean.parseBoolean(args[1]);
+ if (!newState && !args[1].equalsIgnoreCase("false")) {
+ writer.println("Failed to parse argument. Valid arguments: true | false");
+ return;
+ }
+ mCarWatchdogService.controlProcessHealthCheck(newState);
+ }
+
// Check if the given property is global
private static boolean isPropertyAreaTypeGlobal(@Nullable String property) {
if (property == null) {
diff --git a/service/src/com/android/car/watchdog/CarWatchdogService.java b/service/src/com/android/car/watchdog/CarWatchdogService.java
index fccaa8b..4bbb40a 100644
--- a/service/src/com/android/car/watchdog/CarWatchdogService.java
+++ b/service/src/com/android/car/watchdog/CarWatchdogService.java
@@ -326,6 +326,14 @@
return mWatchdogPerfHandler.getResourceOveruseConfigurations(resourceOveruseFlag);
}
+ /**
+ * Enables/disables the watchdog daemon client health check process.
+ */
+ public void controlProcessHealthCheck(boolean disable) {
+ ICarImpl.assertPermission(mContext, Car.PERMISSION_USE_CAR_WATCHDOG);
+ mWatchdogProcessHandler.controlProcessHealthCheck(disable);
+ }
+
private void postRegisterToDaemonMessage() {
CarServiceUtils.runOnMain(() -> {
synchronized (mLock) {
diff --git a/service/src/com/android/car/watchdog/WatchdogProcessHandler.java b/service/src/com/android/car/watchdog/WatchdogProcessHandler.java
index cce3d15..c935f0a 100644
--- a/service/src/com/android/car/watchdog/WatchdogProcessHandler.java
+++ b/service/src/com/android/car/watchdog/WatchdogProcessHandler.java
@@ -240,6 +240,16 @@
}
}
+ /** Enables/disables the watchdog daemon client health check process. */
+ void controlProcessHealthCheck(boolean disable) {
+ try {
+ mCarWatchdogDaemonHelper.controlProcessHealthCheck(disable);
+ } catch (RemoteException e) {
+ Slogf.w(CarWatchdogService.TAG,
+ "Cannot enable/disable the car watchdog daemon health check process: %s", e);
+ }
+ }
+
private void onClientDeath(ICarWatchdogServiceCallback client, int timeout) {
synchronized (mLock) {
removeClientLocked(client.asBinder(), timeout);
diff --git a/tests/carservice_unit_test/src/android/car/watchdoglib/CarWatchdogDaemonHelperTest.java b/tests/carservice_unit_test/src/android/car/watchdoglib/CarWatchdogDaemonHelperTest.java
index c67d3d8..99bbc4c 100644
--- a/tests/carservice_unit_test/src/android/car/watchdoglib/CarWatchdogDaemonHelperTest.java
+++ b/tests/carservice_unit_test/src/android/car/watchdoglib/CarWatchdogDaemonHelperTest.java
@@ -193,6 +193,13 @@
verify(mFakeCarWatchdog).actionTakenOnResourceOveruse(eq(actions));
}
+ @Test
+ public void testIndirectCall_controlProcessHealthCheck() throws Exception {
+ mCarWatchdogDaemonHelper.controlProcessHealthCheck(true);
+
+ verify(mFakeCarWatchdog).controlProcessHealthCheck(eq(true));
+ }
+
/*
* Test that the {@link CarWatchdogDaemonHelper} throws {@code IllegalArgumentException} when
* trying to register already-registered service again.
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java b/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java
index b12aa27..8140e79 100644
--- a/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/watchdog/CarWatchdogServiceUnitTest.java
@@ -31,6 +31,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyList;
@@ -1245,6 +1246,23 @@
assertPackageInfoEquals(actualPackageInfos, expectedPackageInfos);
}
+ @Test
+ public void testSetProcessHealthCheckEnabled() throws Exception {
+ mCarWatchdogService.controlProcessHealthCheck(true);
+
+ verify(mMockCarWatchdogDaemon).controlProcessHealthCheck(eq(true));
+ }
+
+ @Test
+ public void testSetProcessHealthCheckEnabledWithDisconnectedDaemon() throws Exception {
+ crashWatchdogDaemon();
+
+ assertThrows(IllegalStateException.class,
+ () -> mCarWatchdogService.controlProcessHealthCheck(false));
+
+ verify(mMockCarWatchdogDaemon, never()).controlProcessHealthCheck(anyBoolean());
+ }
+
private void mockWatchdogDaemon() {
when(mMockBinder.queryLocalInterface(anyString())).thenReturn(mMockCarWatchdogDaemon);
when(mMockCarWatchdogDaemon.asBinder()).thenReturn(mMockBinder);