Merge "Remove config_systemAutomotiveCluster from car_product overlay." into sc-v2-dev
diff --git a/FrameworkPackageStubs/res/values-my/strings.xml b/FrameworkPackageStubs/res/values-my/strings.xml
index 7becb7d..2cf332a 100644
--- a/FrameworkPackageStubs/res/values-my/strings.xml
+++ b/FrameworkPackageStubs/res/values-my/strings.xml
@@ -3,6 +3,6 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="6179574017413146651">"လုပ်ဆောင်ချက် အပိုင်း"</string>
<string name="message_not_supported" msgid="133939962837892495">"ဤအလုပ်ကို မည်သည့်အက်ပ်မျှ မစီမံနိုင်ပါ"</string>
- <string name="pip_not_supported" msgid="8681268258599412706">"ဤစက်တွင် \'တစ်ခုပေါ်တစ်ခုထပ်၍ ဖွင့်ခြင်း\' သုံး၍မရပါ"</string>
+ <string name="pip_not_supported" msgid="8681268258599412706">"ဤစက်တွင် \'နှစ်ခုထပ်၍ကြည့်ခြင်း\' သုံး၍မရပါ"</string>
<string name="stub_name" msgid="3987164490218189006">"မရှိ"</string>
</resources>
diff --git a/car-internal-lib/src/com/android/car/internal/ICarServiceHelper.aidl b/car-internal-lib/src/com/android/car/internal/ICarServiceHelper.aidl
index cabbc07..82d3cf3 100644
--- a/car-internal-lib/src/com/android/car/internal/ICarServiceHelper.aidl
+++ b/car-internal-lib/src/com/android/car/internal/ICarServiceHelper.aidl
@@ -18,6 +18,7 @@
import android.content.ComponentName;
import android.content.pm.UserInfo;
+import android.os.UserHandle;
import java.util.List;
@@ -61,4 +62,10 @@
* {@code featureId} in the display of {@code displayId}.
*/
int setPersistentActivity(in ComponentName activity, int displayId, int featureId);
+
+ /**
+ * Saves initial user information in System Server. If car service crashes, Car service helepr
+ * service would send back this information.
+ */
+ void sendInitialUser(in UserHandle user);
}
diff --git a/car-internal-lib/src/com/android/car/internal/ICarSystemServerClient.aidl b/car-internal-lib/src/com/android/car/internal/ICarSystemServerClient.aidl
index 3020646..a31024b 100644
--- a/car-internal-lib/src/com/android/car/internal/ICarSystemServerClient.aidl
+++ b/car-internal-lib/src/com/android/car/internal/ICarSystemServerClient.aidl
@@ -17,6 +17,7 @@
package com.android.car.internal;
import android.content.pm.UserInfo;
+import android.os.UserHandle;
import com.android.internal.os.IResultReceiver;
@@ -53,4 +54,13 @@
* @param callback used to trigger the factory reset.
*/
void onFactoryReset(IResultReceiver callback);
+
+ /**
+ * Initial user is decided by HAL and information is saved in CarUserService. It is possible
+ * that car service may crash and this information will be lost. To avoid this situation,
+ * initial user information is saved in System Service using
+ * {@link ICarServiceHelper.sendInitialUser}. If car service reconnects after crash, then this
+ * call will set the initial user information in CarUserService.
+ */
+ void setInitialUser(in UserHandle user);
}
diff --git a/car-lib/src/android/car/input/CarInputManager.java b/car-lib/src/android/car/input/CarInputManager.java
index 7eddcf8..6f54c79 100644
--- a/car-lib/src/android/car/input/CarInputManager.java
+++ b/car-lib/src/android/car/input/CarInputManager.java
@@ -159,7 +159,7 @@
public static final int INPUT_TYPE_DPAD_KEYS = 100;
/**
- * This is for all {@code KeyEvent#KEYCODE_NAVIGATE_*} keys.
+ * This is for all {@code KeyEvent#KEYCODE_NAVIGATE_*} keys and {@link KeyEvent#KEYCODE_BACK}.
*
* @hide
*/
diff --git a/car-lib/src/com/android/car/internal/common/EventLogTags.logtags b/car-lib/src/com/android/car/internal/common/EventLogTags.logtags
index 45fdfe9..ce07e2b 100644
--- a/car-lib/src/com/android/car/internal/common/EventLogTags.logtags
+++ b/car-lib/src/com/android/car/internal/common/EventLogTags.logtags
@@ -66,7 +66,7 @@
#### User-related tags (range 150100 - 150199)
-150100 car_user_svc_initial_user_info_req (request_type|1),(timeout|1)
+150100 car_user_svc_initial_user_info_req (request_type|1),(timeout|1),(current_user_id|1),(current_user_flags|1),(number_existing_users|1)
150101 car_user_svc_initial_user_info_resp (status|1),(action|1),(user_id|1),(flags|1),(safe_name|3),(user_locales|3)
150103 car_user_svc_set_initial_user (user_id|1)
150104 car_user_svc_set_lifecycle_listener (uid|1),(package_name|3)
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/color/car_radio_button_checked_color.xml b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_radio_button_checked_color.xml
new file mode 100644
index 0000000..e29e5b6
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_radio_button_checked_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:alpha="?android:attr/disabledAlpha"
+ android:color="?android:attr/colorControlActivated"/>
+ <item android:color="?android:attr/colorControlActivated"/>
+</selector>
+
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/color/car_radio_button_unchecked_color.xml b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_radio_button_unchecked_color.xml
new file mode 100644
index 0000000..2fe7d66
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_radio_button_unchecked_color.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:alpha="?android:attr/disabledAlpha"
+ android:color="?android:attr/colorControlNormal"/>
+ <item android:color="?android:attr/colorControlNormal"/>
+</selector>
+
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button.xml b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button.xml
new file mode 100644
index 0000000..aa95e82
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 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.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="false" android:drawable="@drawable/car_radio_button_unchecked" />
+ <item android:state_checked="true" android:drawable="@drawable/car_radio_button_checked" />
+</selector>
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button_checked.xml b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button_checked.xml
new file mode 100644
index 0000000..22803ab
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button_checked.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 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.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:gravity="center">
+ <shape
+ android:shape="oval">
+ <size
+ android:width="@dimen/car_radio_button_outer_ring_size"
+ android:height="@dimen/car_radio_button_outer_ring_size" />
+ <stroke
+ android:width="@dimen/car_radio_button_outer_ring_stroke_width"
+ android:color="@color/car_radio_button_checked_color"/>
+ </shape>
+ </item>
+ <item android:gravity="center">
+ <shape
+ android:shape="oval">
+ <size
+ android:width="@dimen/car_radio_button_inner_circle_size"
+ android:height="@dimen/car_radio_button_inner_circle_size" />
+ <solid android:color="@color/car_radio_button_checked_color"/>
+ </shape>
+ </item>
+</layer-list>
+
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button_unchecked.xml b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button_unchecked.xml
new file mode 100644
index 0000000..f55d85b
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_radio_button_unchecked.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 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.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <size
+ android:width="@dimen/car_radio_button_outer_ring_size"
+ android:height="@dimen/car_radio_button_outer_ring_size" />
+ <stroke
+ android:width="@dimen/car_radio_button_outer_ring_stroke_width"
+ android:color="@color/car_radio_button_unchecked_color" />
+</shape>
+
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/values/dimens.xml b/car_product/overlay-visual/frameworks/base/core/res/res/values/dimens.xml
index b1ab72a..78bb728 100644
--- a/car_product/overlay-visual/frameworks/base/core/res/res/values/dimens.xml
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/values/dimens.xml
@@ -146,6 +146,11 @@
<!-- car_switch_thumb_size + car_switch_thumb_stroke_width == car_switch_track_height -->
<dimen name="car_switch_thumb_size">40dp</dimen>
+ <!-- Radio button dimensions -->
+ <dimen name="car_radio_button_outer_ring_size">45dp</dimen>
+ <dimen name="car_radio_button_outer_ring_stroke_width">2dp</dimen>
+ <dimen name="car_radio_button_inner_circle_size">32dp</dimen>
+
<!-- SeekBar dimensions. -->
<!-- Allows thumb to extend out of the range of the track. -->
<!-- For more information see android.widget.SeekBar#attr_android:thumbOffset. -->
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/values/styles_device_default.xml b/car_product/overlay-visual/frameworks/base/core/res/res/values/styles_device_default.xml
index 191b9ac..1038815 100644
--- a/car_product/overlay-visual/frameworks/base/core/res/res/values/styles_device_default.xml
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/values/styles_device_default.xml
@@ -106,6 +106,11 @@
<item name="android:button">@*android:drawable/car_checkbox</item>
</style>
+ <style name="Widget.DeviceDefault.CompoundButton.RadioButton"
+ parent="android:Widget.DeviceDefault.CompoundButton.RadioButton">
+ <item name="android:button">@drawable/car_radio_button</item>
+ </style>
+
<style name="Widget.DeviceDefault.CompoundButton.Switch"
parent="android:Widget.Material.CompoundButton.Switch">
<item name="android:thumb">@drawable/car_switch_thumb</item>
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/values/themes_device_defaults.xml b/car_product/overlay-visual/frameworks/base/core/res/res/values/themes_device_defaults.xml
index 45c33d3..1e81822 100644
--- a/car_product/overlay-visual/frameworks/base/core/res/res/values/themes_device_defaults.xml
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/values/themes_device_defaults.xml
@@ -43,6 +43,7 @@
<item name="android:textAppearanceListItemSmall">@*android:style/TextAppearance.DeviceDefault.Large</item>
<item name="android:textAppearanceListItemSecondary">@*android:style/TextAppearance.DeviceDefault.Small</item>
<item name="android:actionBarSize">@*android:dimen/car_app_bar_height</item>
+ <item name="android:radioButtonStyle">@style/Widget.DeviceDefault.CompoundButton.RadioButton</item>
<item name="colorSwitchThumbNormal">@color/car_switch_thumb_color</item>
<item name="colorSwitchTrack">@color/car_switch_track_background_selector</item>
diff --git a/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl b/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl
index c9ece21..61b65c7 100644
--- a/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl
+++ b/cpp/watchdog/aidl/android/automotive/watchdog/internal/ICarWatchdog.aidl
@@ -19,7 +19,6 @@
import android.automotive.watchdog.internal.ComponentType;
import android.automotive.watchdog.internal.ICarWatchdogMonitor;
import android.automotive.watchdog.internal.ICarWatchdogServiceForSystem;
-import android.automotive.watchdog.internal.PackageResourceOveruseAction;
import android.automotive.watchdog.internal.ResourceOveruseConfiguration;
import android.automotive.watchdog.internal.StateType;
@@ -121,14 +120,6 @@
*/
List<ResourceOveruseConfiguration> getResourceOveruseConfigurations();
- /**
- * CarWatchdogService notifies the native service with the actions taken on the resource overusing
- * applications.
- *
- * @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.
diff --git a/cpp/watchdog/aidl/android/automotive/watchdog/internal/PackageResourceOveruseAction.aidl b/cpp/watchdog/aidl/android/automotive/watchdog/internal/PackageResourceOveruseAction.aidl
deleted file mode 100644
index 521b604..0000000
--- a/cpp/watchdog/aidl/android/automotive/watchdog/internal/PackageResourceOveruseAction.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 android.automotive.watchdog.internal;
-
-import android.automotive.watchdog.internal.PackageIdentifier;
-import android.automotive.watchdog.internal.ResourceOveruseActionType;
-import android.automotive.watchdog.ResourceType;
-
-/**
- * Structure that describes the action taken on a package due to resource overuse.
- */
-parcelable PackageResourceOveruseAction {
- /**
- * Identifier for the package.
- */
- PackageIdentifier packageIdentifier;
-
- /**
- * Resources that were overused.
- */
- ResourceType[] resourceTypes;
-
- /**
- * Action taken on the package.
- */
- ResourceOveruseActionType resourceOveruseActionType = ResourceOveruseActionType.NOT_KILLED;
-}
diff --git a/cpp/watchdog/aidl/android/automotive/watchdog/internal/ResourceOveruseActionType.aidl b/cpp/watchdog/aidl/android/automotive/watchdog/internal/ResourceOveruseActionType.aidl
deleted file mode 100644
index 0d7d935..0000000
--- a/cpp/watchdog/aidl/android/automotive/watchdog/internal/ResourceOveruseActionType.aidl
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 android.automotive.watchdog.internal;
-
-/**
- * Describes the action taken on resource overuse.
- */
-@Backing(type="int")
-enum ResourceOveruseActionType {
- /**
- * The package is not killed because either it is not killable, internal error occurred, or
- * already disabled.
- */
- NOT_KILLED,
-
- /**
- * The package is not killed as the user opted-out the package from killing on resource overuse.
- */
- NOT_KILLED_USER_OPTED,
-
- /**
- * The package is killed on resource overuse.
- */
- KILLED,
-
- /**
- * The package is killed as it has recurring resource overuse pattern.
- */
- KILLED_RECURRING_OVERUSE,
-}
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 e7229ba..945383a 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
@@ -23,7 +23,6 @@
import android.automotive.watchdog.internal.ICarWatchdog;
import android.automotive.watchdog.internal.ICarWatchdogMonitor;
import android.automotive.watchdog.internal.ICarWatchdogServiceForSystem;
-import android.automotive.watchdog.internal.PackageResourceOveruseAction;
import android.automotive.watchdog.internal.ResourceOveruseConfiguration;
import android.os.Handler;
import android.os.IBinder;
@@ -280,18 +279,6 @@
}
/**
- * Notifies car watchdog daemon with the actions taken on resource overuse.
- *
- * @param actions List of actions taken on resource overuse. One action taken per resource
- * overusing user package.
- * @throws RemoteException
- */
- public void actionTakenOnResourceOveruse(List<PackageResourceOveruseAction> actions)
- throws RemoteException {
- invokeDaemonMethod((daemon) -> daemon.actionTakenOnResourceOveruse(actions));
- }
-
- /**
* Enable/disable the internal client health check process.
* Disabling would stop the ANR killing process.
*
diff --git a/cpp/watchdog/server/src/IoOveruseMonitor.cpp b/cpp/watchdog/server/src/IoOveruseMonitor.cpp
index 1164a2a..0ebe0d4 100644
--- a/cpp/watchdog/server/src/IoOveruseMonitor.cpp
+++ b/cpp/watchdog/server/src/IoOveruseMonitor.cpp
@@ -50,7 +50,6 @@
using ::android::automotive::watchdog::internal::PackageIdentifier;
using ::android::automotive::watchdog::internal::PackageInfo;
using ::android::automotive::watchdog::internal::PackageIoOveruseStats;
-using ::android::automotive::watchdog::internal::PackageResourceOveruseAction;
using ::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
using ::android::automotive::watchdog::internal::UidType;
using ::android::automotive::watchdog::internal::UserPackageIoUsageStats;
@@ -472,7 +471,6 @@
if (DEBUG) {
ALOGD("Notified native packages on I/O overuse");
}
- // TODO(b/184310189): Upload I/O overuse metrics for native packages.
}
Result<void> IoOveruseMonitor::updateResourceOveruseConfigurations(
@@ -512,15 +510,6 @@
return {};
}
-Result<void> IoOveruseMonitor::actionTakenOnIoOveruse(
- [[maybe_unused]] const std::vector<PackageResourceOveruseAction>& actions) {
- // TODO(b/184310189): Upload metrics.
- if (DEBUG) {
- ALOGD("Recorded action taken on I/O overuse");
- }
- return {};
-}
-
Result<void> IoOveruseMonitor::addIoOveruseListener(const sp<IResourceOveruseListener>& listener) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
uid_t callingUid = IPCThreadState::self()->getCallingUid();
diff --git a/cpp/watchdog/server/src/IoOveruseMonitor.h b/cpp/watchdog/server/src/IoOveruseMonitor.h
index 57c01c0..5fa91aa 100644
--- a/cpp/watchdog/server/src/IoOveruseMonitor.h
+++ b/cpp/watchdog/server/src/IoOveruseMonitor.h
@@ -31,7 +31,6 @@
#include <android/automotive/watchdog/internal/IoOveruseConfiguration.h>
#include <android/automotive/watchdog/internal/PackageInfo.h>
#include <android/automotive/watchdog/internal/PackageIoOveruseStats.h>
-#include <android/automotive/watchdog/internal/PackageResourceOveruseAction.h>
#include <utils/Mutex.h>
#include <time.h>
@@ -81,10 +80,6 @@
virtual android::base::Result<void> getResourceOveruseConfigurations(
std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
configs) const = 0;
- virtual android::base::Result<void> actionTakenOnIoOveruse(
- const std::vector<
- android::automotive::watchdog::internal::PackageResourceOveruseAction>&
- actions) = 0;
// Below methods support APIs from ICarWatchdog.aidl. Please refer to the AIDL for description.
virtual android::base::Result<void> addIoOveruseListener(
@@ -155,11 +150,6 @@
std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
configs) const override;
- android::base::Result<void> actionTakenOnIoOveruse(
- const std::vector<
- android::automotive::watchdog::internal::PackageResourceOveruseAction>& actions)
- override;
-
android::base::Result<void> addIoOveruseListener(
const sp<IResourceOveruseListener>& listener) override;
diff --git a/cpp/watchdog/server/src/WatchdogInternalHandler.cpp b/cpp/watchdog/server/src/WatchdogInternalHandler.cpp
index be49ff9..2441ccf 100644
--- a/cpp/watchdog/server/src/WatchdogInternalHandler.cpp
+++ b/cpp/watchdog/server/src/WatchdogInternalHandler.cpp
@@ -36,7 +36,6 @@
using aawi::ComponentType;
using aawi::GarageMode;
using aawi::ICarWatchdogServiceForSystem;
-using aawi::PackageResourceOveruseAction;
using aawi::PowerCycle;
using aawi::ResourceOveruseConfiguration;
using ::android::sp;
@@ -256,18 +255,6 @@
return Status::ok();
}
-Status WatchdogInternalHandler::actionTakenOnResourceOveruse(
- const std::vector<PackageResourceOveruseAction>& actions) {
- Status status = checkSystemUser();
- if (!status.isOk()) {
- return status;
- }
- if (const auto result = mIoOveruseMonitor->actionTakenOnIoOveruse(actions); !result.ok()) {
- return fromExceptionCode(result.error().code(), result.error().message());
- }
- return Status::ok();
-}
-
Status WatchdogInternalHandler::controlProcessHealthCheck(bool disable) {
Status status = checkSystemUser();
if (!status.isOk()) {
diff --git a/cpp/watchdog/server/src/WatchdogInternalHandler.h b/cpp/watchdog/server/src/WatchdogInternalHandler.h
index e23620e..1000c8e 100644
--- a/cpp/watchdog/server/src/WatchdogInternalHandler.h
+++ b/cpp/watchdog/server/src/WatchdogInternalHandler.h
@@ -26,7 +26,6 @@
#include <android/automotive/watchdog/internal/ComponentType.h>
#include <android/automotive/watchdog/internal/ICarWatchdogMonitor.h>
#include <android/automotive/watchdog/internal/ICarWatchdogServiceForSystem.h>
-#include <android/automotive/watchdog/internal/PackageResourceOveruseAction.h>
#include <android/automotive/watchdog/internal/ResourceOveruseConfiguration.h>
#include <android/automotive/watchdog/internal/StateType.h>
#include <binder/Status.h>
@@ -89,10 +88,6 @@
android::binder::Status getResourceOveruseConfigurations(
std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
configs) override;
- android::binder::Status actionTakenOnResourceOveruse(
- const std::vector<
- android::automotive::watchdog::internal::PackageResourceOveruseAction>& actions)
- override;
android::binder::Status controlProcessHealthCheck(bool disable) override;
protected:
diff --git a/cpp/watchdog/server/tests/MockIoOveruseMonitor.h b/cpp/watchdog/server/tests/MockIoOveruseMonitor.h
index a9d677e..294276b 100644
--- a/cpp/watchdog/server/tests/MockIoOveruseMonitor.h
+++ b/cpp/watchdog/server/tests/MockIoOveruseMonitor.h
@@ -45,11 +45,6 @@
android::base::Result<void>, getResourceOveruseConfigurations,
(std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*),
(const, override));
- MOCK_METHOD(android::base::Result<void>, actionTakenOnIoOveruse,
- (const std::vector<
- android::automotive::watchdog::internal::PackageResourceOveruseAction>&
- actions),
- (override));
MOCK_METHOD(android::base::Result<void>, addIoOveruseListener,
(const sp<IResourceOveruseListener>&), (override));
MOCK_METHOD(android::base::Result<void>, removeIoOveruseListener,
diff --git a/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp b/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
index 4646a11..a5abbc4 100644
--- a/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
+++ b/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
@@ -45,7 +45,6 @@
using aawi::GarageMode;
using aawi::ICarWatchdogServiceForSystem;
using aawi::ICarWatchdogServiceForSystemDefault;
-using aawi::PackageResourceOveruseAction;
using aawi::PowerCycle;
using aawi::ResourceOveruseConfiguration;
using ::android::sp;
@@ -454,22 +453,6 @@
ASSERT_FALSE(status.isOk()) << status;
}
-TEST_F(WatchdogInternalHandlerTest, TestActionTakenOnResourceOveruse) {
- setSystemCallingUid();
- EXPECT_CALL(*mMockIoOveruseMonitor, actionTakenOnIoOveruse(_)).WillOnce(Return(Result<void>()));
- Status status = mWatchdogInternalHandler->actionTakenOnResourceOveruse(
- std::vector<PackageResourceOveruseAction>{});
- ASSERT_TRUE(status.isOk()) << status;
-}
-
-TEST_F(WatchdogInternalHandlerTest,
- TestErrorOnActionTakenOnResourceOveruseWithNonSystemCallingUid) {
- EXPECT_CALL(*mMockIoOveruseMonitor, actionTakenOnIoOveruse(_)).Times(0);
- Status status = mWatchdogInternalHandler->actionTakenOnResourceOveruse(
- std::vector<PackageResourceOveruseAction>{});
- ASSERT_FALSE(status.isOk()) << status;
-}
-
TEST_F(WatchdogInternalHandlerTest, TestControlProcessHealthCheck) {
setSystemCallingUid();
EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/true)).Times(1);
diff --git a/packages/CarShell/AndroidManifest.xml b/packages/CarShell/AndroidManifest.xml
index 40420d7..c07083c 100644
--- a/packages/CarShell/AndroidManifest.xml
+++ b/packages/CarShell/AndroidManifest.xml
@@ -21,6 +21,8 @@
coreApp="true"
android:sharedUserId="android.uid.shell"
>
+ <!-- Permission required for ATS tests - AtsAudioDeviceTest#resetVolumeMute-->
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
<!-- To pass GtsInstallPackagesWhitelistDeviceTestCases b/173156153 -->
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<!-- Permission required for ATS tests - AtsCarHostTestCases, AtsCarDeviceApp -->
diff --git a/service/src/com/android/car/CarShellCommand.java b/service/src/com/android/car/CarShellCommand.java
index 19d8a1a..d70151d 100644
--- a/service/src/com/android/car/CarShellCommand.java
+++ b/service/src/com/android/car/CarShellCommand.java
@@ -1633,8 +1633,8 @@
}
private void getInitialUser(IndentingPrintWriter writer) {
- android.content.pm.UserInfo user = mCarUserService.getInitialUser();
- writer.println(user == null ? NO_INITIAL_USER : user.id);
+ UserHandle user = mCarUserService.getInitialUser();
+ writer.println(user == null ? NO_INITIAL_USER : user.getIdentifier());
}
private void getUserAuthAssociation(String[] args, IndentingPrintWriter writer) {
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index 4b7c75d..c9fde05 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -46,6 +46,7 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.Trace;
+import android.os.UserHandle;
import android.os.UserManager;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
@@ -962,5 +963,10 @@
mCarPowerManagementService.setFactoryResetCallback(callback);
FactoryResetActivity.sendNotification(mContext, callback);
}
+
+ @Override
+ public void setInitialUser(UserHandle user) {
+ mCarUserService.setInitialUserFromSystemServer(user);
+ }
}
}
diff --git a/service/src/com/android/car/InputCaptureClientController.java b/service/src/com/android/car/InputCaptureClientController.java
index 5f9ebfa..4e866a5 100644
--- a/service/src/com/android/car/InputCaptureClientController.java
+++ b/service/src/com/android/car/InputCaptureClientController.java
@@ -79,6 +79,7 @@
entry(KeyEvent.KEYCODE_NAVIGATE_OUT, CarInputManager.INPUT_TYPE_NAVIGATE_KEYS),
entry(KeyEvent.KEYCODE_NAVIGATE_NEXT, CarInputManager.INPUT_TYPE_NAVIGATE_KEYS),
entry(KeyEvent.KEYCODE_NAVIGATE_PREVIOUS, CarInputManager.INPUT_TYPE_NAVIGATE_KEYS),
+ entry(KeyEvent.KEYCODE_BACK, CarInputManager.INPUT_TYPE_NAVIGATE_KEYS),
entry(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
CarInputManager.INPUT_TYPE_SYSTEM_NAVIGATE_KEYS),
entry(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
diff --git a/service/src/com/android/car/evs/CarEvsService.java b/service/src/com/android/car/evs/CarEvsService.java
index 7af1adb..961707f 100644
--- a/service/src/com/android/car/evs/CarEvsService.java
+++ b/service/src/com/android/car/evs/CarEvsService.java
@@ -24,6 +24,7 @@
import static android.car.evs.CarEvsManager.SERVICE_STATE_REQUESTED;
import static android.car.evs.CarEvsManager.SERVICE_STATE_UNAVAILABLE;
import static android.car.evs.CarEvsManager.STREAM_EVENT_STREAM_STOPPED;
+import static android.hardware.display.DisplayManager.DisplayListener;
import static com.android.car.CarLog.TAG_EVS;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -51,6 +52,7 @@
import android.hardware.automotive.vehicle.V2_0.VehicleArea;
import android.hardware.automotive.vehicle.V2_0.VehicleGear;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.hardware.display.DisplayManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -64,6 +66,7 @@
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
+import android.view.Display;
import com.android.car.CarPropertyService;
import com.android.car.CarServiceBase;
@@ -159,6 +162,7 @@
private final Context mContext;
private final EvsHalService mEvsHalService;
private final CarPropertyService mPropertyService;
+ private final DisplayManager mDisplayManager; // To monitor the default display's state
private final Object mLock = new Object();
private final ComponentName mEvsCameraActivity;
@@ -224,6 +228,48 @@
}
};
+ private final DisplayManager.DisplayListener mDisplayListener =
+ new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ // Nothing to do
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ // Nothing to do
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ // We are interested only in the default display.
+ return;
+ }
+
+ Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ switch (display.getState()) {
+ case Display.STATE_ON:
+ // We may want to request the system viewer.
+ if (!requestActivityIfNecessaryLocked()) {
+ Slog.e(TAG_EVS, "Failed to request the system viewer");
+ }
+ break;
+
+ case Display.STATE_OFF:
+ // Stop an active client
+ if (mStreamCallback != null) {
+ stopVideoStream(mStreamCallback);
+ }
+ break;
+
+ default:
+ // Nothing to do for all other state changes
+ break;
+ }
+ }
+ };
+
// CarEvsService state machine implementation to handle all state transitions.
private final class StateMachine {
// Current state
@@ -444,10 +490,13 @@
throw new IllegalStateException("CarEvsService is in the unknown state.");
}
- // Arms the timer
- mHandler.sendMessageDelayed(obtainMessage(CarEvsService::handleActivityRequestTimeout,
- CarEvsService.this).setWhat(MSG_CHECK_ACTIVITY_REQUEST_TIMEOUT),
- STREAM_START_REQUEST_TIMEOUT_MS);
+ // Arms the timer for the high-priority request
+ if (priority == REQUEST_PRIORITY_HIGH) {
+ mHandler.sendMessageDelayed(obtainMessage(
+ CarEvsService::handleActivityRequestTimeout,
+ CarEvsService.this).setWhat(MSG_CHECK_ACTIVITY_REQUEST_TIMEOUT),
+ STREAM_START_REQUEST_TIMEOUT_MS);
+ }
mState = SERVICE_STATE_REQUESTED;
mServiceType = service;
@@ -626,8 +675,9 @@
@GuardedBy("mLock")
private boolean requestActivityIfNecessaryLocked() {
- if (!mStateEngine.checkCurrentStateRequiresActivityLocked() || mLastEvsHalEvent == null ||
- !mLastEvsHalEvent.isRequestingToStartActivity()) {
+ // TODO(b/202398413): add a test case to verify below logic
+ if (!mStateEngine.checkCurrentStateRequiresActivityLocked() &&
+ (mLastEvsHalEvent == null || !mLastEvsHalEvent.isRequestingToStartActivity())) {
return false;
}
@@ -704,6 +754,9 @@
mEvsCameraActivity = null;
}
if (DBG) Slog.d(TAG_EVS, "evsCameraActivity=" + mEvsCameraActivity);
+
+ mDisplayManager = context.getSystemService(DisplayManager.class);
+ mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
}
/** Implements EvsHalService.EvsHalEventListener to monitor VHAL properties. */
diff --git a/service/src/com/android/car/telemetry/databroker/DataSubscriber.java b/service/src/com/android/car/telemetry/databroker/DataSubscriber.java
index 9ab7604..d61d89c 100644
--- a/service/src/com/android/car/telemetry/databroker/DataSubscriber.java
+++ b/service/src/com/android/car/telemetry/databroker/DataSubscriber.java
@@ -57,12 +57,20 @@
/**
* Creates a {@link ScriptExecutionTask} and pushes it to the priority queue where the task
- * will be pending execution.
+ * will be pending execution. Flag isLargeData indicates whether data is large.
+ */
+ public void push(PersistableBundle data, boolean isLargeData) {
+ ScriptExecutionTask task = new ScriptExecutionTask(
+ this, data, SystemClock.elapsedRealtime(), isLargeData);
+ mDataBroker.addTaskToQueue(task);
+ }
+
+ /**
+ * Creates a {@link ScriptExecutionTask} and pushes it to the priority queue where the task
+ * will be pending execution. Defaults isLargeData flag to false.
*/
public void push(PersistableBundle data) {
- ScriptExecutionTask task = new ScriptExecutionTask(
- this, data, SystemClock.elapsedRealtime());
- mDataBroker.addTaskToQueue(task);
+ push(data, false);
}
/** Returns the {@link TelemetryProto.MetricsConfig}. */
diff --git a/service/src/com/android/car/telemetry/databroker/ScriptExecutionTask.java b/service/src/com/android/car/telemetry/databroker/ScriptExecutionTask.java
index 18d0512..5a995d2 100644
--- a/service/src/com/android/car/telemetry/databroker/ScriptExecutionTask.java
+++ b/service/src/com/android/car/telemetry/databroker/ScriptExecutionTask.java
@@ -17,7 +17,6 @@
package com.android.car.telemetry.databroker;
import android.car.telemetry.MetricsConfigKey;
-import android.os.Parcel;
import android.os.PersistableBundle;
import com.android.car.telemetry.TelemetryProto;
@@ -30,37 +29,17 @@
* The object can be accessed from any thread. See {@link DataSubscriber} for thread-safety.
*/
public class ScriptExecutionTask implements Comparable<ScriptExecutionTask> {
- // Key to the calculated bundle size, which doesn't contain implementation-dependent overhead
- // and other allocations. It's approximately 10% smaller than the actual size of binder parcel.
- public static final String APPROX_BUNDLE_SIZE_BYTES_KEY = "approx_bundle_size_bytes";
-
- /**
- * Binder transaction size limit is 1MB for all binders per process, so for large script input
- * file pipe will be used to transfer the data to script executor instead of binder call. This
- * is the input size threshold above which piping is used.
- */
- private static final int LARGE_SCRIPT_INPUT_SIZE_BYTES = 20 * 1024; // 20 kb
-
private final long mTimestampMillis;
private final DataSubscriber mSubscriber;
private final PersistableBundle mData;
private final boolean mIsLargeData;
ScriptExecutionTask(DataSubscriber subscriber, PersistableBundle data,
- long elapsedRealtimeMillis) {
+ long elapsedRealtimeMillis, boolean isLargeData) {
mTimestampMillis = elapsedRealtimeMillis;
mSubscriber = subscriber;
mData = data;
- if (mData.containsKey(APPROX_BUNDLE_SIZE_BYTES_KEY)) {
- mIsLargeData =
- mData.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY) > LARGE_SCRIPT_INPUT_SIZE_BYTES;
- mData.remove(APPROX_BUNDLE_SIZE_BYTES_KEY);
- } else {
- Parcel parcel = Parcel.obtain();
- parcel.writePersistableBundle(mData);
- mIsLargeData = parcel.dataSize() > LARGE_SCRIPT_INPUT_SIZE_BYTES;
- parcel.recycle();
- }
+ mIsLargeData = isLargeData;
}
/** Returns the priority of the task. */
diff --git a/service/src/com/android/car/telemetry/proto/atoms.proto b/service/src/com/android/car/telemetry/proto/atoms.proto
index ccb9021..443ec58 100644
--- a/service/src/com/android/car/telemetry/proto/atoms.proto
+++ b/service/src/com/android/car/telemetry/proto/atoms.proto
@@ -32,6 +32,7 @@
// Pulled events will start at field 10000.
oneof pulled {
ProcessMemoryState process_memory_state = 10013;
+ ProcessCpuTime process_cpu_time = 10035;
}
}
@@ -68,3 +69,10 @@
}
optional State state = 4;
}
+
+message ProcessCpuTime {
+ optional int32 uid = 1;
+ optional string process_name = 2;
+ optional int64 user_time_millis = 3;
+ optional int64 system_time_millis = 4;
+}
diff --git a/service/src/com/android/car/telemetry/proto/telemetry.proto b/service/src/com/android/car/telemetry/proto/telemetry.proto
index 4106098..f5b14a1 100644
--- a/service/src/com/android/car/telemetry/proto/telemetry.proto
+++ b/service/src/com/android/car/telemetry/proto/telemetry.proto
@@ -87,6 +87,8 @@
PROCESS_MEMORY_STATE = 2;
// Collects activity foreground/background transition events.
ACTIVITY_FOREGROUND_STATE_CHANGED = 3;
+ // Collects process CPU usage time
+ PROCESS_CPU_TIME = 4;
}
// Required.
diff --git a/service/src/com/android/car/telemetry/publisher/StatsPublisher.java b/service/src/com/android/car/telemetry/publisher/StatsPublisher.java
index be335e9..8570d6a 100644
--- a/service/src/com/android/car/telemetry/publisher/StatsPublisher.java
+++ b/service/src/com/android/car/telemetry/publisher/StatsPublisher.java
@@ -18,8 +18,11 @@
import static com.android.car.telemetry.AtomsProto.Atom.ACTIVITY_FOREGROUND_STATE_CHANGED_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.Atom.APP_START_MEMORY_STATE_CAPTURED_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.Atom.PROCESS_CPU_TIME_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.Atom.PROCESS_MEMORY_STATE_FIELD_NUMBER;
+import static java.nio.charset.StandardCharsets.UTF_16;
+
import android.app.StatsManager.StatsUnavailableException;
import android.os.Handler;
import android.os.PersistableBundle;
@@ -27,7 +30,8 @@
import android.util.LongSparseArray;
import com.android.car.CarLog;
-import com.android.car.telemetry.AtomsProto;
+import com.android.car.telemetry.AtomsProto.ProcessCpuTime;
+import com.android.car.telemetry.AtomsProto.ProcessMemoryState;
import com.android.car.telemetry.StatsLogProto;
import com.android.car.telemetry.StatsdConfigProto;
import com.android.car.telemetry.StatsdConfigProto.StatsdConfig;
@@ -74,6 +78,10 @@
static final long ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID = 5;
@VisibleForTesting
static final long ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID = 6;
+ @VisibleForTesting
+ static final long PROCESS_CPU_TIME_MATCHER_ID = 7;
+ @VisibleForTesting
+ static final long PROCESS_CPU_TIME_GAUGE_METRIC_ID = 8;
// The file that contains stats config key and stats config version
@VisibleForTesting
@@ -85,6 +93,12 @@
private static final String BUNDLE_CONFIG_KEY_PREFIX = "statsd-publisher-config-id-";
private static final String BUNDLE_CONFIG_VERSION_PREFIX = "statsd-publisher-config-version-";
+ /**
+ * Binder transaction size limit is 1MB for all binders per process, so for large script input
+ * file pipe will be used to transfer the data to script executor instead of binder call. This
+ * is the input size threshold above which piping is used.
+ */
+ private static final int SCRIPT_INPUT_SIZE_THRESHOLD_BYTES = 20 * 1024; // 20 kb
@VisibleForTesting
static final StatsdConfigProto.FieldMatcher PROCESS_MEMORY_STATE_FIELDS_MATCHER =
@@ -92,23 +106,27 @@
.setField(
PROCESS_MEMORY_STATE_FIELD_NUMBER)
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(
- AtomsProto.ProcessMemoryState.OOM_ADJ_SCORE_FIELD_NUMBER))
+ .setField(ProcessMemoryState.OOM_ADJ_SCORE_FIELD_NUMBER))
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(
- AtomsProto.ProcessMemoryState.PAGE_FAULT_FIELD_NUMBER))
+ .setField(ProcessMemoryState.PAGE_FAULT_FIELD_NUMBER))
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(
- AtomsProto.ProcessMemoryState.PAGE_MAJOR_FAULT_FIELD_NUMBER))
+ .setField(ProcessMemoryState.PAGE_MAJOR_FAULT_FIELD_NUMBER))
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(
- AtomsProto.ProcessMemoryState.RSS_IN_BYTES_FIELD_NUMBER))
+ .setField(ProcessMemoryState.RSS_IN_BYTES_FIELD_NUMBER))
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(
- AtomsProto.ProcessMemoryState.CACHE_IN_BYTES_FIELD_NUMBER))
+ .setField(ProcessMemoryState.CACHE_IN_BYTES_FIELD_NUMBER))
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(
- AtomsProto.ProcessMemoryState.SWAP_IN_BYTES_FIELD_NUMBER))
+ .setField(ProcessMemoryState.SWAP_IN_BYTES_FIELD_NUMBER))
+ .build();
+
+ @VisibleForTesting
+ static final StatsdConfigProto.FieldMatcher PROCESS_CPU_TIME_FIELDS_MATCHER =
+ StatsdConfigProto.FieldMatcher.newBuilder()
+ .setField(PROCESS_CPU_TIME_FIELD_NUMBER)
+ .addChild(StatsdConfigProto.FieldMatcher.newBuilder()
+ .setField(ProcessCpuTime.USER_TIME_MILLIS_FIELD_NUMBER))
+ .addChild(StatsdConfigProto.FieldMatcher.newBuilder()
+ .setField(ProcessCpuTime.SYSTEM_TIME_MILLIS_FIELD_NUMBER))
.build();
private final StatsManagerProxy mStatsManager;
@@ -218,6 +236,9 @@
case ACTIVITY_FOREGROUND_STATE_CHANGED:
metricId = ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID;
break;
+ case PROCESS_CPU_TIME:
+ metricId = PROCESS_CPU_TIME_GAUGE_METRIC_ID;
+ break;
default:
return;
}
@@ -226,7 +247,39 @@
"No reports for metric id " + metricId + " for config " + configKey);
return;
}
- subscriber.push(metricBundles.get(metricId));
+ PersistableBundle bundle = metricBundles.get(metricId);
+ subscriber.push(bundle, isBundleLargeData(bundle));
+ }
+
+ @VisibleForTesting
+ boolean isBundleLargeData(PersistableBundle bundle) {
+ String[] keys = bundle.keySet().toArray(new String[0]);
+ int bytes = 0;
+ for (int i = 0; i < keys.length; ++i) {
+ Object array = bundle.get(keys[i]);
+ if (array instanceof boolean[]) {
+ boolean[] boolArray = (boolean[]) array;
+ bytes += boolArray.length; // Java boolean is 1 byte
+ } else if (array instanceof long[]) {
+ long[] longArray = (long[]) array;
+ bytes += longArray.length * Long.BYTES;
+ } else if (array instanceof int[]) {
+ int[] intArray = (int[]) array;
+ bytes += intArray.length * Integer.BYTES;
+ } else if (array instanceof double[]) {
+ double[] doubleArray = (double[]) array;
+ bytes += doubleArray.length * Double.BYTES;
+ } else if (array instanceof String[]) {
+ String[] stringArray = (String[]) array;
+ for (String str : stringArray) {
+ bytes += str.getBytes(UTF_16).length;
+ }
+ }
+ }
+ if (bytes < SCRIPT_INPUT_SIZE_THRESHOLD_BYTES) {
+ return false;
+ }
+ return true;
}
private void processStatsMetadata(StatsLogProto.StatsdStatsReport statsReport) {
@@ -470,6 +523,8 @@
return buildProcessMemoryStateStatsdConfig(builder);
case ACTIVITY_FOREGROUND_STATE_CHANGED:
return buildActivityForegroundStateStatsdConfig(builder);
+ case PROCESS_CPU_TIME:
+ return buildProcessCpuTimeStatsdConfig(builder);
default:
throw new IllegalArgumentException("Unsupported metric " + metric.name());
}
@@ -503,9 +558,9 @@
.setDimensionsInWhat(StatsdConfigProto.FieldMatcher.newBuilder()
.setField(PROCESS_MEMORY_STATE_FIELD_NUMBER)
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(1)) // ProcessMemoryState.uid
+ .setField(ProcessMemoryState.UID_FIELD_NUMBER))
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(2)) // ProcessMemoryState.process_name
+ .setField(ProcessMemoryState.PROCESS_NAME_FIELD_NUMBER))
)
.setGaugeFieldsFilter(StatsdConfigProto.FieldFilter.newBuilder()
.setFields(PROCESS_MEMORY_STATE_FIELDS_MATCHER)
@@ -534,4 +589,35 @@
.setWhat(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID))
.build();
}
+
+ private static StatsdConfig buildProcessCpuTimeStatsdConfig(StatsdConfig.Builder builder) {
+ return builder
+ .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder()
+ // The id must be unique within StatsdConfig/matchers
+ .setId(PROCESS_CPU_TIME_MATCHER_ID)
+ .setSimpleAtomMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder()
+ .setAtomId(PROCESS_CPU_TIME_FIELD_NUMBER)))
+ .addGaugeMetric(StatsdConfigProto.GaugeMetric.newBuilder()
+ // The id must be unique within StatsdConfig/metrics
+ .setId(PROCESS_CPU_TIME_GAUGE_METRIC_ID)
+ .setWhat(PROCESS_CPU_TIME_MATCHER_ID)
+ .setDimensionsInWhat(StatsdConfigProto.FieldMatcher.newBuilder()
+ .setField(PROCESS_CPU_TIME_FIELD_NUMBER)
+ .addChild(StatsdConfigProto.FieldMatcher.newBuilder()
+ .setField(ProcessCpuTime.UID_FIELD_NUMBER))
+ .addChild(StatsdConfigProto.FieldMatcher.newBuilder()
+ .setField(ProcessCpuTime.PROCESS_NAME_FIELD_NUMBER))
+ )
+ .setGaugeFieldsFilter(StatsdConfigProto.FieldFilter.newBuilder()
+ .setFields(PROCESS_CPU_TIME_FIELDS_MATCHER)
+ ) // setGaugeFieldsFilter
+ .setSamplingType(
+ StatsdConfigProto.GaugeMetric.SamplingType.RANDOM_ONE_SAMPLE)
+ .setBucket(StatsdConfigProto.TimeUnit.FIVE_MINUTES)
+ )
+ .addPullAtomPackages(StatsdConfigProto.PullAtomPackages.newBuilder()
+ .setAtomId(PROCESS_CPU_TIME_FIELD_NUMBER)
+ .addPackages("AID_SYSTEM"))
+ .build();
+ }
}
diff --git a/service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java
index e201f1d..8e20eb4 100644
--- a/service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java
@@ -16,10 +16,6 @@
package com.android.car.telemetry.publisher.statsconverters;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
-
-import static java.nio.charset.StandardCharsets.UTF_16;
-
import android.os.PersistableBundle;
import android.util.SparseArray;
@@ -102,7 +98,6 @@
Map<Long, String> hashToStringMap) throws StatsConversionException {
PersistableBundle bundle = new PersistableBundle();
SparseArray<AtomFieldAccessor<T>> parserConfig = getAtomFieldAccessorMap();
- int bundleByteSize = 0;
// For each field, if set, add the values from all atoms to list and convert
for (int i = 0; i < parserConfig.size(); ++i) {
AtomFieldAccessor<T> atomFieldAccessor = parserConfig.valueAt(i);
@@ -120,13 +115,12 @@
}
valueList.add(atomFieldAccessor.getField(atomData));
}
- bundleByteSize += setPersistableBundleArrayField(
+ setPersistableBundleArrayField(
atomFieldAccessor.getFieldName(), valueList, bundle);
}
}
// Check if there are dimension fields needing conversion
if (dimensionsFieldsIds == null || dimensionsValuesList == null) {
- bundle.putInt(APPROX_BUNDLE_SIZE_BYTES_KEY, bundleByteSize);
return bundle;
}
// Create conversions for fields encoded in dimension fields
@@ -137,12 +131,11 @@
for (List<DimensionsValue> dvList : dimensionsValuesList) {
valueList.add(extractDimensionsValue(dvList.get(i), hashToStringMap));
}
- bundleByteSize += setPersistableBundleArrayField(
+ setPersistableBundleArrayField(
getAtomFieldAccessorMap().get(fieldId).getFieldName(),
valueList,
bundle);
}
- bundle.putInt(APPROX_BUNDLE_SIZE_BYTES_KEY, bundleByteSize);
return bundle;
}
@@ -186,58 +179,44 @@
* @param name key value for the bundle, corresponds to atom field name.
* @param objList the list to be converted to {@link PersistableBundle} compatible array.
* @param bundle the {@link PersistableBundle} to put the arrays to.
- * @return bytes written to PersistableBundle.
*/
- private static int setPersistableBundleArrayField(
+ private static void setPersistableBundleArrayField(
String name,
List<Object> objList,
PersistableBundle bundle) {
Object e = objList.get(0); // All elements of the list are the same type.
- int len = objList.size();
if (e instanceof Integer) {
int[] intArray = new int[objList.size()];
for (int i = 0; i < objList.size(); ++i) {
intArray[i] = (Integer) objList.get(i);
}
bundle.putIntArray(name, intArray);
- return len * Integer.BYTES;
} else if (e instanceof Long) {
long[] longArray = new long[objList.size()];
for (int i = 0; i < objList.size(); ++i) {
longArray[i] = (Long) objList.get(i);
}
bundle.putLongArray(name, longArray);
- return len * Long.BYTES;
} else if (e instanceof String) {
- String[] strArray = objList.toArray(new String[0]);
- bundle.putStringArray(name, strArray);
- int bytes = 0;
- for (String str : strArray) {
- bytes += str.getBytes(UTF_16).length;
- }
- return bytes;
+ bundle.putStringArray(name, objList.toArray(new String[0]));
} else if (e instanceof Boolean) {
boolean[] boolArray = new boolean[objList.size()];
for (int i = 0; i < objList.size(); ++i) {
boolArray[i] = (Boolean) objList.get(i);
}
bundle.putBooleanArray(name, boolArray);
- return len; // Java boolean is 1 byte
} else if (e instanceof Double) {
double[] doubleArray = new double[objList.size()];
for (int i = 0; i < objList.size(); ++i) {
doubleArray[i] = (Double) objList.get(i);
}
bundle.putDoubleArray(name, doubleArray);
- return len * Double.BYTES;
} else if (e instanceof Float) {
double[] doubleArray = new double[objList.size()];
for (int i = 0; i < objList.size(); ++i) {
doubleArray[i] = ((Float) objList.get(i)).doubleValue();
}
bundle.putDoubleArray(name, doubleArray);
- return len * Double.BYTES;
}
- return 0;
}
}
diff --git a/service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java
index a854b3a..0a574dd 100644
--- a/service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java
@@ -38,7 +38,8 @@
// Map of pulled atom cases to corresponding atom converter.
private static Map<Atom.PulledCase, AbstractAtomConverter> sPulledCaseConverters = Map.of(
- Atom.PulledCase.PROCESS_MEMORY_STATE, new ProcessMemoryStateConverter());
+ Atom.PulledCase.PROCESS_MEMORY_STATE, new ProcessMemoryStateConverter(),
+ Atom.PulledCase.PROCESS_CPU_TIME, new ProcessCpuTimeConverter());
/**
* Converts a list of atoms to separate the atoms fields values into arrays to be put into the
diff --git a/service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java
index f0803d6..52f9713 100644
--- a/service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java
@@ -16,8 +16,6 @@
package com.android.car.telemetry.publisher.statsconverters;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
-
import android.os.PersistableBundle;
import com.android.car.telemetry.AtomsProto;
@@ -58,9 +56,6 @@
}
PersistableBundle bundle = AtomListConverter.convert(atoms, null, null, null);
bundle.putLongArray(ELAPSED_TIME_NANOS, elapsedTimes);
- int bundleSize = bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)
- + elapsedTimes.length * Long.BYTES;
- bundle.putInt(APPROX_BUNDLE_SIZE_BYTES_KEY, bundleSize);
return bundle;
}
}
diff --git a/service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java
index e82a6ce..32a139c 100644
--- a/service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java
@@ -16,8 +16,6 @@
package com.android.car.telemetry.publisher.statsconverters;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
-
import android.os.PersistableBundle;
import com.android.car.telemetry.AtomsProto;
@@ -84,9 +82,6 @@
elapsedTimesArray[i] = elapsedTimes.get(i);
}
bundle.putLongArray(ELAPSED_TIME_NANOS, elapsedTimesArray);
- int bundleSize = bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)
- + elapsedTimesArray.length * Long.BYTES;
- bundle.putInt(APPROX_BUNDLE_SIZE_BYTES_KEY, bundleSize);
return bundle;
}
}
diff --git a/service/src/com/android/car/telemetry/publisher/statsconverters/ProcessCpuTimeConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/ProcessCpuTimeConverter.java
new file mode 100644
index 0000000..c56826a
--- /dev/null
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/ProcessCpuTimeConverter.java
@@ -0,0 +1,71 @@
+/*
+ * 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.publisher.statsconverters;
+
+import android.util.SparseArray;
+
+import com.android.car.telemetry.AtomsProto.Atom;
+import com.android.car.telemetry.AtomsProto.ProcessCpuTime;
+
+/**
+ * Atom data converter for atoms of type {@link ProcessCpuTime}.
+ */
+public class ProcessCpuTimeConverter extends AbstractAtomConverter<ProcessCpuTime> {
+ private static final SparseArray<AtomFieldAccessor<ProcessCpuTime>> sAtomFieldAccessorMap =
+ new SparseArray<>();
+ static {
+ sAtomFieldAccessorMap.append(1, new AtomFieldAccessor<>(
+ "uid",
+ a -> a.hasUid(),
+ a -> a.getUid()
+ ));
+ sAtomFieldAccessorMap.append(2, new AtomFieldAccessor<>(
+ "process_name",
+ a -> a.hasProcessName(),
+ a -> a.getProcessName()
+ ));
+ sAtomFieldAccessorMap.append(3, new AtomFieldAccessor<>(
+ "user_time_millis",
+ a -> a.hasUserTimeMillis(),
+ a -> a.getUserTimeMillis()
+ ));
+ sAtomFieldAccessorMap.append(4, new AtomFieldAccessor<>(
+ "system_time_millis",
+ a -> a.hasSystemTimeMillis(),
+ a -> a.getSystemTimeMillis()
+ ));
+ }
+
+ ProcessCpuTimeConverter() {
+ super();
+ }
+
+ @Override
+ SparseArray<AtomFieldAccessor<ProcessCpuTime>> getAtomFieldAccessorMap() {
+ return sAtomFieldAccessorMap;
+ }
+
+ @Override
+ ProcessCpuTime getAtomData(Atom atom) {
+ return atom.getProcessCpuTime();
+ }
+
+ @Override
+ String getAtomDataClassName() {
+ return ProcessCpuTime.class.getSimpleName();
+ }
+}
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index d535c92..07cf782 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -230,7 +230,7 @@
@Nullable
@GuardedBy("mLockUser")
- private UserInfo mInitialUser;
+ private UserHandle mInitialUser;
private IResultReceiver mUserSwitchUiReceiver;
@@ -751,7 +751,7 @@
* @hide
*/
@Nullable
- public UserInfo getInitialUser() {
+ public UserHandle getInitialUser() {
checkInteractAcrossUsersPermission("getInitialUser");
synchronized (mLockUser) {
return mInitialUser;
@@ -765,13 +765,53 @@
EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
user == null ? UserHandle.USER_NULL : user.id);
synchronized (mLockUser) {
+ if (user == null) {
+ // This mean InitialUserSetter failed and could not fallback, so the initial user
+ // was not switched (and most likely is SYSTEM_USER).
+ // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
+ Slog.wtf(TAG, "Initial user set to null");
+ mInitialUser = null;
+ return;
+ }
+ mInitialUser = user.getUserHandle();
+ }
+ sendInitialUserToSystemServer(user.getUserHandle());
+ }
+
+ /**
+ * Sets the initial foreground user after car service is crashed and reconnected.
+ */
+ public void setInitialUserFromSystemServer(@Nullable UserHandle user) {
+ if (user == null || user.getIdentifier() == UserHandle.USER_NULL) {
+ Slogf.e(TAG,
+ "setInitialUserFromSystemServer: Not setting initial user as user is NULL ");
+ return;
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Slogf.d(TAG, "setInitialUserFromSystemServer: initial User: %s", user);
+ }
+
+ synchronized (mLockUser) {
mInitialUser = user;
}
- if (user == null) {
- // This mean InitialUserSetter failed and could not fallback, so the initial user was
- // not switched (and most likely is SYSTEM_USER).
- // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
- Slog.wtf(TAG, "Initial user set to null");
+ }
+
+ private void sendInitialUserToSystemServer(UserHandle user) {
+ ICarServiceHelper iCarServiceHelper;
+ synchronized (mLockUser) {
+ iCarServiceHelper = mICarServiceHelper;
+ }
+
+ if (iCarServiceHelper == null) {
+ Slogf.e(TAG, "sendInitialUserToSystemServer: CarServiceHelper is NULL.");
+ return;
+ }
+
+ try {
+ iCarServiceHelper.sendInitialUser(user);
+ } catch (RemoteException e) {
+ Slogf.e(TAG, "Error calling sendInitialUser.", e);
}
}
@@ -830,8 +870,6 @@
private void initBootUser(int requestType) {
boolean replaceGuest =
requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
- EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
- mHalTimeoutMs);
checkManageUsersPermission("startInitialUser");
if (!isUserHalSupported()) {
@@ -842,6 +880,11 @@
}
UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
+
+ EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
+ mHalTimeoutMs, usersInfo.currentUser.userId, usersInfo.currentUser.flags,
+ usersInfo.numberUsers);
+
mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
if (resp != null) {
EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
diff --git a/service/src/com/android/car/watchdog/WatchdogPerfHandler.java b/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
index 50a4d24..0fcaeb0 100644
--- a/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
+++ b/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
@@ -16,8 +16,6 @@
package com.android.car.watchdog;
-import static android.automotive.watchdog.internal.ResourceOveruseActionType.KILLED_RECURRING_OVERUSE;
-import static android.automotive.watchdog.internal.ResourceOveruseActionType.NOT_KILLED;
import static android.car.watchdog.CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO;
import static android.car.watchdog.CarWatchdogManager.STATS_PERIOD_CURRENT_DAY;
import static android.car.watchdog.CarWatchdogManager.STATS_PERIOD_PAST_15_DAYS;
@@ -31,6 +29,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.os.Process.INVALID_UID;
import static com.android.car.CarStatsLog.CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED;
import static com.android.car.CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED;
@@ -55,10 +54,8 @@
import android.automotive.watchdog.internal.ComponentType;
import android.automotive.watchdog.internal.GarageMode;
import android.automotive.watchdog.internal.IoUsageStats;
-import android.automotive.watchdog.internal.PackageIdentifier;
import android.automotive.watchdog.internal.PackageIoOveruseStats;
import android.automotive.watchdog.internal.PackageMetadata;
-import android.automotive.watchdog.internal.PackageResourceOveruseAction;
import android.automotive.watchdog.internal.PerStateIoOveruseThreshold;
import android.automotive.watchdog.internal.ResourceSpecificConfiguration;
import android.automotive.watchdog.internal.UserPackageIoUsageStats;
@@ -166,9 +163,6 @@
@GuardedBy("mLock")
private final ArrayMap<String, PackageResourceUsage> mUsageByUserPackage = new ArrayMap<>();
@GuardedBy("mLock")
- private final List<PackageResourceOveruseAction> mOveruseActionsByUserPackage =
- new ArrayList<>();
- @GuardedBy("mLock")
private final SparseArray<ArrayList<ResourceOveruseListenerInfo>> mOveruseListenerInfosByUid =
new SparseArray<>();
@GuardedBy("mLock")
@@ -313,8 +307,10 @@
public void onGarageModeChange(@GarageMode int garageMode) {
synchronized (mLock) {
mCurrentGarageMode = garageMode;
- mCurrentUxState = UX_STATE_NO_INTERACTION;
- performOveruseHandlingLocked();
+ if (mCurrentGarageMode == GarageMode.GARAGE_MODE_ON) {
+ mCurrentUxState = UX_STATE_NO_INTERACTION;
+ performOveruseHandlingLocked();
+ }
}
}
@@ -713,13 +709,6 @@
continue;
}
overusingUserPackageKeys.add(usage.getUniqueId());
- PackageResourceOveruseAction overuseAction = new PackageResourceOveruseAction();
- overuseAction.packageIdentifier = new PackageIdentifier();
- overuseAction.packageIdentifier.name = genericPackageName;
- overuseAction.packageIdentifier.uid = usage.getUid();
- overuseAction.resourceTypes = new int[]{ ResourceType.IO };
- overuseAction.resourceOveruseActionType = NOT_KILLED;
- mOveruseActionsByUserPackage.add(overuseAction);
int killableState = usage.getKillableState();
if (killableState == KILLABLE_STATE_NEVER) {
continue;
@@ -730,9 +719,6 @@
mUserNotifiablePackages.add(id);
}
}
- if (!mOveruseActionsByUserPackage.isEmpty()) {
- mMainHandler.post(this::notifyActionsTakenOnOveruse);
- }
if (mCurrentUxState != UX_STATE_NO_DISTRACTION
&& (!mActionableUserPackages.isEmpty() || !mUserNotifiablePackages.isEmpty())) {
mMainHandler.postDelayed(() -> {
@@ -765,19 +751,35 @@
Slogf.i(TAG,
"Reset resource overuse settings and stats for user '%d' package '%s'",
usage.userId, usage.genericPackageName);
- try {
- if (packageManager.getApplicationEnabledSetting(usage.genericPackageName,
- usage.userId) != COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+ List<String> packages = Collections.singletonList(usage.genericPackageName);
+ if (usage.isSharedPackage()) {
+ int uid = usage.getUid();
+ if (uid == INVALID_UID) {
+ // Only enable packages that were disabled by the watchdog service. Ergo, if
+ // the usage doesn't have a valid UID, the package was not recently disabled
+ // by the watchdog service (unless the service crashed) and can be safely
+ // skipped.
+ Slogf.e(TAG, "Skipping enabling user %d's package %s", usage.userId,
+ usage.genericPackageName);
continue;
}
- packageManager.setApplicationEnabledSetting(usage.genericPackageName,
- COMPONENT_ENABLED_STATE_ENABLED, /* flags= */ 0, usage.userId,
- mContext.getPackageName());
- Slogf.i(TAG, "Enabled user '%d' package '%s'", usage.userId,
- usage.genericPackageName);
- } catch (RemoteException | IllegalArgumentException e) {
- Slogf.e(TAG, e, "Failed to verify and enable user %d, package '%s'",
- usage.userId, usage.genericPackageName);
+ packages = mPackageInfoHandler.getPackagesForUid(uid, usage.genericPackageName);
+ }
+ for (int pkgIdx = 0; pkgIdx < packages.size(); pkgIdx++) {
+ String packageName = packages.get(pkgIdx);
+ try {
+ if (packageManager.getApplicationEnabledSetting(packageName, usage.userId)
+ != COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+ continue;
+ }
+ packageManager.setApplicationEnabledSetting(packageName,
+ COMPONENT_ENABLED_STATE_ENABLED, /* flags= */ 0, usage.userId,
+ mContext.getPackageName());
+ Slogf.i(TAG, "Enabled user '%d' package '%s'", usage.userId, packageName);
+ } catch (RemoteException | IllegalArgumentException e) {
+ Slogf.e(TAG, e, "Failed to verify and enable user %d, package '%s'",
+ usage.userId, packageName);
+ }
}
}
}
@@ -1311,18 +1313,12 @@
if (killableState != KILLABLE_STATE_YES) {
continue;
}
- killedUserPackageKeys.add(usage.getUniqueId());
- PackageResourceOveruseAction overuseAction = new PackageResourceOveruseAction();
- overuseAction.packageIdentifier = new PackageIdentifier();
- overuseAction.packageIdentifier.name = usage.genericPackageName;
- overuseAction.packageIdentifier.uid = usage.getUid();
- overuseAction.resourceTypes = new int[]{ ResourceType.IO };
- overuseAction.resourceOveruseActionType = NOT_KILLED;
List<String> packages = Collections.singletonList(usage.genericPackageName);
if (usage.isSharedPackage()) {
- packages = mPackageInfoHandler.getPackagesForUid(
- overuseAction.packageIdentifier.uid, usage.genericPackageName);
+ packages = mPackageInfoHandler.getPackagesForUid(usage.getUid(),
+ usage.genericPackageName);
}
+ boolean isKilled = false;
for (int pkgIdx = 0; pkgIdx < packages.size(); pkgIdx++) {
String packageName = packages.get(pkgIdx);
try {
@@ -1337,28 +1333,21 @@
packageManager.setApplicationEnabledSetting(packageName,
COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, /* flags= */ 0,
usage.userId, mContext.getPackageName());
+ isKilled = true;
Slogf.i(TAG,
"Disabled user %d's package '%s' until used due to disk I/O overuse",
usage.userId, packageName);
- // TODO(b/200599130): When background apps are killed immediately regardless
- // of the UX state, update the action type as KILLED only for immediately
- // killed apps and KILLED_RECURRING_OVERUSE only for apps killed on
- // recurring overuse.
- overuseAction.resourceOveruseActionType = KILLED_RECURRING_OVERUSE;
} catch (RemoteException e) {
Slogf.e(TAG, "Failed to disable application for user %d, package '%s'",
usage.userId, packageName);
}
}
- if (overuseAction.resourceOveruseActionType != NOT_KILLED) {
+ if (isKilled) {
usage.ioUsage.killed();
- mOveruseActionsByUserPackage.add(overuseAction);
+ killedUserPackageKeys.add(usage.getUniqueId());
}
}
pushIoOveruseKillMetrics(killedUserPackageKeys);
- if (!mOveruseActionsByUserPackage.isEmpty()) {
- mMainHandler.post(this::notifyActionsTakenOnOveruse);
- }
mActionableUserPackages.clear();
}
@@ -1451,29 +1440,8 @@
writtenBytes.backgroundBytes, writtenBytes.garageModeBytes));
}
- /** Notify daemon about the actions take on resource overuse */
- private void notifyActionsTakenOnOveruse() {
- List<PackageResourceOveruseAction> actions;
- synchronized (mLock) {
- if (mOveruseActionsByUserPackage.isEmpty()) {
- return;
- }
- actions = new ArrayList<>(mOveruseActionsByUserPackage);
- mOveruseActionsByUserPackage.clear();
- }
- try {
- mCarWatchdogDaemonHelper.actionTakenOnResourceOveruse(actions);
- } catch (RemoteException | RuntimeException e) {
- Slogf.w(TAG, e, "Failed to notify car watchdog daemon of actions taken on resource "
- + "overuse");
- }
- if (DEBUG) {
- Slogf.d(TAG, "Notified car watchdog daemon of actions taken on resource overuse");
- }
- }
-
- private static String getUserPackageUniqueId(int userId, String genericPackageName) {
- return String.valueOf(userId) + ":" + genericPackageName;
+ private static String getUserPackageUniqueId(@UserIdInt int userId, String genericPackageName) {
+ return userId + ":" + genericPackageName;
}
@VisibleForTesting
@@ -1849,6 +1817,7 @@
this.genericPackageName = genericPackageName;
this.userId = userId;
this.mKillableState = defaultKillableState;
+ this.mUid = INVALID_UID;
}
public boolean isSharedPackage() {
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml
index cfad246..1951e15 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml
@@ -122,6 +122,31 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/process_cpu_time_config"/>
+ <Button
+ android:id="@+id/send_on_process_cpu_time_config"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/add_metrics_config"/>
+ <Button
+ android:id="@+id/remove_on_process_cpu_time_config"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/remove_metrics_config"/>
+ <Button
+ android:id="@+id/get_on_process_cpu_time_report"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/get_report"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
<Button
android:id="@+id/show_mem_info_btn"
android:layout_width="wrap_content"
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/car_watchdog_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/car_watchdog_test.xml
index c594b13..f476d5a 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/car_watchdog_test.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/car_watchdog_test.xml
@@ -28,6 +28,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recurring_io_overuse"/>
+ <Button
+ android:id="@+id/long_running_recurring_io_overuse_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/long_running_recurring_io_overuse"/>
<TextView
android:id="@+id/io_overuse_textview"
android:layout_width="wrap_content"
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/user_restrictions.xml b/tests/EmbeddedKitchenSinkApp/res/layout/user_restrictions.xml
index e144acd..3c57e71 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/user_restrictions.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/user_restrictions.xml
@@ -19,9 +19,8 @@
android:orientation="vertical" >
<ListView
android:id="@+id/user_restrictions_list"
- android:layout_height="0dp"
+ android:layout_height="match_parent"
android:layout_width="match_parent"
- android:layout_weight="1"
android:scrollbars="vertical"/>
<Button
@@ -30,6 +29,5 @@
android:layout_height="wrap_content"
android:padding="@dimen/users_button_padding"
android:textSize="@dimen/users_button_text_size"
- android:layout_weight="0"
android:text="@string/users_apply_button" />
</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
index 16e897c..45c12f0 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
@@ -387,6 +387,7 @@
<string name="process_memory_config" translate="false">process_memory:</string>
<string name="app_start_memory_state_captured_config" translate="false">app_start_memory_state_captured:</string>
<string name="activity_foreground_state_changed_config" translate="false">activity_foreground_state_changed:</string>
+ <string name="process_cpu_time_config" translate="false">process_cpu_time:</string>
<string name="add_metrics_config" translatable="false">Add MetricsConfig</string>
<string name="remove_metrics_config" translatable="false">Remove MetricsConfig</string>
<string name="get_report" translatable="false">Get Report</string>
@@ -395,4 +396,5 @@
<!-- Watchdog Test -->
<string name="non_recurring_io_overuse" translate="false">Non-recurring I/O overuse</string>
<string name="recurring_io_overuse" translate="false">Recurring I/O overuse</string>
+ <string name="long_running_recurring_io_overuse" translate="false">Long-running recurring I/O overuse</string>
</resources>
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
index 64f7aa8..7fc4705 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/telemetry/CarTelemetryTestFragment.java
@@ -18,6 +18,7 @@
import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.ACTIVITY_FOREGROUND_STATE_CHANGED;
import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.APP_START_MEMORY_STATE_CAPTURED;
+import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_CPU_TIME;
import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_MEMORY_STATE;
import android.annotation.NonNull;
@@ -49,8 +50,10 @@
import java.util.concurrent.Executors;
public class CarTelemetryTestFragment extends Fragment {
+ private static final int SCRIPT_EXECUTION_PRIORITY_HIGH = 0;
+ private static final int SCRIPT_EXECUTION_PRIORITY_LOW = 100;
- /** Hello World test from vehicle property publisher by injecting gear change. */
+ /** Vehicle property via gear change section. */
private static final String LUA_SCRIPT_ON_GEAR_CHANGE =
"function onGearChange(published_data, state)\n"
+ " result = {data = \"Hello World!\"}\n"
@@ -73,13 +76,13 @@
TelemetryProto.Subscriber.newBuilder()
.setHandler("onGearChange")
.setPublisher(VEHICLE_PROPERTY_PUBLISHER)
- .setPriority(100)) // low priority
+ .setPriority(SCRIPT_EXECUTION_PRIORITY_LOW))
.build();
private static final MetricsConfigKey ON_GEAR_CHANGE_KEY_V1 = new MetricsConfigKey(
METRICS_CONFIG_ON_GEAR_CHANGE_V1.getName(),
METRICS_CONFIG_ON_GEAR_CHANGE_V1.getVersion());
- /** Memory metrics test. */
+ /** ProcessMemoryState section. */
private static final String LUA_SCRIPT_ON_PROCESS_MEMORY_STATE = new StringBuilder()
.append("function calculateAverage(tbl)\n")
.append(" sum = 0\n")
@@ -106,7 +109,6 @@
.append(" on_script_finished(result)\n")
.append("end\n")
.toString();
-
private static final TelemetryProto.Publisher PROCESS_MEMORY_PUBLISHER =
TelemetryProto.Publisher.newBuilder()
.setStats(
@@ -122,13 +124,13 @@
TelemetryProto.Subscriber.newBuilder()
.setHandler("onProcessMemory")
.setPublisher(PROCESS_MEMORY_PUBLISHER)
- .setPriority(0)) // high priority
+ .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
.build();
private static final MetricsConfigKey PROCESS_MEMORY_KEY_V1 = new MetricsConfigKey(
METRICS_CONFIG_PROCESS_MEMORY_V1.getName(),
METRICS_CONFIG_PROCESS_MEMORY_V1.getVersion());
- /** AppStartMemoryStateCaptured metric test. */
+ /** AppStartMemoryStateCaptured section. */
private static final String LUA_SCRIPT_ON_APP_START_MEMORY_STATE_CAPTURED = new StringBuilder()
.append("function calculateAverage(tbl)\n")
.append(" sum = 0\n")
@@ -154,7 +156,6 @@
.append(" on_script_finished(result)\n")
.append("end\n")
.toString();
-
private static final TelemetryProto.Publisher APP_START_MEMORY_STATE_CAPTURED_PUBLISHER =
TelemetryProto.Publisher.newBuilder()
.setStats(
@@ -170,26 +171,27 @@
TelemetryProto.Subscriber.newBuilder()
.setHandler("onAppStartMemoryStateCaptured")
.setPublisher(APP_START_MEMORY_STATE_CAPTURED_PUBLISHER)
- .setPriority(0)) // high priority
+ .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
.build();
private static final MetricsConfigKey APP_START_MEMORY_STATE_CAPTURED_KEY_V1 =
new MetricsConfigKey(
METRICS_CONFIG_APP_START_MEMORY_V1.getName(),
METRICS_CONFIG_APP_START_MEMORY_V1.getVersion());
- /** ActivityForegroundStateChanged metric test. */
+ /** ActivityForegroundStateChanged section. */
private static final String LUA_SCRIPT_ON_ACTIVITY_FOREGROUND_STATE_CHANGED =
new StringBuilder()
.append("function onActivityForegroundStateChanged(published_data, state)\n")
.append(" result = {}\n")
- .append(" result.uid = published_data.uid\n")
- .append(" result.pkg_name = published_data.pkg_name\n")
- .append(" result.class_name = published_data.class_name\n")
- .append(" result.state = published_data.state\n")
+ .append(" n = 0\n")
+ .append(" for k, v in pairs(published_data) do\n")
+ .append(" result[k] = v[1]\n")
+ .append(" n = n + 1\n")
+ .append(" end\n")
+ .append(" result.n = n\n")
.append(" on_script_finished(result)\n")
.append("end\n")
.toString();
-
private static final TelemetryProto.Publisher ACTIVITY_FOREGROUND_STATE_CHANGED_PUBLISHER =
TelemetryProto.Publisher.newBuilder()
.setStats(
@@ -205,13 +207,49 @@
TelemetryProto.Subscriber.newBuilder()
.setHandler("onActivityForegroundStateChanged")
.setPublisher(ACTIVITY_FOREGROUND_STATE_CHANGED_PUBLISHER)
- .setPriority(0)) // high priority
+ .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
.build();
private static final MetricsConfigKey ACTIVITY_FOREGROUND_STATE_CHANGED_KEY_V1 =
new MetricsConfigKey(
METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.getName(),
METRICS_CONFIG_ACTIVITY_FOREGROUND_STATE_V1.getVersion());
+ /* ProcessCpuTime section */
+ private static final String LUA_SCRIPT_ON_PROCESS_CPU_TIME =
+ new StringBuilder()
+ .append("function onProcessCpuTime(published_data, state)\n")
+ .append(" result = {}\n")
+ .append(" n = 0\n")
+ .append(" for k, v in pairs(published_data) do\n")
+ .append(" result[k] = v[1]\n")
+ .append(" n = n + 1\n")
+ .append(" end\n")
+ .append(" result.n = n\n")
+ .append(" on_script_finished(result)\n")
+ .append("end\n")
+ .toString();
+ private static final TelemetryProto.Publisher PROCESS_CPU_TIME_PUBLISHER =
+ TelemetryProto.Publisher.newBuilder()
+ .setStats(
+ TelemetryProto.StatsPublisher.newBuilder()
+ .setSystemMetric(PROCESS_CPU_TIME)
+ ).build();
+ private static final TelemetryProto.MetricsConfig METRICS_CONFIG_PROCESS_CPU_TIME_V1 =
+ TelemetryProto.MetricsConfig.newBuilder()
+ .setName("process_cpu_time_config")
+ .setVersion(1)
+ .setScript(LUA_SCRIPT_ON_PROCESS_CPU_TIME)
+ .addSubscribers(
+ TelemetryProto.Subscriber.newBuilder()
+ .setHandler("onProcessCpuTime")
+ .setPublisher(PROCESS_CPU_TIME_PUBLISHER)
+ .setPriority(SCRIPT_EXECUTION_PRIORITY_HIGH))
+ .build();
+ private static final MetricsConfigKey PROCESS_CPU_TIME_KEY_V1 =
+ new MetricsConfigKey(
+ METRICS_CONFIG_PROCESS_CPU_TIME_V1.getName(),
+ METRICS_CONFIG_PROCESS_CPU_TIME_V1.getVersion());
+
private final Executor mExecutor = Executors.newSingleThreadExecutor();
private CarTelemetryManager mCarTelemetryManager;
@@ -260,6 +298,12 @@
.setOnClickListener(this::onRemoveActivityForegroundStateChangedConfigBtnClick);
view.findViewById(R.id.get_on_activity_foreground_state_changed_report)
.setOnClickListener(this::onGetActivityForegroundStateChangedReportBtnClick);
+ view.findViewById(R.id.send_on_process_cpu_time_config)
+ .setOnClickListener(this::onSendProcessCpuTimeConfigBtnClick);
+ view.findViewById(R.id.remove_on_process_cpu_time_config)
+ .setOnClickListener(this::onRemoveProcessCpuTimeConfigBtnClick);
+ view.findViewById(R.id.get_on_process_cpu_time_report)
+ .setOnClickListener(this::onGetProcessCpuTimeReportBtnClick);
view.findViewById(R.id.show_mem_info_btn).setOnClickListener(this::onShowMemInfoBtnClick);
return view;
}
@@ -341,6 +385,23 @@
mCarTelemetryManager.sendFinishedReports(ACTIVITY_FOREGROUND_STATE_CHANGED_KEY_V1);
}
+ private void onSendProcessCpuTimeConfigBtnClick(View view) {
+ showOutput("Sending MetricsConfig that listens for PROCESS_CPU_TIME...");
+ mCarTelemetryManager.addMetricsConfig(PROCESS_CPU_TIME_KEY_V1,
+ METRICS_CONFIG_PROCESS_CPU_TIME_V1.toByteArray());
+ }
+
+ private void onRemoveProcessCpuTimeConfigBtnClick(View view) {
+ showOutput("Removing MetricsConfig that listens for PROCESS_CPU_TIME...");
+ mCarTelemetryManager.removeMetricsConfig(PROCESS_CPU_TIME_KEY_V1);
+ }
+
+ private void onGetProcessCpuTimeReportBtnClick(View view) {
+ showOutput("Fetching report for PROCESS_CPU_TIME... If nothing shows up within 5 "
+ + "seconds, there is no result yet");
+ mCarTelemetryManager.sendFinishedReports(PROCESS_CPU_TIME_KEY_V1);
+ }
+
/** Gets a MemoryInfo object for the device's current memory status. */
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager = getActivity().getSystemService(ActivityManager.class);
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/users/UserRestrictionsFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/users/UserRestrictionsFragment.java
index 445273d..1ce98d0 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/users/UserRestrictionsFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/users/UserRestrictionsFragment.java
@@ -32,6 +32,7 @@
import com.google.android.car.kitchensink.R;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -46,6 +47,7 @@
Arrays.asList(
UserManager.DISALLOW_ADD_USER,
UserManager.DISALLOW_BLUETOOTH,
+ UserManager.DISALLOW_CONFIG_BRIGHTNESS,
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_INSTALL_APPS,
UserManager.DISALLOW_MODIFY_ACCOUNTS,
@@ -56,6 +58,11 @@
UserManager.DISALLOW_USER_SWITCH
);
+ static {
+ Collections.sort(CONFIGURABLE_USER_RESTRICTIONS);
+ Log.d(TAG, "Configurable user restrictions: " + CONFIGURABLE_USER_RESTRICTIONS);
+ }
+
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/watchdog/CarWatchdogTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/watchdog/CarWatchdogTestFragment.java
index cd5cc3a..1298ddb 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/watchdog/CarWatchdogTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/watchdog/CarWatchdogTestFragment.java
@@ -54,6 +54,7 @@
import java.nio.file.Files;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Fragment to test the I/O monitoring of Car Watchdog.
@@ -76,7 +77,12 @@
*/
public class CarWatchdogTestFragment extends Fragment {
private static final long TEN_MEGABYTES = 1024 * 1024 * 10;
- private static final int DISK_DELAY_MS = 3000;
+ private static final int WATCHDOG_IO_EVENT_SYNC_SHORT_DELAY_MS = 3_000;
+ // By default, watchdog daemon syncs the disk I/O events with the CarService once every
+ // 2 minutes unless it is manually changed with the aforementioned `--start_perf` watchdog
+ // daemon's dumpsys command.
+ private static final int WATCHDOG_IO_EVENT_SYNC_LONG_DELAY_MS = 240_000;
+ private static final int USER_APP_SWITCHING_TIMEOUT_MS = 30_000;
private static final String TAG = "CarWatchdogTestFragment";
private static final double WARN_THRESHOLD_PERCENT = 0.8;
private static final double EXCEED_WARN_THRESHOLD_PERCENT = 0.9;
@@ -104,6 +110,7 @@
private @interface NotificationType{}
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+ private final AtomicBoolean mIsAppInForeground = new AtomicBoolean(true);
private Context mContext;
private CarWatchdogManager mCarWatchdogManager;
private KitchenSinkActivity mActivity;
@@ -129,11 +136,15 @@
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
+ mIsAppInForeground.set(true);
+
View view = inflater.inflate(R.layout.car_watchdog_test, container, false);
mOveruseTextView = view.findViewById(R.id.io_overuse_textview);
Button nonRecurringIoOveruseButton = view.findViewById(R.id.non_recurring_io_overuse_btn);
Button recurringIoOveruseButton = view.findViewById(R.id.recurring_io_overuse_btn);
+ Button longRunningRecurringIoOveruseButton =
+ view.findViewById(R.id.long_running_recurring_io_overuse_btn);
try {
mTestDir =
@@ -147,10 +158,12 @@
v -> mExecutor.execute(
() -> {
mTextViewSetter = new TextViewSetter(mOveruseTextView, mActivity);
+ mTextViewSetter.setPermanent("Note: Keep the app in the foreground "
+ + "until the test completes." + System.lineSeparator());
mTextViewSetter.set("Starting non-recurring I/O overuse test.");
IoOveruseListener listener = addResourceOveruseListener();
- if (overuseDiskIo(listener)) {
+ if (overuseDiskIo(listener, WATCHDOG_IO_EVENT_SYNC_SHORT_DELAY_MS)) {
showAlert("Non-recurring I/O overuse test",
"Test completed successfully.", 0);
} else {
@@ -162,50 +175,79 @@
Log.d(TAG, "Non-recurring I/O overuse test completed.");
}));
- recurringIoOveruseButton.setOnClickListener(
- v -> mExecutor.execute(
- () -> {
- mTextViewSetter = new TextViewSetter(mOveruseTextView, mActivity);
- mTextViewSetter.set("Starting recurring I/O overuse test.");
- IoOveruseListener listener = addResourceOveruseListener();
+ recurringIoOveruseButton.setOnClickListener(v -> mExecutor.execute(
+ () -> {
+ mTextViewSetter = new TextViewSetter(mOveruseTextView, mActivity);
+ mTextViewSetter.setPermanent("Note: Keep the app in the foreground "
+ + "until the test completes." + System.lineSeparator());
+ recurringIoOveruseTest(WATCHDOG_IO_EVENT_SYNC_SHORT_DELAY_MS);
+ }));
- if (!overuseDiskIo(listener)) {
- mTextViewSetter.setPermanent("First disk I/O overuse failed.");
- finishTest(listener);
- return;
- }
- mTextViewSetter.setPermanent(
- "First disk I/O overuse completed successfully."
- + System.lineSeparator());
+ // Long-running recurring I/O overuse test is helpful to trigger recurring I/O overuse
+ // behavior in environments where shell access is limited.
+ longRunningRecurringIoOveruseButton.setOnClickListener(v -> mExecutor.execute(
+ () -> {
+ mTextViewSetter = new TextViewSetter(mOveruseTextView, mActivity);
+ mTextViewSetter.setPermanent("Note: Please switch the app to the background "
+ + "and don't bring the app to the foreground until the test completes."
+ + System.lineSeparator());
- if (!overuseDiskIo(listener)) {
- mTextViewSetter.setPermanent("Second disk I/O overuse failed.");
- finishTest(listener);
- return;
- }
- mTextViewSetter.setPermanent(
- "Second disk I/O overuse completed successfully."
- + System.lineSeparator());
-
- if (!overuseDiskIo(listener)) {
- mTextViewSetter.setPermanent("Third disk I/O overuse failed.");
- finishTest(listener);
- return;
- }
- mTextViewSetter.setPermanent(
- "Third disk I/O overuse completed successfully.");
-
- finishTest(listener);
- showAlert("Recurring I/O overuse test", "Test completed successfully.",
- 0);
- Log.d(TAG, "Recurring I/O overuse test completed.");
- }));
+ waitFor(USER_APP_SWITCHING_TIMEOUT_MS,
+ "user to switch the app to the background");
+ recurringIoOveruseTest(WATCHDOG_IO_EVENT_SYNC_LONG_DELAY_MS);
+ }));
return view;
}
- private boolean overuseDiskIo(IoOveruseListener listener) {
- DiskIoStats diskIoStats = fetchInitialDiskIoStats();
+ @Override
+ public void onPause() {
+ super.onPause();
+ Log.d(TAG, "App switched to background");
+ mIsAppInForeground.set(false);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.d(TAG, "App switched to foreground");
+ mIsAppInForeground.set(true);
+ }
+
+ private void recurringIoOveruseTest(int watchdogSyncDelayMs) {
+ mTextViewSetter.set("Starting recurring I/O overuse test.");
+ IoOveruseListener listener = addResourceOveruseListener();
+
+ if (!overuseDiskIo(listener, watchdogSyncDelayMs)) {
+ mTextViewSetter.setPermanent("First disk I/O overuse failed.");
+ finishTest(listener);
+ return;
+ }
+ mTextViewSetter.setPermanent("First disk I/O overuse completed successfully."
+ + System.lineSeparator());
+
+ if (!overuseDiskIo(listener, watchdogSyncDelayMs)) {
+ mTextViewSetter.setPermanent("Second disk I/O overuse failed.");
+ finishTest(listener);
+ return;
+ }
+ mTextViewSetter.setPermanent("Second disk I/O overuse completed successfully."
+ + System.lineSeparator());
+
+ if (!overuseDiskIo(listener, watchdogSyncDelayMs)) {
+ mTextViewSetter.setPermanent("Third disk I/O overuse failed.");
+ finishTest(listener);
+ return;
+ }
+ mTextViewSetter.setPermanent("Third disk I/O overuse completed successfully.");
+
+ finishTest(listener);
+ showAlert("Recurring I/O overuse test", "Test completed successfully.", 0);
+ Log.d(TAG, "Recurring I/O overuse test completed.");
+ }
+
+ private boolean overuseDiskIo(IoOveruseListener listener, int watchdogSyncDelayMs) {
+ DiskIoStats diskIoStats = fetchInitialDiskIoStats(watchdogSyncDelayMs);
if (diskIoStats == null) {
return false;
}
@@ -223,7 +265,8 @@
NOTIFICATION_TYPE_WARNING);
long bytesToExceedWarnThreshold =
(long) Math.ceil(diskIoStats.remainingBytes * EXCEED_WARN_THRESHOLD_PERCENT);
- if (!writeToDisk(bytesToExceedWarnThreshold) || !listener.isValidNotificationReceived()) {
+ if (!writeToDisk(bytesToExceedWarnThreshold)
+ || !listener.isValidNotificationReceived(watchdogSyncDelayMs)) {
return false;
}
mTextViewSetter.setPermanent(
@@ -232,7 +275,8 @@
long remainingBytes = listener.getNotifiedRemainingBytes();
listener.expectNewNotification(remainingBytes, diskIoStats.totalOveruses + 1,
NOTIFICATION_TYPE_OVERUSE);
- if (!writeToDisk(remainingBytes) || !listener.isValidNotificationReceived()) {
+ if (!writeToDisk(remainingBytes)
+ || !listener.isValidNotificationReceived(watchdogSyncDelayMs)) {
return false;
}
mTextViewSetter.setPermanent(
@@ -247,10 +291,12 @@
super.onDestroyView();
}
- private @Nullable DiskIoStats fetchInitialDiskIoStats() {
+ private @Nullable DiskIoStats fetchInitialDiskIoStats(int watchdogSyncDelayMs) {
if (!writeToDisk(TEN_MEGABYTES)) {
return null;
}
+ waitFor(watchdogSyncDelayMs,
+ "the disk I/O activity to be detected by the watchdog service...");
ResourceOveruseStats resourceOveruseStats = mCarWatchdogManager.getResourceOveruseStats(
CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO,
@@ -270,11 +316,10 @@
+ ioOveruseStats.getTotalBytesWritten() + "' returned by get request.");
return null;
}
- /*
- * Check for foreground mode bytes given kitchensink app is running in the foreground
- * during manual testing.
- */
- long remainingBytes = ioOveruseStats.getRemainingWriteBytes().getForegroundModeBytes();
+
+ long remainingBytes = mIsAppInForeground.get()
+ ? ioOveruseStats.getRemainingWriteBytes().getForegroundModeBytes()
+ : ioOveruseStats.getRemainingWriteBytes().getBackgroundModeBytes();
if (remainingBytes == 0) {
showErrorAlert("Zero remaining bytes reported." + System.lineSeparator()
+ "Note: Reset resource overuse stats before running the test.");
@@ -327,20 +372,10 @@
return false;
}
fos.getFD().sync();
- mTextViewSetter.set("Wrote " + bytes + " bytes to disk. Waiting "
- + (DISK_DELAY_MS / 1000) + " seconds for the disk I/O activity to be detected "
- + "by the watchdog service...");
- Thread.sleep(DISK_DELAY_MS);
+ mTextViewSetter.set("Wrote " + bytes + " bytes to disk.");
return true;
- } catch (IOException | InterruptedException e) {
- String reason;
- if (e instanceof IOException) {
- reason = "I/O exception";
- } else {
- reason = "Thread interrupted";
- Thread.currentThread().interrupt();
- }
- String message = reason + " after successfully writing to disk.";
+ } catch (IOException e) {
+ String message = "I/O exception after successfully writing to disk.";
Log.e(TAG, message, e);
showErrorAlert(message + System.lineSeparator() + System.lineSeparator()
+ e.getMessage());
@@ -376,6 +411,19 @@
return totalBytesWritten;
}
+ private void waitFor(int waitMs, String reason) {
+ try {
+ mTextViewSetter.set("Waiting " + (waitMs / 1000) + " seconds for " + reason);
+ Thread.sleep(waitMs);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ String message = "Thread interrupted while waiting for " + reason;
+ Log.e(TAG, message, e);
+ showErrorAlert(message + System.lineSeparator() + System.lineSeparator()
+ + e.getMessage());
+ }
+ }
+
private void showErrorAlert(String message) {
mTextViewSetter.setPermanent("Error: " + message);
showAlert("Error", message, android.R.drawable.ic_dialog_alert);
@@ -407,7 +455,7 @@
private final class IoOveruseListener
implements CarWatchdogManager.ResourceOveruseListener {
- private static final int NOTIFICATION_DELAY_MS = 10000;
+ private static final int NOTIFICATION_DELAY_MS = 10_000;
private final Object mLock = new Object();
@GuardedBy("mLock")
@@ -443,8 +491,9 @@
+ toNotificationTypeString(mExpectedNotificationType) + '.');
return;
}
- mNotifiedRemainingBytes = ioOveruseStats.getRemainingWriteBytes()
- .getForegroundModeBytes();
+ mNotifiedRemainingBytes = mIsAppInForeground.get()
+ ? ioOveruseStats.getRemainingWriteBytes().getForegroundModeBytes()
+ : ioOveruseStats.getRemainingWriteBytes().getBackgroundModeBytes();
if (mExpectedNotificationType == NOTIFICATION_TYPE_WARNING
&& mNotifiedRemainingBytes == 0) {
showErrorAlert("Expected non-zero remaining write bytes in the "
@@ -484,12 +533,13 @@
}
}
- private boolean isValidNotificationReceived() {
+ private boolean isValidNotificationReceived(int watchdogSyncDelayMs) {
synchronized (mLock) {
long now = SystemClock.uptimeMillis();
- long deadline = now + NOTIFICATION_DELAY_MS;
- mTextViewSetter.set("Waiting " + (NOTIFICATION_DELAY_MS / 1000)
- + " seconds to be notified of disk I/O overuse...");
+ long deadline = now + NOTIFICATION_DELAY_MS + watchdogSyncDelayMs;
+ mTextViewSetter.set("Waiting "
+ + ((NOTIFICATION_DELAY_MS + watchdogSyncDelayMs) / 1000)
+ + " seconds to be notified of disk I/O overuse...");
while (mNotificationStatus == NOTIFICATION_STATUS_NO && now < deadline) {
try {
mLock.wait(deadline - now);
diff --git a/tests/OWNERS b/tests/OWNERS
index e515908..9301565 100644
--- a/tests/OWNERS
+++ b/tests/OWNERS
@@ -4,3 +4,5 @@
# AAE TLs
pirozzoj@google.com
twasilczyk@google.com
+stenning@google.com
+igorr@google.com
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 80cab06..fe183bd 100644
--- a/tests/carservice_unit_test/src/android/car/watchdoglib/CarWatchdogDaemonHelperTest.java
+++ b/tests/carservice_unit_test/src/android/car/watchdoglib/CarWatchdogDaemonHelperTest.java
@@ -34,7 +34,6 @@
import android.automotive.watchdog.internal.ICarWatchdogServiceForSystem;
import android.automotive.watchdog.internal.PackageInfo;
import android.automotive.watchdog.internal.PackageIoOveruseStats;
-import android.automotive.watchdog.internal.PackageResourceOveruseAction;
import android.automotive.watchdog.internal.PowerCycle;
import android.automotive.watchdog.internal.ResourceOveruseConfiguration;
import android.automotive.watchdog.internal.StateType;
@@ -186,15 +185,6 @@
}
@Test
- public void testIndirectCall_actionTakenOnResourceOveruse() throws Exception {
- List<PackageResourceOveruseAction> actions = new ArrayList<>();
-
- mCarWatchdogDaemonHelper.actionTakenOnResourceOveruse(actions);
-
- verify(mFakeCarWatchdog).actionTakenOnResourceOveruse(eq(actions));
- }
-
- @Test
public void testIndirectCall_controlProcessHealthCheck() throws Exception {
mCarWatchdogDaemonHelper.controlProcessHealthCheck(true);
diff --git a/tests/carservice_unit_test/src/com/android/car/AbstractICarServiceHelperStub.java b/tests/carservice_unit_test/src/com/android/car/AbstractICarServiceHelperStub.java
index 5d387cc..6ebd43e 100644
--- a/tests/carservice_unit_test/src/com/android/car/AbstractICarServiceHelperStub.java
+++ b/tests/carservice_unit_test/src/com/android/car/AbstractICarServiceHelperStub.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.pm.UserInfo;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import com.android.car.internal.ICarServiceHelper;
@@ -81,4 +82,9 @@
+ ", displayId=" + displayId + ", featureId=" + featureId + ")");
return CarActivityManager.RESULT_SUCCESS;
}
+
+ @Override
+ public void sendInitialUser(UserHandle user) {
+ Log.d(TAG, "sendInitialUser " + user);
+ }
}
diff --git a/tests/carservice_unit_test/src/com/android/car/hardware/power/CarPowerManagerUnitTest.java b/tests/carservice_unit_test/src/com/android/car/hardware/power/CarPowerManagerUnitTest.java
index 6d5c7dc..3032180 100644
--- a/tests/carservice_unit_test/src/com/android/car/hardware/power/CarPowerManagerUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/hardware/power/CarPowerManagerUnitTest.java
@@ -55,6 +55,7 @@
import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
+import android.os.UserManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.AtomicFile;
import android.util.Log;
@@ -115,6 +116,8 @@
@Mock
private Car mCar;
@Mock
+ private UserManager mUserManager;
+ @Mock
private CarUserService mCarUserService;
@Mock
private IVoiceInteractionManagerService mVoiceInteractionManagerService;
@@ -406,7 +409,7 @@
mPowerComponentHandler = new PowerComponentHandler(mContext, mSystemInterface,
mVoiceInteractionManagerService, new AtomicFile(mComponentStateFile.getFile()));
mService = new CarPowerManagementService(mContext, mResources, mPowerHal, mSystemInterface,
- null, mCarUserService, mPowerPolicyDaemon, mPowerComponentHandler,
+ mUserManager, mCarUserService, mPowerPolicyDaemon, mPowerComponentHandler,
/* silentModeHwStatePath= */ null, /* silentModeKernelStatePath= */ null,
/* bootReason= */ null);
mService.init();
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerTest.java
index c5f30c2..d639820 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/databroker/DataBrokerTest.java
@@ -16,8 +16,6 @@
package com.android.car.telemetry.databroker;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -156,11 +154,13 @@
mHighPriorityTask = new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
mData,
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(),
+ false);
mLowPriorityTask = new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_BAR, SUBSCRIBER_BAR),
mData,
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(),
+ false);
}
@Override
@@ -319,13 +319,13 @@
}
@Test
- public void testScheduleNextTask_largeInput_shouldPipeData() throws Exception {
+ public void testScheduleNextTask_withLargeDataFlag_shouldPipeData() throws Exception {
PersistableBundle data = new PersistableBundle();
- data.putBooleanArray("1 MB Array", new boolean [1024 * 1024]);
ScriptExecutionTask highPriorityTask = new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
data,
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(),
+ true);
mDataBroker.getTaskQueue().add(highPriorityTask);
mDataBroker.scheduleNextTask();
@@ -335,29 +335,13 @@
}
@Test
- public void testScheduleNextTask_largeReportWithApproxSize_shouldPipeData() throws Exception {
+ public void testScheduleNextTask_withoutLargeDataFlag_doesNotPipeData() throws Exception {
PersistableBundle data = new PersistableBundle();
- data.putInt(APPROX_BUNDLE_SIZE_BYTES_KEY, 21000);
ScriptExecutionTask highPriorityTask = new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
data,
- SystemClock.elapsedRealtime());
- mDataBroker.getTaskQueue().add(highPriorityTask);
-
- mDataBroker.scheduleNextTask();
-
- waitForTelemetryThreadToFinish();
- assertThat(mFakeScriptExecutor.getInvokeScriptForLargeInputCount()).isEqualTo(1);
- }
-
- @Test
- public void testScheduleNextTask_smallReportWithApproxSize_doesNotPipeData() throws Exception {
- PersistableBundle data = new PersistableBundle();
- data.putInt(APPROX_BUNDLE_SIZE_BYTES_KEY, 1000);
- ScriptExecutionTask highPriorityTask = new ScriptExecutionTask(
- new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
- data,
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(),
+ false);
mDataBroker.getTaskQueue().add(highPriorityTask);
mDataBroker.scheduleNextTask();
@@ -369,18 +353,18 @@
@Test
public void testScheduleNextTask_largeInputPipeIOException_shouldIgnoreCurrentTask()
throws Exception {
- PersistableBundle data = new PersistableBundle();
- data.putBooleanArray("1 MB Array", new boolean [1024 * 1024]);
PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
ScriptExecutionTask highPriorityTask = new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
- data,
- SystemClock.elapsedRealtime());
+ new PersistableBundle(),
+ SystemClock.elapsedRealtime(),
+ true);
taskQueue.add(highPriorityTask); // invokeScriptForLargeInput() path
taskQueue.add(new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
new PersistableBundle(),
- SystemClock.elapsedRealtime())); // invokeScript() path
+ SystemClock.elapsedRealtime(),
+ false)); // invokeScript() path
ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
when(ParcelFileDescriptor.createPipe()).thenReturn(fds);
fds[1].close(); // cause IO Exception in invokeScriptForLargeInput() path
@@ -496,7 +480,8 @@
ScriptExecutionTask taskWithMetricsConfigFoo = new ScriptExecutionTask(
new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
mData,
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(),
+ false);
PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
taskQueue.add(mHighPriorityTask); // associated with METRICS_CONFIG_FOO
taskQueue.add(mLowPriorityTask); // associated with METRICS_CONFIG_BAR
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/StatsPublisherTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/StatsPublisherTest.java
index 25076a1..35173aa 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/StatsPublisherTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/StatsPublisherTest.java
@@ -33,6 +33,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.reset;
@@ -449,7 +450,7 @@
mFakeHandlerWrapper.dispatchQueuedMessages();
- verify(subscriber1).push(mBundleCaptor.capture());
+ verify(subscriber1).push(mBundleCaptor.capture(), anyBoolean());
PersistableBundle bundle1 = mBundleCaptor.getValue();
assertThat(bundle1.getLongArray("elapsed_timestamp_nanos"))
.asList().containsExactly(99999999L);
@@ -457,7 +458,7 @@
assertThat(Arrays.asList(bundle1.getStringArray("activity_name")))
.containsExactly("activityName");
assertThat(bundle1.getLongArray("rss_in_bytes")).asList().containsExactly(1234L);
- verify(subscriber2).push(mBundleCaptor.capture());
+ verify(subscriber2).push(mBundleCaptor.capture(), anyBoolean());
PersistableBundle bundle2 = mBundleCaptor.getValue();
assertThat(bundle2.getIntArray("uid")).asList().containsExactly(234);
assertThat(bundle2.getLongArray("rss_in_bytes")).asList().containsExactly(4567L);
@@ -466,6 +467,38 @@
}
@Test
+ public void testBundleWithLargeSize_isLargeData() throws Exception {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBooleanArray("bool", new boolean[1000]);
+ bundle.putLongArray("long", new long[1000]);
+ bundle.putIntArray("int", new int[1000]);
+ bundle.putDoubleArray("double", new double[1000]);
+ String[] strArray = new String[1000];
+ for (int i = 0; i < strArray.length; ++i) {
+ strArray[i] = "test";
+ }
+ bundle.putStringArray("string", strArray);
+
+ assertThat(mPublisher.isBundleLargeData(bundle)).isTrue();
+ }
+
+ @Test
+ public void testBundleWithSmallSize_isNotLargeData() throws Exception {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBooleanArray("bool", new boolean[100]);
+ bundle.putLongArray("long", new long[100]);
+ bundle.putIntArray("int", new int[100]);
+ bundle.putDoubleArray("double", new double[100]);
+ String[] strArray = new String[100];
+ for (int i = 0; i < strArray.length; ++i) {
+ strArray[i] = "test";
+ }
+ bundle.putStringArray("string", strArray);
+
+ assertThat(mPublisher.isBundleLargeData(bundle)).isFalse();
+ }
+
+ @Test
public void testOnInvalidConfig_notifiesPublisherFailureListener() throws Exception {
DataSubscriber subscriber = spy(new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_1));
mPublisher.addDataSubscriber(subscriber);
@@ -483,7 +516,7 @@
mFakeHandlerWrapper.dispatchQueuedMessages();
// subscriber shouldn't get data, because of EMPTY_METRICS_REPORT.
- verify(subscriber, times(0)).push(any());
+ verify(subscriber, times(0)).push(any(), anyBoolean());
assertThat(mFailedConfigs).containsExactly(METRICS_CONFIG);
assertThat(mPublisherFailure).hasMessageThat().contains("Found invalid configs");
}
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverterTest.java
index 221c716..98a0925 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverterTest.java
@@ -20,7 +20,6 @@
import static com.android.car.telemetry.AtomsProto.ActivityForegroundStateChanged.PKG_NAME_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.ActivityForegroundStateChanged.STATE_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.ActivityForegroundStateChanged.UID_FIELD_NUMBER;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
import static com.google.common.truth.Truth.assertThat;
@@ -105,8 +104,7 @@
PersistableBundle bundle = mConverter.convert(atomsList, DIM_FIELDS_IDS,
dimensionsValuesList, HASH_STR_MAP);
- assertThat(bundle.size()).isEqualTo(5);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(120);
+ assertThat(bundle.size()).isEqualTo(4);
assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 2000).inOrder();
assertThat(Arrays.asList(
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java
index b309069..1579e00 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java
@@ -24,7 +24,6 @@
import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.RSS_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.SWAP_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.UID_FIELD_NUMBER;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
import static com.google.common.truth.Truth.assertThat;
@@ -119,8 +118,7 @@
PersistableBundle bundle = mConverter.convert(atomsList, DIM_FIELDS_IDS,
dimensionsValuesList, HASH_STR_MAP);
- assertThat(bundle.size()).isEqualTo(9);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(204);
+ assertThat(bundle.size()).isEqualTo(8);
assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 2000).inOrder();
assertThat(Arrays.asList(
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java
index 4704966..a8cc426 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java
@@ -16,8 +16,6 @@
package com.android.car.telemetry.publisher.statsconverters;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
-
import static com.google.common.truth.Truth.assertThat;
import android.os.PersistableBundle;
@@ -60,8 +58,7 @@
PersistableBundle bundle = AtomListConverter.convert(pushedAtomsList, null, null, null);
- assertThat(bundle.size()).isEqualTo(4);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(80);
+ assertThat(bundle.size()).isEqualTo(3);
assertThat(bundle.getIntArray(
accessorMap.get(AppStartMemoryStateCaptured.UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 1100).inOrder();
@@ -97,8 +94,7 @@
PersistableBundle bundle = AtomListConverter.convert(pulledAtomsList, null, null, null);
- assertThat(bundle.size()).isEqualTo(4);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(76);
+ assertThat(bundle.size()).isEqualTo(3);
assertThat(bundle.getIntArray(
accessorMap.get(ProcessMemoryState.UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 1100).inOrder();
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java
index 0bac4cd..dac3310 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java
@@ -19,7 +19,6 @@
import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.ACTIVITY_NAME_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.RSS_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.UID_FIELD_NUMBER;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
import static com.google.common.truth.Truth.assertThat;
@@ -67,8 +66,7 @@
PersistableBundle bundle = EventMetricDataConverter.convertEventDataList(eventDataList);
- assertThat(bundle.size()).isEqualTo(5);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(96);
+ assertThat(bundle.size()).isEqualTo(4);
assertThat(bundle.getLongArray(EventMetricDataConverter.ELAPSED_TIME_NANOS))
.asList().containsExactly(12345678L, 23456789L).inOrder();
assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java
index 808a6a1..8e747ae 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java
@@ -21,7 +21,6 @@
import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.RSS_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.SWAP_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.UID_FIELD_NUMBER;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
import static com.google.common.truth.Truth.assertThat;
@@ -104,8 +103,7 @@
// For each atom 2 fields were set, additionally 3 fields were encoded in dimension values,
// and 1 elapsed time array, so 6 arrays are expected in the bundle.
- assertThat(bundle.size()).isEqualTo(7);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(264);
+ assertThat(bundle.size()).isEqualTo(6);
assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(123, 123, 123, 234).inOrder();
assertThat(Arrays.asList(bundle.getStringArray(
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessCpuTimeConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessCpuTimeConverterTest.java
new file mode 100644
index 0000000..0075391
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessCpuTimeConverterTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.publisher.statsconverters;
+
+import static com.android.car.telemetry.AtomsProto.ProcessCpuTime.PROCESS_NAME_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessCpuTime.SYSTEM_TIME_MILLIS_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessCpuTime.UID_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessCpuTime.USER_TIME_MILLIS_FIELD_NUMBER;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.os.PersistableBundle;
+import android.util.SparseArray;
+
+import com.android.car.telemetry.AtomsProto.Atom;
+import com.android.car.telemetry.AtomsProto.ProcessCpuTime;
+import com.android.car.telemetry.StatsLogProto.DimensionsValue;
+import com.android.car.telemetry.publisher.HashUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public class ProcessCpuTimeConverterTest {
+ private static final Atom ATOM_A =
+ Atom.newBuilder()
+ .setProcessCpuTime(ProcessCpuTime.newBuilder()
+ .setUserTimeMillis(234L)
+ .setSystemTimeMillis(111L))
+ .build();
+
+ private static final Atom ATOM_B =
+ Atom.newBuilder()
+ .setProcessCpuTime(ProcessCpuTime.newBuilder()
+ .setUserTimeMillis(345L)
+ .setSystemTimeMillis(222L))
+ .build();
+
+ private static final Atom ATOM_MISMATCH =
+ Atom.newBuilder()
+ .setProcessCpuTime(ProcessCpuTime.newBuilder()
+ // Some fields are not set, creating mismatch with above atoms
+ .setSystemTimeMillis(333L))
+ .build();
+
+ private static final List<Integer> DIM_FIELDS_IDS = Arrays.asList(1, 2);
+ private static final Long HASH_1 = HashUtils.murmur2Hash64("process.name.1");
+ private static final Long HASH_2 = HashUtils.murmur2Hash64("process.name.2");
+ private static final Map<Long, String> HASH_STR_MAP = Map.of(
+ HASH_1, "process.name.1",
+ HASH_2, "process.name.2");
+
+ private static final List<DimensionsValue> DV_PAIR_A =
+ Arrays.asList(
+ DimensionsValue.newBuilder().setValueInt(1000).build(),
+ DimensionsValue.newBuilder().setValueStrHash(HASH_1).build());
+
+ private static final List<DimensionsValue> DV_PAIR_B =
+ Arrays.asList(
+ DimensionsValue.newBuilder().setValueInt(2000).build(),
+ DimensionsValue.newBuilder().setValueStrHash(HASH_2).build());
+
+ private static final List<DimensionsValue> DV_PAIR_MALFORMED =
+ Arrays.asList(
+ DimensionsValue.newBuilder().setValueInt(3000).build(),
+ // Wrong format since leaf level dimension value should set value, not field
+ DimensionsValue.newBuilder().setField(3).build());
+
+ // Subject of the test.
+ private ProcessCpuTimeConverter mConverter = new ProcessCpuTimeConverter();
+
+ @Test
+ public void testConvertAtomsListWithDimensionValues_putsCorrectDataToPersistableBundle()
+ throws StatsConversionException {
+ List<Atom> atomsList = Arrays.asList(ATOM_A, ATOM_B);
+ List<List<DimensionsValue>> dimensionsValuesList = Arrays.asList(DV_PAIR_A, DV_PAIR_B);
+ SparseArray<AtomFieldAccessor<ProcessCpuTime>> accessorMap =
+ mConverter.getAtomFieldAccessorMap();
+
+ PersistableBundle bundle = mConverter.convert(atomsList, DIM_FIELDS_IDS,
+ dimensionsValuesList, HASH_STR_MAP);
+
+ assertThat(bundle.size()).isEqualTo(4);
+ assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
+ .asList().containsExactly(1000, 2000).inOrder();
+ assertThat(Arrays.asList(
+ bundle.getStringArray(accessorMap.get(PROCESS_NAME_FIELD_NUMBER).getFieldName())))
+ .containsExactly("process.name.1", "process.name.2").inOrder();
+ assertThat(bundle.getLongArray(
+ accessorMap.get(USER_TIME_MILLIS_FIELD_NUMBER).getFieldName()))
+ .asList().containsExactly(234L, 345L).inOrder();
+ assertThat(bundle.getLongArray(
+ accessorMap.get(SYSTEM_TIME_MILLIS_FIELD_NUMBER).getFieldName()))
+ .asList().containsExactly(111L, 222L).inOrder();
+ }
+
+ @Test
+ public void testAtomSetFieldInconsistency_throwsException() {
+ List<Atom> atomsList = Arrays.asList(ATOM_A, ATOM_MISMATCH);
+ List<List<DimensionsValue>> dimensionsValuesList = Arrays.asList(DV_PAIR_A, DV_PAIR_B);
+
+ assertThrows(
+ StatsConversionException.class,
+ () -> mConverter.convert(
+ atomsList,
+ DIM_FIELDS_IDS,
+ dimensionsValuesList,
+ HASH_STR_MAP));
+ }
+
+ @Test
+ public void testMalformedDimensionValue_throwsException() {
+ List<Atom> atomsList = Arrays.asList(ATOM_A, ATOM_B);
+ List<List<DimensionsValue>> dimensionsValuesList =
+ Arrays.asList(DV_PAIR_A, DV_PAIR_MALFORMED);
+
+ assertThrows(
+ StatsConversionException.class,
+ () -> mConverter.convert(
+ atomsList,
+ DIM_FIELDS_IDS,
+ dimensionsValuesList,
+ HASH_STR_MAP));
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java
index 050cb4c..f922d17 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java
@@ -24,7 +24,6 @@
import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.RSS_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.SWAP_IN_BYTES_FIELD_NUMBER;
import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.UID_FIELD_NUMBER;
-import static com.android.car.telemetry.databroker.ScriptExecutionTask.APPROX_BUNDLE_SIZE_BYTES_KEY;
import static com.google.common.truth.Truth.assertThat;
@@ -117,8 +116,7 @@
PersistableBundle bundle = mConverter.convert(atomsList, DIM_FIELDS_IDS,
dimensionsValuesList, HASH_STR_MAP);
- assertThat(bundle.size()).isEqualTo(9);
- assertThat(bundle.getInt(APPROX_BUNDLE_SIZE_BYTES_KEY)).isEqualTo(156);
+ assertThat(bundle.size()).isEqualTo(8);
assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 2000).inOrder();
assertThat(Arrays.asList(
diff --git a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
index e72df67..b4e6502 100644
--- a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
@@ -289,6 +289,50 @@
}
@Test
+ public void testSetInitialUser() throws Exception {
+ UserInfo user = new UserInfoBuilder(101).build();
+
+ mCarUserService.setInitialUser(user);
+
+ assertThat(mCarUserService.getInitialUser()).isEqualTo(user.getUserHandle());
+ }
+
+ @Test
+ @ExpectWtf
+ public void testSetInitialUser_nullUser() throws Exception {
+ mCarUserService.setInitialUser(null);
+
+ mockInteractAcrossUsersPermission(true);
+ assertThat(mCarUserService.getInitialUser()).isNull();
+ }
+
+ @Test
+ public void testSendInitialUserToSystemServer() throws Exception {
+ UserInfo user = new UserInfoBuilder(101).build();
+ mCarUserService.setCarServiceHelper(mICarServiceHelper);
+
+ mCarUserService.setInitialUser(user);
+
+ verify(mICarServiceHelper).sendInitialUser(user.getUserHandle());
+ }
+
+ @Test
+ public void testsetInitialUserFromSystemServer() throws Exception {
+ UserHandle user = UserHandle.of(101);
+
+ mCarUserService.setInitialUserFromSystemServer(user);
+
+ assertThat(mCarUserService.getInitialUser()).isEqualTo(user);
+ }
+
+ @Test
+ public void testsetInitialUserFromSystemServer_nullUser() throws Exception {
+ mCarUserService.setInitialUserFromSystemServer(null);
+
+ assertThat(mCarUserService.getInitialUser()).isNull();
+ }
+
+ @Test
public void testSetICarServiceHelper_withUxRestrictions() throws Exception {
mockGetUxRestrictions(/* restricted= */ true);
ICarUxRestrictionsChangeListener listener = initService();
@@ -2209,15 +2253,6 @@
}
@Test
- @ExpectWtf
- public void testSetInitialUser_nullUser() throws Exception {
- mCarUserService.setInitialUser(null);
-
- mockInteractAcrossUsersPermission(true);
- assertThat(mCarUserService.getInitialUser()).isNull();
- }
-
- @Test
public void testOnSuspend_replace() throws Exception {
mockExistingUsersAndCurrentUser(mGuestUser);
when(mInitialUserSetter.canReplaceGuestUser(any())).thenReturn(true);
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 e757536..cb3eb52 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
@@ -16,8 +16,6 @@
package com.android.car.watchdog;
-import static android.automotive.watchdog.internal.ResourceOveruseActionType.KILLED_RECURRING_OVERUSE;
-import static android.automotive.watchdog.internal.ResourceOveruseActionType.NOT_KILLED;
import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetAllUsers;
import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetUserHandles;
@@ -56,7 +54,6 @@
import static org.mockito.Mockito.when;
import android.app.ActivityThread;
-import android.automotive.watchdog.ResourceType;
import android.automotive.watchdog.internal.ApplicationCategoryType;
import android.automotive.watchdog.internal.ComponentType;
import android.automotive.watchdog.internal.GarageMode;
@@ -67,7 +64,6 @@
import android.automotive.watchdog.internal.PackageInfo;
import android.automotive.watchdog.internal.PackageIoOveruseStats;
import android.automotive.watchdog.internal.PackageMetadata;
-import android.automotive.watchdog.internal.PackageResourceOveruseAction;
import android.automotive.watchdog.internal.PerStateIoOveruseThreshold;
import android.automotive.watchdog.internal.PowerCycle;
import android.automotive.watchdog.internal.ResourceSpecificConfiguration;
@@ -178,8 +174,6 @@
@Captor private ArgumentCaptor<List<
android.automotive.watchdog.internal.ResourceOveruseConfiguration>>
mResourceOveruseConfigurationsCaptor;
- @Captor private ArgumentCaptor<List<PackageResourceOveruseAction>>
- mResourceOveruseActionsCaptor;
@Captor private ArgumentCaptor<int[]> mIntArrayCaptor;
@Captor private ArgumentCaptor<byte[]> mOveruseStatsCaptor;
@Captor private ArgumentCaptor<byte[]> mKilledStatsCaptor;
@@ -1881,14 +1875,6 @@
WatchdogPerfHandler.constructCarWatchdogPerStateBytes(300, 600, 900)));
captureAndVerifyKillStatsReported(expectedReportedKillStats);
-
- /* {@link thirdPartyPkgUid} action is sent twice. Once before it is killed and once after
- * it is killed. This is done because the package is killed only after the display is turned
- * off.
- */
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{criticalSysPkgUid, thirdPartyPkgUid},
- /* killedRecurringOveruseUids= */ new int[]{thirdPartyPkgUid}));
}
@Test
@@ -1985,14 +1971,6 @@
WatchdogPerfHandler.constructCarWatchdogPerStateBytes(300, 600, 900)));
captureAndVerifyKillStatsReported(expectedReportedKillStats);
-
- /* {@link thirdPartySharedUid} action is sent twice. Once before it is killed and once after
- * it is killed. This is done because the package is killed only after the display is turned
- * off.
- */
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{criticalSysSharedUid, thirdPartySharedUid},
- /* killedRecurringOveruseUids= */ new int[]{thirdPartySharedUid}));
}
@Test
@@ -2260,11 +2238,6 @@
verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED),
anyInt(), anyInt(), anyInt(), anyInt(), any(), any()), never());
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{}));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty();
}
@@ -2284,11 +2257,6 @@
verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED),
anyInt(), anyInt(), anyInt(), anyInt(), any(), any()), never());
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{}));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty();
}
@@ -2308,11 +2276,6 @@
verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED),
anyInt(), anyInt(), anyInt(), anyInt(), any(), any()), never());
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{}));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty();
}
@@ -2341,12 +2304,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE,
/* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10010004, 10110004, 10010005, 10110005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly(
"100:vendor_package.non_critical", "101:vendor_package.non_critical",
"100:third_party_package.A", "101:third_party_package.A",
@@ -2371,12 +2328,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE,
/* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10010004, 10110004, 10010005, 10110005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly(
"100:vendor_package.non_critical", "101:vendor_package.non_critical",
"100:third_party_package.A", "101:third_party_package.A",
@@ -2411,12 +2362,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE,
/* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10010004, 10110004, 10010005, 10110005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly(
"100:vendor_package.non_critical", "101:vendor_package.non_critical",
"100:third_party_package.A", "101:third_party_package.A",
@@ -2450,12 +2395,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE,
/* killedUids= */ new int[]{10110004, 10010005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10110004, 10010005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages)
.containsExactly("101:vendor_package.non_critical", "100:third_party_package.A",
"100:third_party_package.B");
@@ -2488,12 +2427,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE,
/* killedUids= */ new int[]{10110004, 10010005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10110004, 10010005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages)
.containsExactly("101:vendor_package.non_critical", "100:third_party_package.A",
"100:third_party_package.B");
@@ -2527,12 +2460,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE,
/* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10010004, 10110004, 10010005, 10110005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly(
"100:vendor_package.non_critical", "101:vendor_package.non_critical",
"100:third_party_package.A", "101:third_party_package.A",
@@ -2559,12 +2486,6 @@
CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__GARAGE_MODE,
/* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005}));
- verifyActionsTakenOnResourceOveruse(sampleActionTakenOnOveruse(
- /* notKilledUids= */ new int[]{
- 10010001, 10110001, 10010004, 10110004, 10010005, 10110005},
- /* killedRecurringOveruseUids= */ new int[]{10010004, 10110004, 10010005, 10110005}
- ));
-
assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly(
"100:vendor_package.non_critical", "101:vendor_package.non_critical",
"100:third_party_package.A", "101:third_party_package.A",
@@ -2582,17 +2503,12 @@
String packageName = mMockContext.getPackageName();
mGenericPackageNameByUid.put(10003346, packageName);
mGenericPackageNameByUid.put(10101278, "vendor_package.critical");
- mGenericPackageNameByUid.put(10103456, "third_party_package");
injectIoOveruseStatsForPackages(
mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(),
/* shouldNotifyPackages= */ new ArraySet<>());
- doReturn(COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED).when(mSpiedPackageManager)
- .getApplicationEnabledSetting(
- or(eq("third_party_package"), eq("vendor_package.critical")), eq(101));
-
mWatchdogServiceForSystemImpl.resetResourceOveruseStats(
- Arrays.asList(packageName, "third_party_package"));
+ Collections.singletonList(packageName));
ResourceOveruseStats actualStats =
mCarWatchdogService.getResourceOveruseStatsForUserPackage(
@@ -2606,11 +2522,49 @@
ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats);
verify(mMockWatchdogStorage).deleteUserPackage(eq(user.getIdentifier()), eq(packageName));
+ }
- verify(mSpiedPackageManager).getApplicationEnabledSetting(packageName, 100);
- verify(mSpiedPackageManager).getApplicationEnabledSetting("third_party_package", 101);
- verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("third_party_package"),
- eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(101), anyString());
+ @Test
+ public void testResetResourceOveruseStatsEnablesPackage() throws Exception {
+ injectPackageInfos(Arrays.asList(
+ constructPackageManagerPackageInfo("third_party_package.A", 10012345,
+ /* sharedUserId= */ null),
+ constructPackageManagerPackageInfo("vendor_package.critical.A", 10014567,
+ "vendor_shared_package.A"),
+ constructPackageManagerPackageInfo("vendor_package.critical.B", 10014567,
+ "vendor_shared_package.A"),
+ constructPackageManagerPackageInfo("system_package.critical.A", 10001278,
+ "system_shared_package.A"),
+ constructPackageManagerPackageInfo("third_party_package.B", 10056790,
+ /* sharedUserId= */ null),
+ constructPackageManagerPackageInfo("system_package.non_critical.B", 10007345,
+ "system_shared_package.B")));
+
+ injectIoOveruseStatsForPackages(
+ mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(),
+ /* shouldNotifyPackages= */ new ArraySet<>());
+
+ doReturn(COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED).when(mSpiedPackageManager)
+ .getApplicationEnabledSetting(
+ or(or(eq("third_party_package.A"), eq("vendor_package.critical.A")),
+ eq("vendor_package.critical.B")), eq(100));
+
+ mWatchdogServiceForSystemImpl.resetResourceOveruseStats(
+ Arrays.asList("third_party_package.A", "shared:vendor_shared_package.A",
+ "shared:system_shared_package.A", "third_party_package.B"));
+
+ verify(mSpiedPackageManager).getApplicationEnabledSetting("third_party_package.A", 100);
+ verify(mSpiedPackageManager).getApplicationEnabledSetting("vendor_package.critical.A", 100);
+ verify(mSpiedPackageManager).getApplicationEnabledSetting("vendor_package.critical.B", 100);
+ verify(mSpiedPackageManager).getApplicationEnabledSetting("system_package.critical.A", 100);
+ verify(mSpiedPackageManager).getApplicationEnabledSetting("third_party_package.B", 100);
+
+ verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("third_party_package.A"),
+ eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(100), anyString());
+ verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("vendor_package.critical.A"),
+ eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(100), anyString());
+ verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("vendor_package.critical.B"),
+ eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(100), anyString());
verifyNoMoreInteractions(mSpiedPackageManager);
}
@@ -3264,25 +3218,6 @@
delayedRunOnMainSync(() -> {}, OVERUSE_HANDLING_DELAY_MILLS * 2);
}
- private void verifyActionsTakenOnResourceOveruse(List<PackageResourceOveruseAction> expected)
- throws Exception {
- // notifyActionsTakenOnOveruse is posted on the main thread after taking action, so wait for
- // this to complete by posting a task on the main thread.
- CarServiceUtils.runOnMainSync(() -> {});
-
- verify(mMockCarWatchdogDaemon,
- timeout(MAX_WAIT_TIME_MS).atLeastOnce()).actionTakenOnResourceOveruse(
- mResourceOveruseActionsCaptor.capture());
-
- List<PackageResourceOveruseAction> actual = new ArrayList<>();
- for (List<PackageResourceOveruseAction> actions :
- mResourceOveruseActionsCaptor.getAllValues()) {
- actual.addAll(actions);
- }
-
- PackageResourceOveruseActionSubject.assertThat(actual).containsExactlyElementsIn(expected);
- }
-
private void setUpSampleUserAndPackages() {
mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100, 101);
int[] users = new int[]{100, 101};
@@ -3404,22 +3339,6 @@
return reportedKillStats;
}
- private List<PackageResourceOveruseAction> sampleActionTakenOnOveruse(
- int[] notKilledUids, int[] killedRecurringOveruseUids) {
- List<PackageResourceOveruseAction> actions = new ArrayList<>();
- for (int uid : notKilledUids) {
- actions.add(constructPackageResourceOveruseAction(
- mGenericPackageNameByUid.get(uid), uid, new int[]{ResourceType.IO}, NOT_KILLED)
- );
- }
- for (int uid : killedRecurringOveruseUids) {
- actions.add(constructPackageResourceOveruseAction(
- mGenericPackageNameByUid.get(uid), uid, new int[]{ResourceType.IO},
- KILLED_RECURRING_OVERUSE));
- }
- return actions;
- }
-
private static void verifyOnOveruseCalled(List<ResourceOveruseStats> expectedStats,
IResourceOveruseListener mockListener) throws Exception {
ArgumentCaptor<ResourceOveruseStats> resourceOveruseStatsCaptor =
@@ -3667,17 +3586,6 @@
return stats;
}
- private static PackageResourceOveruseAction constructPackageResourceOveruseAction(
- String packageName, int uid, int[] resourceTypes, int resourceOveruseActionType) {
- PackageResourceOveruseAction action = new PackageResourceOveruseAction();
- action.packageIdentifier = new PackageIdentifier();
- action.packageIdentifier.name = packageName;
- action.packageIdentifier.uid = uid;
- action.resourceTypes = resourceTypes;
- action.resourceOveruseActionType = resourceOveruseActionType;
- return action;
- }
-
private static void delayedRunOnMainSync(Runnable action, long delayMillis)
throws InterruptedException {
AtomicBoolean isComplete = new AtomicBoolean();
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/PackageResourceOveruseActionSubject.java b/tests/carservice_unit_test/src/com/android/car/watchdog/PackageResourceOveruseActionSubject.java
deleted file mode 100644
index d0911a3..0000000
--- a/tests/carservice_unit_test/src/com/android/car/watchdog/PackageResourceOveruseActionSubject.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.watchdog;
-
-import static com.google.common.truth.Truth.assertAbout;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.annotation.Nullable;
-import android.automotive.watchdog.internal.PackageIdentifier;
-import android.automotive.watchdog.internal.PackageResourceOveruseAction;
-
-import com.google.common.truth.Correspondence;
-import com.google.common.truth.FailureMetadata;
-import com.google.common.truth.Subject;
-
-import java.util.Arrays;
-
-public final class PackageResourceOveruseActionSubject extends Subject {
- /* Boiler-plate Subject.Factory for PackageResourceOveruseActionSubject. */
- private static final Subject.Factory<
- com.android.car.watchdog.PackageResourceOveruseActionSubject,
- Iterable<PackageResourceOveruseAction>>
- PACKAGE_RESOURCE_OVERUSE_ACTION_SUBJECT_FACTORY =
- com.android.car.watchdog.PackageResourceOveruseActionSubject::new;
-
- private final Iterable<PackageResourceOveruseAction> mActual;
-
- /* User-defined entry point. */
- public static PackageResourceOveruseActionSubject assertThat(
- @Nullable Iterable<PackageResourceOveruseAction> actions) {
- return assertAbout(PACKAGE_RESOURCE_OVERUSE_ACTION_SUBJECT_FACTORY).that(actions);
- }
-
- public static Subject.Factory<PackageResourceOveruseActionSubject,
- Iterable<PackageResourceOveruseAction>> packageResourceOveruseActions() {
- return PACKAGE_RESOURCE_OVERUSE_ACTION_SUBJECT_FACTORY;
- }
-
- public void containsExactly(PackageResourceOveruseAction... actions) {
- containsExactlyElementsIn(Arrays.asList(actions));
- }
-
- public void containsExactlyElementsIn(
- Iterable<PackageResourceOveruseAction> expected) {
- assertWithMessage("Package resource overuse actions:\nExpected: %s\nActual: %s\n",
- toString(expected), toString(mActual)).that(mActual)
- .comparingElementsUsing(Correspondence.from(
- PackageResourceOveruseActionSubject::isEquals, "is equal to"))
- .containsExactlyElementsIn(expected);
- }
-
- public static boolean isEquals(PackageResourceOveruseAction actual,
- PackageResourceOveruseAction expected) {
- if (actual == null || expected == null) {
- return (actual == null) && (expected == null);
- }
- return isPackageIdentifierEquals(actual.packageIdentifier, expected.packageIdentifier)
- && Arrays.equals(actual.resourceTypes, expected.resourceTypes)
- && actual.resourceOveruseActionType == expected.resourceOveruseActionType;
- }
-
- private static boolean isPackageIdentifierEquals(PackageIdentifier lhs, PackageIdentifier rhs) {
- return lhs.name.equals(rhs.name) && lhs.uid == rhs.uid;
- }
-
- public static String toString(Iterable<PackageResourceOveruseAction> actions) {
- StringBuilder builder = new StringBuilder();
- builder.append("[");
- for (PackageResourceOveruseAction action : actions) {
- builder = toStringBuilder(builder, action);
- builder.append(", ");
- }
- if (builder.length() > 1) {
- builder.delete(builder.length() - 2, builder.length());
- }
- builder.append("]");
- return builder.toString();
- }
-
- public static StringBuilder toStringBuilder(
- StringBuilder builder, PackageResourceOveruseAction action) {
- return builder.append("{Package Identifier: {Name: ")
- .append(action.packageIdentifier.name)
- .append(", UID: ").append(action.packageIdentifier.uid)
- .append("}, Resource Types: ").append(Arrays.toString(action.resourceTypes))
- .append(", Action Type: ").append(action.resourceOveruseActionType).append("}");
- }
-
- private PackageResourceOveruseActionSubject(FailureMetadata failureMetadata,
- @Nullable Iterable<PackageResourceOveruseAction> iterableSubject) {
- super(failureMetadata, iterableSubject);
- this.mActual = iterableSubject;
- }
-}