Merge "Fix a bug where the locale was not switching properly for user-10." into sc-v2-dev
diff --git a/car-lib/src/android/car/telemetry/CarTelemetryManager.java b/car-lib/src/android/car/telemetry/CarTelemetryManager.java
index 5d2b4cc..097ad98 100644
--- a/car-lib/src/android/car/telemetry/CarTelemetryManager.java
+++ b/car-lib/src/android/car/telemetry/CarTelemetryManager.java
@@ -182,28 +182,46 @@
private void onResult(MetricsConfigKey key, byte[] result) {
long token = Binder.clearCallingIdentity();
- synchronized (mLock) {
- // TODO(b/198824696): listener should be nonnull
- mExecutor.execute(() -> mResultsListener.onResult(key, result));
+ Executor executor = getExecutor();
+ if (executor == null) {
+ return;
}
+ executor.execute(() -> {
+ CarTelemetryResultsListener listener = getResultsListener();
+ if (listener != null) {
+ listener.onResult(key, result);
+ }
+ });
Binder.restoreCallingIdentity(token);
}
private void onError(MetricsConfigKey key, byte[] error) {
long token = Binder.clearCallingIdentity();
- synchronized (mLock) {
- // TODO(b/198824696): listener should be nonnull
- mExecutor.execute(() -> mResultsListener.onError(key, error));
+ Executor executor = getExecutor();
+ if (executor == null) {
+ return;
}
+ executor.execute(() -> {
+ CarTelemetryResultsListener listener = getResultsListener();
+ if (listener != null) {
+ listener.onError(key, error);
+ }
+ });
Binder.restoreCallingIdentity(token);
}
private void onAddMetricsConfigStatus(MetricsConfigKey key, int statusCode) {
long token = Binder.clearCallingIdentity();
- synchronized (mLock) {
- // TODO(b/198824696): listener should be nonnull
- mExecutor.execute(() -> mResultsListener.onAddMetricsConfigStatus(key, statusCode));
+ Executor executor = getExecutor();
+ if (executor == null) {
+ return;
}
+ executor.execute(() -> {
+ CarTelemetryResultsListener listener = getResultsListener();
+ if (listener != null) {
+ listener.onAddMetricsConfigStatus(key, statusCode);
+ }
+ });
Binder.restoreCallingIdentity(token);
}
@@ -237,7 +255,8 @@
/**
* Registers a listener with {@link com.android.car.telemetry.CarTelemetryService} for client
- * to receive script execution results.
+ * to receive script execution results. The listener must be set before invoking other APIs in
+ * this class.
*
* @param listener to received data from {@link com.android.car.telemetry.CarTelemetryService}.
* @throws IllegalStateException if the listener is already set.
@@ -285,17 +304,22 @@
* The {@link MetricsConfigKey} is used to uniquely identify a MetricsConfig. If a MetricsConfig
* of the same name already exists in {@link com.android.car.telemetry.CarTelemetryService},
* the config version will be compared. If the version is strictly higher, the existing
- * MetricsConfig will be replaced by the new one. All cache and intermediate results will be
- * cleared if replaced.
+ * MetricsConfig will be replaced by the new one. All legacy data will be cleared if replaced.
+ * Client should use {@link #sendFinishedReports(MetricsConfigKey)} to get the result before
+ * replacing a MetricsConfig.
* The status of this API is sent back asynchronously via {@link CarTelemetryResultsListener}.
*
* @param key the unique key to identify the MetricsConfig.
* @param metricsConfig the serialized bytes of a MetricsConfig object.
* @throws IllegalArgumentException if the MetricsConfig size exceeds limit.
+ * @throws IllegalStateException if the listener is not set.
* @hide
*/
@RequiresPermission(Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE)
public void addMetricsConfig(@NonNull MetricsConfigKey key, @NonNull byte[] metricsConfig) {
+ if (getResultsListener() == null) {
+ throw new IllegalStateException("Listener must be set.");
+ }
if (metricsConfig.length > METRICS_CONFIG_MAX_SIZE_BYTES) {
throw new IllegalArgumentException("MetricsConfig size exceeds limit.");
}
@@ -312,11 +336,14 @@
* nothing will be removed.
*
* @param key the unique key to identify the MetricsConfig. Name and version must be exact.
- * @return true for success, false otherwise.
+ * @throws IllegalStateException if the listener is not set.
* @hide
*/
@RequiresPermission(Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE)
public void removeMetricsConfig(@NonNull MetricsConfigKey key) {
+ if (getResultsListener() == null) {
+ throw new IllegalStateException("Listener must be set.");
+ }
try {
mService.removeMetricsConfig(key);
} catch (RemoteException e) {
@@ -328,10 +355,14 @@
* Removes all MetricsConfigs from {@link com.android.car.telemetry.CarTelemetryService}. This
* will also remove all MetricsConfig outputs.
*
+ * @throws IllegalStateException if the listener is not set.
* @hide
*/
@RequiresPermission(Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE)
public void removeAllMetricsConfigs() {
+ if (getResultsListener() == null) {
+ throw new IllegalStateException("Listener must be set.");
+ }
try {
mService.removeAllMetricsConfigs();
} catch (RemoteException e) {
@@ -346,10 +377,14 @@
* This call is destructive. The returned results will be deleted from CarTelemetryService.
*
* @param key the unique key to identify the MetricsConfig.
+ * @throws IllegalStateException if the listener is not set.
* @hide
*/
@RequiresPermission(Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE)
public void sendFinishedReports(@NonNull MetricsConfigKey key) {
+ if (getResultsListener() == null) {
+ throw new IllegalStateException("Listener must be set.");
+ }
try {
mService.sendFinishedReports(key);
} catch (RemoteException e) {
@@ -362,14 +397,30 @@
* asynchronously via the {@link CarTelemetryResultsListener}.
* This call is destructive. The returned results will be deleted from CarTelemetryService.
*
+ * @throws IllegalStateException if the listener is not set.
* @hide
*/
@RequiresPermission(Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE)
public void sendAllFinishedReports() {
+ if (getResultsListener() == null) {
+ throw new IllegalStateException("Listener must be set.");
+ }
try {
mService.sendAllFinishedReports();
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
+
+ private CarTelemetryResultsListener getResultsListener() {
+ synchronized (mLock) {
+ return mResultsListener;
+ }
+ }
+
+ private Executor getExecutor() {
+ synchronized (mLock) {
+ return mExecutor;
+ }
+ }
}
diff --git a/car-test-lib/Android.bp b/car-test-lib/Android.bp
index bb72590..bad376e 100644
--- a/car-test-lib/Android.bp
+++ b/car-test-lib/Android.bp
@@ -48,5 +48,6 @@
"android.hardware.automotive.vehicle-V2.0-java",
"mockito-target-extended",
"compatibility-device-util-axt",
+ "android.test.mock",
],
}
diff --git a/car-test-lib/src/android/car/test/util/BroadcastingFakeContext.java b/car-test-lib/src/android/car/test/util/BroadcastingFakeContext.java
new file mode 100644
index 0000000..014e283
--- /dev/null
+++ b/car-test-lib/src/android/car/test/util/BroadcastingFakeContext.java
@@ -0,0 +1,107 @@
+/*
+ * 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.car.test.util;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.test.mock.MockContext;
+
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A fake implementation for {@link android.content.Context}, that helps broadcast {@link Intent}s
+ * to registered {@link BroadcastReceiver} instances.
+ */
+// TODO(b/202420937): Add unit tests for this class.
+public final class BroadcastingFakeContext extends MockContext {
+ private BroadcastReceiver mReceiver;
+ private IntentFilter mIntentFilter;
+ private Handler mHandler;
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ mReceiver = receiver;
+ mIntentFilter = filter;
+
+ return null;
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler) {
+ mReceiver = receiver;
+ mIntentFilter = filter;
+ mHandler = scheduler;
+
+ return null;
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent) {
+ if (mHandler == null) {
+ mReceiver.onReceive(this, intent);
+ return;
+ }
+
+ CountDownLatch latch = new CountDownLatch(1);
+ mHandler.getLooper().getQueue().addIdleHandler(() -> {
+ latch.countDown();
+ return false;
+ });
+
+ mHandler.post(() -> mReceiver.onReceive(this, intent));
+
+ // wait until the queue is idle
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException(
+ "Interrupted while waiting for Broadcast Intent to be received");
+ }
+ }
+
+ @Override
+ public void unregisterReceiver(BroadcastReceiver receiver) {
+ if (receiver == mReceiver) {
+ mReceiver = null;
+ mIntentFilter = null;
+ mHandler = null;
+ }
+ }
+
+ public void verifyReceiverNotRegistered() {
+ assertThat(mIntentFilter).isNull();
+ assertThat(mReceiver).isNull();
+ assertThat(mHandler).isNull();
+ }
+
+ public void verifyReceiverRegistered(String expectedAction) {
+ assertThat(mIntentFilter.actionsIterator()).isNotNull();
+ ArrayList<String> actions = Lists.newArrayList(mIntentFilter.actionsIterator());
+ assertWithMessage("IntentFilter actions").that(actions).contains(expectedAction);
+ assertWithMessage("Registered BroadcastReceiver").that(mReceiver).isNotNull();
+ }
+}
diff --git a/car_product/build/car.mk b/car_product/build/car.mk
index 67202f2..7700cca 100644
--- a/car_product/build/car.mk
+++ b/car_product/build/car.mk
@@ -24,6 +24,7 @@
CarActivityResolver \
CarDeveloperOptions \
CarSettingsIntelligence \
+ CarManagedProvisioning \
OneTimeInitializer \
CarProvision \
StatementService \
diff --git a/car_product/build/car_base.mk b/car_product/build/car_base.mk
index 4d3cf5e..c0d5190 100644
--- a/car_product/build/car_base.mk
+++ b/car_product/build/car_base.mk
@@ -42,7 +42,6 @@
Keyguard \
LatinIME \
Launcher2 \
- ManagedProvisioning \
PacProcessor \
PrintSpooler \
ProxyHandler \
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_bottom_system_bar.xml b/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_bottom_system_bar.xml
index 69c3d30..b5dcecb 100644
--- a/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_bottom_system_bar.xml
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_bottom_system_bar.xml
@@ -48,7 +48,7 @@
android:gravity="center"
android:layoutDirection="ltr">
- <com.android.systemui.car.systembar.CarSystemBarButton
+ <com.android.systemui.car.systembar.DisplayAreaButton
android:id="@+id/grid_nav"
style="@style/SystemBarButton"
systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
@@ -58,7 +58,7 @@
systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"
systemui:clearBackStack="true"/>
- <com.android.systemui.car.systembar.CarSystemBarButton
+ <com.android.systemui.car.systembar.DisplayAreaButton
android:id="@+id/standalone_notifications"
style="@style/SystemBarButton"
systemui:componentNames="com.android.car.notification/.CarNotificationCenterActivity"
@@ -69,7 +69,7 @@
systemui:intent="intent:#Intent;component=com.android.car.notification/.CarNotificationCenterActivity;launchFlags=0x24000000;end"
systemui:longIntent="intent:#Intent;component=com.android.car.bugreport/.BugReportActivity;end"/>
- <com.android.systemui.car.systembar.CarSystemBarButton
+ <com.android.systemui.car.systembar.HvacButton
android:id="@+id/hvac"
style="@style/SystemBarButton"
systemui:icon="@drawable/car_ic_hvac"
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_top_system_bar.xml b/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_top_system_bar.xml
index e30ec45..83b759b 100644
--- a/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_top_system_bar.xml
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/res/layout/car_top_system_bar.xml
@@ -64,22 +64,35 @@
android:textAppearance="@style/TextAppearance.SystemBar.Clock"
systemui:amPmStyle="normal"/>
- <com.android.systemui.car.systembar.CarSystemBarButton
- android:id="@+id/system_icon_area"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/car_padding_3"
android:layout_gravity="end"
- android:gravity="end"
- systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivities$HomepageActivity;launchFlags=0x24000000;end">
+ android:orientation="horizontal"
+ android:gravity="end">
- <com.android.systemui.statusbar.phone.StatusIconContainer
- android:id="@+id/statusIcons"
- android:layout_width="match_parent"
+ <include layout="@layout/mic_privacy_chip"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical"/>
+
+ <com.android.systemui.car.systembar.CarSystemBarButton
+ android:id="@+id/system_icon_area"
+ android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:scaleType="fitCenter"
- android:gravity="center"
- android:orientation="horizontal"
- />
- </com.android.systemui.car.systembar.CarSystemBarButton>
-</com.android.systemui.car.systembar.CarSystemBarView>
\ No newline at end of file
+ android:layout_marginEnd="@dimen/car_padding_3"
+ android:layout_gravity="end"
+ android:gravity="end"
+ systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivities$HomepageActivity;launchFlags=0x24000000;end">
+
+ <com.android.systemui.statusbar.phone.StatusIconContainer
+ android:id="@+id/statusIcons"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitCenter"
+ android:gravity="center"
+ android:orientation="horizontal"/>
+
+ </com.android.systemui.car.systembar.CarSystemBarButton>
+ </LinearLayout>
+</com.android.systemui.car.systembar.CarSystemBarView>
diff --git a/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/src/com/android/systemui/car/systembar/DisplayAreaButton.java b/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/src/com/android/systemui/car/systembar/DisplayAreaButton.java
new file mode 100644
index 0000000..1412903
--- /dev/null
+++ b/car_product/car_ui_portrait/apps/CarUiPortraitSystemUI/src/com/android/systemui/car/systembar/DisplayAreaButton.java
@@ -0,0 +1,56 @@
+/*
+ * 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.systemui.car.systembar;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.AttributeSet;
+
+/** A CarSystemBarButton that controls a display area. */
+public class DisplayAreaButton extends CarSystemBarButton {
+
+ // TODO(b/194334719): Remove when display area logic is moved into systemui
+ private static final String DISPLAY_AREA_VISIBILITY_CHANGED =
+ "com.android.car.carlauncher.displayarea.DISPLAY_AREA_VISIBILITY_CHANGED";
+ private static final String INTENT_EXTRA_IS_DISPLAY_AREA_VISIBLE =
+ "EXTRA_IS_DISPLAY_AREA_VISIBLE";
+
+ /**
+ * A broadcast receiver to listen when the display area is closed via swipe.
+ * When the display area logic is moved from launcher into system ui, the DisplayAreaButton
+ * should be notified of changes in the panel's visibility directly, rather than using a
+ * broadcast.
+ */
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean isDisplayAreaVisible = intent.getBooleanExtra(
+ INTENT_EXTRA_IS_DISPLAY_AREA_VISIBLE, /* defaultValue= */ true);
+ if (getSelected() && !isDisplayAreaVisible) {
+ context.getMainExecutor().execute(() -> setSelected(/* selected= */ false));
+ }
+ }
+ };
+
+ public DisplayAreaButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ context.registerReceiver(mBroadcastReceiver,
+ new IntentFilter(DISPLAY_AREA_VISIBILITY_CHANGED));
+ }
+}
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/incall_dialpad_fragment.xml b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/incall_dialpad_fragment.xml
new file mode 100644
index 0000000..e7b31ed
--- /dev/null
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/incall_dialpad_fragment.xml
@@ -0,0 +1,56 @@
+<?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.
+ -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:singleLine="true"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"/>
+
+ <Chronometer
+ android:id="@+id/call_state"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:singleLine="true"
+ android:layout_marginTop="40dp"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/title"/>
+
+ <com.android.car.ui.FocusArea
+ android:id="@+id/dialpad_focus_area"
+ android:layout_height="456dp"
+ android:layout_width="416dp"
+ android:layout_marginBottom="171dp"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true">
+
+ <fragment
+ android:id="@+id/dialpad_fragment"
+ android:name="com.android.car.dialer.ui.dialpad.KeypadFragment"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+
+ </com.android.car.ui.FocusArea>
+</RelativeLayout>
\ No newline at end of file
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/ongoing_call_fragment.xml b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/ongoing_call_fragment.xml
new file mode 100644
index 0000000..0e76d6b
--- /dev/null
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/ongoing_call_fragment.xml
@@ -0,0 +1,55 @@
+<!--
+ ~ 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.car.apps.common.BackgroundImageView
+ android:id="@+id/background_image"
+ android:layout_width="0dp"
+ android:layout_height="0dp"/>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/transparent">
+
+ <fragment
+ android:name="com.android.car.dialer.ui.dialpad.InCallDialpadFragment"
+ android:id="@+id/incall_dialpad_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="0dp">
+
+ <include
+ layout="@layout/user_profile_large"
+ android:id="@+id/user_profile_container"/>
+
+ </LinearLayout>
+
+ <fragment
+ android:id="@+id/onhold_user_profile"
+ android:name="com.android.car.dialer.ui.activecall.OnHoldCallUserProfileFragment"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"/>
+
+ </RelativeLayout>
+
+</LinearLayout>
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/user_profile_large.xml b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/user_profile_large.xml
new file mode 100644
index 0000000..f59ee9e
--- /dev/null
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/layout/user_profile_large.xml
@@ -0,0 +1,52 @@
+<?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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="start|center_vertical"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/user_profile_avatar"
+ android:layout_width="196dp"
+ android:layout_height="196dp"
+ android:scaleType="fitCenter"/>
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/user_profile_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"/>
+ <TextView
+ android:id="@+id/user_profile_phone_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"/>
+
+ <!-- A textView without a fixed width will call requestLayout() every time its text is changed -->
+ <!-- So we have to make this Chronometer match_parent to avoid redrawing the whole screen -->
+ <Chronometer
+ android:id="@+id/user_profile_call_state"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/values/configs.xml b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/values/configs.xml
index 2f28c76..39e81f6 100644
--- a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/values/configs.xml
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/values/configs.xml
@@ -17,4 +17,6 @@
<resources>
<integer name="config_dialed_number_gravity">1</integer>
+
+ <bool name="config_always_show_incall_dialpad">true</bool>
</resources>
\ No newline at end of file
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/xml/overlays.xml b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/xml/overlays.xml
index 848c5eb..2064bc4 100644
--- a/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/xml/overlays.xml
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitDialerRRO/res/xml/overlays.xml
@@ -42,10 +42,22 @@
<item target="id/error_icon" value="@id/error_icon" />
<item target="id/error_string" value="@id/error_string" />
<item target="id/connect_bluetooth_button" value="@id/connect_bluetooth_button" />
+ <item target="id/background_image" value="@id/background_image" />
+ <item target="id/incall_dialpad_fragment" value="@id/incall_dialpad_fragment" />
+ <item target="id/user_profile_container" value="@id/user_profile_container" />
+ <item target="id/onhold_user_profile" value="@id/onhold_user_profile" />
+ <item target="id/user_profile_avatar" value="@id/user_profile_avatar" />
+ <item target="id/user_profile_title" value="@id/user_profile_title" />
+ <item target="id/user_profile_phone_number" value="@id/user_profile_phone_number" />
+ <item target="id/user_profile_call_state" value="@id/user_profile_call_state" />
+ <item target="id/call_state" value="@id/call_state" />
+ <item target="id/dialpad_focus_area" value="@id/dialpad_focus_area" />
<item target="color/divider_color" value="@color/divider_color" />
<item target="color/hero_button_background_color" value="@color/hero_button_background_color" />
+ <item target="bool/config_always_show_incall_dialpad" value="@bool/config_always_show_incall_dialpad" />
+
<item target="integer/config_dialed_number_gravity" value="@integer/config_dialed_number_gravity" />
<item target="layout/dialpad_fragment_with_type_down" value="@layout/dialpad_fragment_with_type_down"/>
@@ -53,6 +65,9 @@
<item target="layout/type_down_list_item" value="@layout/type_down_list_item"/>
<item target="layout/restricted_dialing_mode_label" value="@layout/restricted_dialing_mode_label"/>
<item target="layout/no_hfp" value="@layout/no_hfp"/>
+ <item target="layout/ongoing_call_fragment" value="@layout/ongoing_call_fragment"/>
+ <item target="layout/user_profile_large" value="@layout/user_profile_large"/>
+ <item target="layout/incall_dialpad_fragment" value="@layout/incall_dialpad_fragment"/>
<item target="style/KeypadButtonStyle" value="@style/KeypadButtonStyle"/>
<item target="style/TextAppearance.DialNumber" value="@style/TextAppearance.DialNumber"/>
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitLauncherRRO/res/values/config.xml b/car_product/car_ui_portrait/rro/CarUiPortraitLauncherRRO/res/values/config.xml
index 059f7b1..d049e9b 100644
--- a/car_product/car_ui_portrait/rro/CarUiPortraitLauncherRRO/res/values/config.xml
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitLauncherRRO/res/values/config.xml
@@ -33,5 +33,8 @@
<item>com.google.android.gms/.auth.uiflows.common.UnpackingRedirectActivity</item>
<item>com.google.android.gms/.auth.auto.SignInMethodActivity</item>
<item>com.google.android.gms/.auth.uiflows.minutemaid.MinuteMaidActivity</item>
+ <item>android.car.cluster/android.car.cluster.FakeFreeNavigationActivity</item>
+ <item>android.car.cluster/android.car.cluster.MainClusterActivity</item>
+ <item>android.car.usb.handler/android.car.usb.handler.UsbHostManagementActivity</item>
</string-array>
</resources>
diff --git a/car_product/car_ui_portrait/rro/CarUiPortraitNotificationRRO/res/layout/headsup_container_bottom.xml b/car_product/car_ui_portrait/rro/CarUiPortraitNotificationRRO/res/layout/headsup_container_bottom.xml
index 3cff34a..66f7085 100644
--- a/car_product/car_ui_portrait/rro/CarUiPortraitNotificationRRO/res/layout/headsup_container_bottom.xml
+++ b/car_product/car_ui_portrait/rro/CarUiPortraitNotificationRRO/res/layout/headsup_container_bottom.xml
@@ -15,17 +15,16 @@
~ limitations under the License.
-->
-<RelativeLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/notification_headsup"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content">
<com.android.car.notification.headsup.HeadsUpContainerView
android:id="@+id/headsup_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/headsup_notification_bottom_margin"/>
-</RelativeLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/car_product/car_ui_portrait/rro/android/res/color/overview_background.xml b/car_product/car_ui_portrait/rro/android/res/color/overview_background.xml
new file mode 100644
index 0000000..1e98723
--- /dev/null
+++ b/car_product/car_ui_portrait/rro/android/res/color/overview_background.xml
@@ -0,0 +1,19 @@
+<?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:color="@android:color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/car_product/car_ui_portrait/rro/android/res/color/overview_background_dark.xml b/car_product/car_ui_portrait/rro/android/res/color/overview_background_dark.xml
new file mode 100644
index 0000000..1e98723
--- /dev/null
+++ b/car_product/car_ui_portrait/rro/android/res/color/overview_background_dark.xml
@@ -0,0 +1,19 @@
+<?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:color="@android:color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selected_background_color_selector.xml b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selected_background_color_selector.xml
new file mode 100644
index 0000000..a01a016
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selected_background_color_selector.xml
@@ -0,0 +1,22 @@
+<?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_selected="true"
+ android:color="@color/car_seekbar_thumb_selected_background_color"/>
+ <item android:color="@android:color/transparent"/>
+</selector>
\ No newline at end of file
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selected_stroke_color_selector.xml b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selected_stroke_color_selector.xml
new file mode 100644
index 0000000..a8ab141
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selected_stroke_color_selector.xml
@@ -0,0 +1,22 @@
+<?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_selected="true"
+ android:color="@color/car_seekbar_thumb_selected_stroke_color"/>
+ <item android:color="@android:color/transparent"/>
+</selector>
\ No newline at end of file
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selector.xml b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selector.xml
new file mode 100644
index 0000000..4fdabcc
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/color/car_seekbar_thumb_selector.xml
@@ -0,0 +1,22 @@
+<?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_enabled="false"
+ android:color="@color/car_seekbar_thumb_disabled_on_dark"/>
+ <item android:color="@color/car_seekbar_thumb"/>
+</selector>
\ No newline at end of file
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_thumb.xml b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_thumb.xml
new file mode 100644
index 0000000..493eeb2
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_thumb.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="52dp"
+ android:height="52dp"
+ android:viewportWidth="52"
+ android:viewportHeight="52">
+ <path
+ android:pathData="M52,26A26,26 0,0 1,26 52,26 26,0 0,1 0,26 26,26 0,0 1,26 0,26 26,0 0,1 52,26Z"
+ android:fillAlpha="0.56">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:gradientRadius="26"
+ android:centerX="26"
+ android:centerY="26"
+ android:type="radial">
+ <item android:offset="0" android:color="#8F000000"/>
+ <item android:offset="0.92307687" android:color="#8F000000"/>
+ <item android:offset="1" android:color="#00000000"/>
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:pathData="M26,26m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"
+ android:fillColor="?attr/colorSeekbarThumb"/>
+</vector>
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_thumb_selectable.xml b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_thumb_selectable.xml
new file mode 100644
index 0000000..2709180
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_thumb_selectable.xml
@@ -0,0 +1,31 @@
+<?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:drawable="@drawable/car_seekbar_thumb"
+ android:gravity="center" />
+ <item
+ android:gravity="center"
+ android:width="@dimen/car_seekbar_thumb_size"
+ android:height="@dimen/car_seekbar_thumb_size">
+ <shape android:shape="oval">
+ <stroke
+ android:color="@color/car_seekbar_thumb_selected_stroke_color_selector"
+ android:width="@dimen/car_seekbar_thumb_selected_stroke_width" />
+ <solid android:color="@color/car_seekbar_thumb_selected_background_color_selector" />
+ </shape>
+ </item>
+</layer-list>
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_track.xml b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_track.xml
new file mode 100644
index 0000000..394a132
--- /dev/null
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/drawable/car_seekbar_track.xml
@@ -0,0 +1,52 @@
+<?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:id="@android:id/background"
+ android:top="@dimen/car_seekbar_track_vertical_padding"
+ android:bottom="@dimen/car_seekbar_track_vertical_padding">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_switch_thumb_outer_radius" />
+ <size android:height="@dimen/car_seekbar_track_height" />
+ <solid android:color="?attr/colorSeekBarTrackBackground" />
+ </shape>
+ </item>
+ <item
+ android:id="@android:id/secondaryProgress"
+ android:top="@dimen/car_seekbar_track_vertical_padding"
+ android:bottom="@dimen/car_seekbar_track_vertical_padding">
+ <scale android:scaleWidth="100%">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_switch_thumb_outer_radius" />
+ <size android:height="@dimen/car_seekbar_track_height" />
+ <solid android:color="?attr/colorSeekBarTrackProgressSecondary" />
+ </shape>
+ </scale>
+ </item>
+ <item
+ android:id="@android:id/progress"
+ android:top="@dimen/car_seekbar_track_vertical_padding"
+ android:bottom="@dimen/car_seekbar_track_vertical_padding">
+ <clip>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_switch_thumb_outer_radius" />
+ <size android:height="@dimen/car_seekbar_track_height" />
+ <solid android:color="?attr/colorSeekBarTrackProgress" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/values/attrs.xml b/car_product/overlay-visual/frameworks/base/core/res/res/values/attrs.xml
index 18376cc..05506a7 100644
--- a/car_product/overlay-visual/frameworks/base/core/res/res/values/attrs.xml
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/values/attrs.xml
@@ -18,4 +18,8 @@
<attr name="colorSwitchThumbDisabled" format="color" />
<attr name="colorSwitchThumbNormal" format="color" />
<attr name="colorSwitchTrack" format="color" />
+ <attr name="colorSeekBarTrackBackground" format="color" />
+ <attr name="colorSeekBarTrackProgress" format="color" />
+ <attr name="colorSeekBarTrackProgressSecondary" format="color" />
+ <attr name="colorSeekbarThumb" format="color"/>
</resources>
\ No newline at end of file
diff --git a/car_product/overlay-visual/frameworks/base/core/res/res/values/colors.xml b/car_product/overlay-visual/frameworks/base/core/res/res/values/colors.xml
index 9e08f57..e6eae25 100644
--- a/car_product/overlay-visual/frameworks/base/core/res/res/values/colors.xml
+++ b/car_product/overlay-visual/frameworks/base/core/res/res/values/colors.xml
@@ -47,9 +47,22 @@
<color name="car_switch_track_background_unchecked_disabled">#75757575</color>
<!-- The Switch thumb color. -->
<color name="car_switch_thumb_color">#FFFFFF</color>
- <!-- The Switch thumb color whhen disabled and using the dark theme. -->
+ <!-- The Switch thumb color when disabled and using the dark theme. -->
<color name="car_switch_thumb_color_disabled_on_dark">#757575</color>
- <!-- The Switch thumb color whhen disabled and using the light theme. -->
+ <!-- The Switch thumb color when disabled and using the light theme. -->
<color name="car_switch_thumb_color_disabled_on_light">@color/car_switch_thumb_color</color>
-
+ <!-- The Switch track's background color. -->
+ <color name="car_seekbar_track_background">#757575</color>
+ <!-- The Switch track's progress color. -->
+ <color name="car_seekbar_track_progress">#66B5FF</color>
+ <!-- The Switch track's secondary progress color. -->
+ <color name="car_seekbar_track_progress_secondary">#A6A6A9</color>
+ <!-- Color of the outer ring when the SeekBar is selected. -->
+ <color name="car_seekbar_thumb_selected_stroke_color">#94CBFF</color>
+ <!-- Color of the background of the ring when the SeekBar is selected. -->
+ <color name="car_seekbar_thumb_selected_background_color">#3D94CBFF</color>
+ <!-- The SeekBar thumb color. -->
+ <color name="car_seekbar_thumb">#FFFFFF</color>
+ <!-- The SeekBar thumb color when disabled. Use for the dark theme. -->
+ <color name="car_seekbar_thumb_disabled_on_dark">#757575</color>
</resources>
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 14d7bc6..b1ab72a 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
@@ -17,10 +17,10 @@
*/
-->
<resources>
- <dimen name="status_bar_height">68dp</dimen>
- <dimen name="status_bar_height_landscape">68dp</dimen>
- <dimen name="status_bar_height_portrait">68dp</dimen>
- <dimen name="car_qs_header_system_icons_area_height">68dp</dimen>
+ <dimen name="status_bar_height">76dp</dimen>
+ <dimen name="status_bar_height_landscape">76dp</dimen>
+ <dimen name="status_bar_height_portrait">76dp</dimen>
+ <dimen name="car_qs_header_system_icons_area_height">76dp</dimen>
<dimen name="navigation_bar_height">96dp</dimen>
<dimen name="navigation_bar_height_landscape">96dp</dimen>
@@ -145,4 +145,22 @@
<dimen name="car_switch_thumb_stroke_width">4dp</dimen>
<!-- car_switch_thumb_size + car_switch_thumb_stroke_width == car_switch_track_height -->
<dimen name="car_switch_thumb_size">40dp</dimen>
+
+ <!-- SeekBar dimensions. -->
+ <!-- Allows thumb to extend out of the range of the track. -->
+ <!-- For more information see android.widget.SeekBar#attr_android:thumbOffset. -->
+ <dimen name="car_seekbar_thumb_offset">24dp</dimen>
+ <!-- Horizontal padding for the SeekBar.-->
+ <dimen name="car_seekbar_horizontal_padding">24dp</dimen>
+ <!-- The SeekBar track height.-->
+ <dimen name="car_seekbar_track_height">24dp</dimen>
+ <!-- Vertical padding that extends the touch area for the SeekBar. -->
+ <dimen name="car_seekbar_track_vertical_padding">26dp</dimen>
+ <!-- The stroke with of the ring around the SeekBar thumb when selected. -->
+ <dimen name="car_seekbar_thumb_selected_stroke_width">8dp</dimen>
+ <!-- The size of the SeekBar thumb. -->
+ <dimen name="car_seekbar_thumb_size">68dp</dimen>
+
+ <!-- Sets the Theme android:disabledAlpha value, Used by SeekBar. -->
+ <dimen name="car_disabled_alpha">0.46</dimen>
</resources>
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 e6883d8..191b9ac 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
@@ -124,8 +124,27 @@
</style>
<style name="Widget.DeviceDefault.SeekBar" parent="android:Widget.Material.SeekBar">
- <item name="android:progressDrawable">@*android:drawable/car_seekbar_track</item>
- <item name="android:thumb">@*android:drawable/car_seekbar_thumb</item>
+ <item name="android:thumb">@drawable/car_seekbar_thumb_selectable</item>
+ <item name="android:progressDrawable">@drawable/car_seekbar_track</item>
+ <item name="android:splitTrack">false</item>
+ <item name="android:thumbOffset">@dimen/car_seekbar_thumb_offset</item>
+ <item name="android:paddingStart">@dimen/car_seekbar_horizontal_padding</item>
+ <item name="android:paddingEnd">@dimen/car_seekbar_horizontal_padding</item>
+ <item name="*android:useDisabledAlpha">true</item>
+ <item name="android:clipToOutline">false</item>
+ <item name="android:clipToPadding">false</item>
+ </style>
+
+ <style name="Widget.DeviceDefault.Light.SeekBar" parent="android:Widget.Material.Light.SeekBar">
+ <item name="android:thumb">@drawable/car_seekbar_thumb_selectable</item>
+ <item name="android:progressDrawable">@drawable/car_seekbar_track</item>
+ <item name="android:splitTrack">false</item>
+ <item name="android:thumbOffset">@dimen/car_seekbar_thumb_offset</item>
+ <item name="android:paddingStart">@dimen/car_seekbar_horizontal_padding</item>
+ <item name="android:paddingEnd">@dimen/car_seekbar_horizontal_padding</item>
+ <item name="*android:useDisabledAlpha">true</item>
+ <item name="android:clipToOutline">false</item>
+ <item name="android:clipToPadding">false</item>
</style>
<style name="Widget.DeviceDefault.ActionBar.Solid" parent="android:Widget.Material.ActionBar.Solid">
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 e97f01f..45c33d3 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
@@ -47,6 +47,11 @@
<item name="colorSwitchThumbNormal">@color/car_switch_thumb_color</item>
<item name="colorSwitchTrack">@color/car_switch_track_background_selector</item>
<item name="colorSwitchThumbDisabled">@color/car_switch_thumb_color_disabled_on_dark</item>
+ <item name="colorSeekBarTrackBackground">@color/car_seekbar_track_background</item>
+ <item name="colorSeekBarTrackProgress">@color/car_seekbar_track_progress</item>
+ <item name="colorSeekBarTrackProgressSecondary">@color/car_seekbar_track_progress_secondary</item>
+ <item name="colorSeekbarThumb">@color/car_seekbar_thumb_selector</item>
+ <item name="*android:disabledAlpha">@dimen/car_disabled_alpha</item>
</style>
<style name="Theme.DeviceDefault.Dialog" parent="android:Theme.Material.Dialog">
@@ -119,9 +124,14 @@
defined theme palette -->
<style name="Theme.DeviceDefault.Light" parent="android:Theme.DeviceDefault">
<item name="android:switchStyle">@style/Widget.DeviceDefault.Light.CompoundButton.Switch</item>
- <item name="colorSwitchThumbDisabled">@color/car_switch_thumb_color_disabled_on_dark</item>
<item name="colorSwitchThumbNormal">@color/car_switch_thumb_color</item>
<item name="colorSwitchThumbDisabled">@color/car_switch_thumb_color_disabled_on_light</item>
+ <item name="colorSeekBarTrackBackground">@color/car_seekbar_track_background</item>
+ <item name="colorSeekBarTrackProgress">@color/car_seekbar_track_progress</item>
+ <item name="colorSeekBarTrackProgressSecondary">@color/car_seekbar_track_progress_secondary</item>
+ <item name="*android:disabledAlpha">@dimen/car_disabled_alpha</item>
+ <!-- To simulate transparency over light (white) background, we don't need a selector. -->
+ <item name="colorSeekbarThumb">@color/car_seekbar_thumb</item>
</style>
<style name="Theme.DeviceDefault.Light.Dialog" parent="android:Theme.DeviceDefault.Dialog"/>
<style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="android:Theme.DeviceDefault.Dialog.Alert"/>
diff --git a/cpp/powerpolicy/server/src/CarPowerPolicyServer.cpp b/cpp/powerpolicy/server/src/CarPowerPolicyServer.cpp
index 10005e9..5fa9197 100644
--- a/cpp/powerpolicy/server/src/CarPowerPolicyServer.cpp
+++ b/cpp/powerpolicy/server/src/CarPowerPolicyServer.cpp
@@ -135,7 +135,7 @@
} else if (value.prop == static_cast<int32_t>(VehicleProperty::POWER_POLICY_REQ)) {
const auto& ret = mService->applyPowerPolicy(value.value.stringValue,
/*carServiceExpected=*/false,
- /*overridePreemptive=*/false);
+ /*force=*/false);
if (!ret.ok()) {
ALOGW("Failed to apply power policy(%s): %s", value.value.stringValue.c_str(),
ret.error().message().c_str());
@@ -179,8 +179,9 @@
return mService->notifyCarServiceReady(policyState);
}
-Status CarServiceNotificationHandler::notifyPowerPolicyChange(const std::string& policyId) {
- return mService->notifyPowerPolicyChange(policyId);
+Status CarServiceNotificationHandler::notifyPowerPolicyChange(const std::string& policyId,
+ bool force) {
+ return mService->notifyPowerPolicyChange(policyId, force);
}
Status CarServiceNotificationHandler::notifyPowerPolicyDefinition(
@@ -316,20 +317,19 @@
return Status::ok();
}
-Status CarPowerPolicyServer::notifyPowerPolicyChange(const std::string& policyId) {
+Status CarPowerPolicyServer::notifyPowerPolicyChange(const std::string& policyId, bool force) {
Status status = checkSystemPermission();
if (!status.isOk()) {
return status;
}
- const auto& ret =
- applyPowerPolicy(policyId, /*carServiceExpected=*/true, /*overridePreemptive=*/false);
+ const auto& ret = applyPowerPolicy(policyId, /*carServiceExpected=*/true, force);
if (!ret.ok()) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
StringPrintf("Failed to notify power policy change: %s",
ret.error().message().c_str())
.c_str());
}
- ALOGD("Policy(%s) is applied at CarService", policyId.c_str());
+ ALOGD("Policy change(%s) is notified by CarService", policyId.c_str());
return Status::ok();
}
@@ -476,7 +476,7 @@
Result<void> CarPowerPolicyServer::applyPowerPolicy(const std::string& policyId,
const bool carServiceInOperation,
- const bool overridePreemptive) {
+ const bool force) {
auto policyMeta = mPolicyManager.getPowerPolicy(policyId);
if (!policyMeta.ok()) {
return Error() << "Failed to apply power policy: " << policyMeta.error().message();
@@ -507,7 +507,7 @@
}
mIsPowerPolicyLocked = true;
} else {
- if (overridePreemptive) {
+ if (force) {
mPendingPowerPolicyId.clear();
mIsPowerPolicyLocked = false;
} else if (mIsPowerPolicyLocked) {
@@ -559,10 +559,10 @@
Result<void> ret;
if (isSilent) {
ret = applyPowerPolicy(kSystemPolicyIdNoUserInteraction,
- /*carServiceExpected=*/false, /*overridePreemptive=*/false);
+ /*carServiceExpected=*/false, /*force=*/false);
} else {
ret = applyPowerPolicy(pendingPowerPolicyId,
- /*carServiceExpected=*/false, /*overridePreemptive=*/true);
+ /*carServiceExpected=*/false, /*force=*/true);
}
if (!ret.ok()) {
ALOGW("Failed to apply power policy: %s", ret.error().message().c_str());
@@ -655,8 +655,7 @@
policyId = kSystemPolicyIdInitialOn;
}
}
- if (const auto& ret = applyPowerPolicy(policyId, /*carServiceExpected=*/false,
- /*overridePreemptive=*/false);
+ if (const auto& ret = applyPowerPolicy(policyId, /*carServiceExpected=*/false, /*force=*/false);
!ret.ok()) {
ALOGW("Cannot apply the initial power policy(%s): %s", policyId.c_str(),
ret.error().message().c_str());
@@ -670,7 +669,7 @@
if (value.value.stringValue.size() > 0) {
const auto& ret = applyPowerPolicy(value.value.stringValue,
/*carServiceExpected=*/false,
- /*overridePreemptive=*/false);
+ /*force=*/false);
if (!ret.ok()) {
ALOGW("Failed to apply power policy(%s): %s",
value.value.stringValue.c_str(),
diff --git a/cpp/powerpolicy/server/src/CarPowerPolicyServer.h b/cpp/powerpolicy/server/src/CarPowerPolicyServer.h
index b2007ff..33081ca 100644
--- a/cpp/powerpolicy/server/src/CarPowerPolicyServer.h
+++ b/cpp/powerpolicy/server/src/CarPowerPolicyServer.h
@@ -122,7 +122,8 @@
android::binder::Status notifyCarServiceReady(
android::frameworks::automotive::powerpolicy::internal::PolicyState* policyState)
override;
- android::binder::Status notifyPowerPolicyChange(const std::string& policyId) override;
+ android::binder::Status notifyPowerPolicyChange(const std::string& policyId,
+ bool force) override;
android::binder::Status notifyPowerPolicyDefinition(
const std::string& policyId, const std::vector<std::string>& enabledComponents,
const std::vector<std::string>& disabledComponents) override;
@@ -169,7 +170,7 @@
// Implements ICarPowerPolicySystemNotification.aidl.
android::binder::Status notifyCarServiceReady(
android::frameworks::automotive::powerpolicy::internal::PolicyState* policyState);
- android::binder::Status notifyPowerPolicyChange(const std::string& policyId);
+ android::binder::Status notifyPowerPolicyChange(const std::string& policyId, bool force);
android::binder::Status notifyPowerPolicyDefinition(
const std::string& policyId, const std::vector<std::string>& enabledComponents,
const std::vector<std::string>& disabledComponents);
@@ -178,11 +179,12 @@
* Applies the given power policy.
*
* @param carServiceInOperation expected Car Service running state.
- * @param overridePreemptive whether to override a preemptive power policy.
+ * @param force whether to apply the policy even when the current policy is a system
+ * power policy.
*/
android::base::Result<void> applyPowerPolicy(const std::string& policyId,
const bool carServiceInOperation,
- const bool overridePreemptive);
+ const bool force);
/**
* Sets the power policy group which contains rules to map a power state to a default power
* policy to apply.
diff --git a/cpp/watchdog/server/Android.bp b/cpp/watchdog/server/Android.bp
index c8d07b4..5aeebb2 100644
--- a/cpp/watchdog/server/Android.bp
+++ b/cpp/watchdog/server/Android.bp
@@ -30,16 +30,15 @@
"system/libbase/include",
],
shared_libs: [
- "android.automotive.watchdog-V3-cpp",
- "android.automotive.watchdog.internal-cpp",
- "android.automotive.watchdog.internal-cpp",
- "android.automotive.watchdog-V3-cpp",
- "android.hardware.automotive.vehicle@2.0",
"libbase",
"libbinder",
"liblog",
"libutils",
],
+ static_libs: [
+ "android.automotive.watchdog.internal-cpp",
+ "android.automotive.watchdog-V3-cpp",
+ ],
header_libs: [
"libgtest_prod_headers",
],
@@ -54,6 +53,7 @@
"carwatchdogd_defaults",
],
shared_libs: [
+ "android.hardware.automotive.vehicle@2.0",
"libcutils",
],
export_include_dirs: [
@@ -67,7 +67,6 @@
"libcutils",
"libprocessgroup",
"libtinyxml2",
- "libwatchdog_package_info_resolver",
],
}
@@ -90,8 +89,12 @@
"src/UidProcStatsCollector.cpp",
"src/UidStatsCollector.cpp",
],
+ shared_libs: [
+ "android.hardware.automotive.vehicle@2.0",
+ ],
whole_static_libs: [
"libwatchdog_properties",
+ "libwatchdog_package_info_resolver",
],
export_include_dirs: [
"src",
@@ -140,7 +143,10 @@
"libwatchdog_binder_mediator",
"libwatchdog_perf_service",
"libwatchdog_process_service",
+ ],
+ whole_static_libs: [
"libwatchdog_package_info_resolver",
+ "android.hardware.automotive.vehicle@2.0",
],
data: [":watchdog_test_xml_files"],
}
@@ -161,6 +167,9 @@
"carwatchdogd_defaults",
"libwatchdog_process_service_defaults"
],
+ shared_libs: [
+ "android.hardware.automotive.vehicle@2.0",
+ ],
}
cc_library {
@@ -176,6 +185,9 @@
"src/WatchdogServiceHelper.cpp",
],
shared_libs: [
+ "android.hardware.automotive.vehicle@2.0",
+ ],
+ static_libs: [
"libwatchdog_perf_service",
"libwatchdog_process_service",
],
@@ -197,10 +209,15 @@
],
init_rc: ["carwatchdogd.rc"],
shared_libs: [
- "libwatchdog_binder_mediator",
- "libwatchdog_perf_service",
- "libwatchdog_process_service",
- "libwatchdog_package_info_resolver",
+ "android.hardware.automotive.vehicle@2.0",
+ ],
+ static_libs: [
+ "libwatchdog_binder_mediator",
+ "libwatchdog_perf_service",
+ "libwatchdog_process_service",
+ ],
+ whole_static_libs: [
+ "libwatchdog_package_info_resolver",
],
vintf_fragments: ["carwatchdogd.xml"],
required: [
diff --git a/packages/CarDeveloperOptions/res/values/strings.xml b/packages/CarDeveloperOptions/res/values/strings.xml
index 5d24671..f92e9a7 100644
--- a/packages/CarDeveloperOptions/res/values/strings.xml
+++ b/packages/CarDeveloperOptions/res/values/strings.xml
@@ -17,4 +17,5 @@
<resources>
<string name="car_pref_category_title">Car</string>
<string name="car_ui_plugin_enabled_pref_title">Enable Car UI library plugin</string>
+ <string name="car_ui_plugin_not_found_text">Car UI plugin not found</string>
</resources>
\ No newline at end of file
diff --git a/packages/CarDeveloperOptions/res/values/themes.xml b/packages/CarDeveloperOptions/res/values/themes.xml
index 691afd3..73bf8d8 100644
--- a/packages/CarDeveloperOptions/res/values/themes.xml
+++ b/packages/CarDeveloperOptions/res/values/themes.xml
@@ -47,6 +47,16 @@
<style name="Theme.CarDeveloperOptions" parent="@style/Theme.CarUi.WithToolbar">
<item name="alertDialogTheme">@style/Theme.AlertDialog</item>
<item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
+ <item name="preferenceTheme">@style/CarDeveloperOptionsPreferenceTheme</item>
+ </style>
+
+ <style name="CarDeveloperOptionsPreferenceTheme" parent="@style/CarUiPreferenceTheme">
+ <item name="preferenceFragmentCompatStyle">@style/CarDeveloperOptionsPreferenceFragment</item>
+ <item name="preferenceFragmentStyle">@style/CarDeveloperOptionsPreferenceFragment</item>
+ </style>
+
+ <style name="CarDeveloperOptionsPreferenceFragment" parent="@style/PreferenceFragment.CarUi">
+ <item name="android:layout">@layout/preference_list_fragment</item>
</style>
</resources>
\ No newline at end of file
diff --git a/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentCarUiLibController.java b/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentCarUiLibController.java
index 619c565..ef2c943 100644
--- a/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentCarUiLibController.java
+++ b/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentCarUiLibController.java
@@ -16,8 +16,15 @@
package com.android.car.developeroptions;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+
+import android.content.ComponentName;
import android.content.Context;
-import android.os.SystemProperties;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
@@ -27,9 +34,6 @@
*/
public class CarDevelopmentCarUiLibController extends CarDevelopmentPreferenceController {
private static final String CAR_UI_PLUGIN_ENABLED_KEY = "car_ui_plugin_enabled";
- static final String CAR_UI_PLUGIN_ENABLED_PROPERTY =
- "persist.sys.automotive.car.ui.plugin.enabled";
-
public CarDevelopmentCarUiLibController(Context context) {
super(context);
@@ -47,19 +51,61 @@
@Override
String getPreferenceSummary() {
+ if (getCarUiPluginProviderInfo() == null) {
+ return mContext.getString(R.string.car_ui_plugin_not_found_text);
+ }
+
return null;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- SystemProperties.set(CAR_UI_PLUGIN_ENABLED_PROPERTY, String.valueOf(newValue));
+ Boolean isPluginEnabled = (Boolean) newValue;
+ ProviderInfo providerInfo = getCarUiPluginProviderInfo();
+ if (providerInfo == null) {
+ throw new IllegalStateException("Car UI plugin not found");
+ }
+
+ ComponentName componentName = new ComponentName(providerInfo.packageName,
+ providerInfo.name);
+ int state = isPluginEnabled ? COMPONENT_ENABLED_STATE_ENABLED
+ : COMPONENT_ENABLED_STATE_DISABLED;
+ mContext.getPackageManager().setComponentEnabledSetting(componentName,
+ state, 0 /* no optional flags */);
return true;
}
@Override
public void updateState(Preference preference) {
- final boolean pluginEnabled = SystemProperties.getBoolean(
- CAR_UI_PLUGIN_ENABLED_PROPERTY, false /* default */);
- ((SwitchPreference) mPreference).setChecked(pluginEnabled);
+ if (getCarUiPluginProviderInfo() == null) {
+ ((SwitchPreference) mPreference).setChecked(false);
+ mPreference.setEnabled(false);
+ return;
+ }
+
+ ((SwitchPreference) mPreference).setChecked(isCarUiPluginEnabled());
+ }
+
+ private ProviderInfo getCarUiPluginProviderInfo() {
+ String authority = mContext.getString(
+ R.string.car_ui_plugin_package_provider_authority_name);
+ return mContext.getPackageManager().resolveContentProvider(authority,
+ MATCH_ALL | MATCH_DISABLED_COMPONENTS);
+ }
+
+ private boolean isCarUiPluginEnabled() {
+ ProviderInfo providerInfo = getCarUiPluginProviderInfo();
+ if (providerInfo == null) {
+ return false;
+ }
+
+ ComponentName componentName = new ComponentName(providerInfo.packageName,
+ providerInfo.name);
+ int state = mContext.getPackageManager().getComponentEnabledSetting(componentName);
+ if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ return providerInfo.enabled;
+ }
+
+ return state == COMPONENT_ENABLED_STATE_ENABLED;
}
}
diff --git a/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentSettingsDashboardFragment.java b/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentSettingsDashboardFragment.java
index ef007b4..d74b8ea 100644
--- a/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentSettingsDashboardFragment.java
+++ b/packages/CarDeveloperOptions/src/com/android/car/developeroptions/CarDevelopmentSettingsDashboardFragment.java
@@ -23,16 +23,12 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
import androidx.annotation.XmlRes;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
-import androidx.recyclerview.widget.RecyclerView;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
import com.android.car.ui.toolbar.MenuItem;
import com.android.car.ui.toolbar.Toolbar;
import com.android.car.ui.toolbar.ToolbarController;
@@ -127,20 +123,6 @@
}
}
- @Override
- public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
- Bundle savedInstanceState) {
- Object carUiRecyclerView = parent.findViewById(R.id.recycler_view);
- RecyclerView recyclerView = (carUiRecyclerView instanceof CarUiRecyclerView)
- ? ((CarUiRecyclerView) carUiRecyclerView).getRecyclerView()
- : (RecyclerView) carUiRecyclerView;
- if (recyclerView != null) {
- return recyclerView;
- } else {
- return super.onCreateRecyclerView(inflater, parent, savedInstanceState);
- }
- }
-
protected ToolbarController getToolbar() {
return requireToolbar(requireActivity());
}
diff --git a/packages/ScriptExecutor/Android.bp b/packages/ScriptExecutor/Android.bp
index 033728b..42cb082 100644
--- a/packages/ScriptExecutor/Android.bp
+++ b/packages/ScriptExecutor/Android.bp
@@ -41,7 +41,6 @@
],
srcs: [
- ":iscriptexecutorconstants_aidl",
"src/BundleWrapper.cpp",
"src/JniUtils.cpp",
"src/LuaEngine.cpp",
@@ -49,9 +48,7 @@
],
shared_libs: [
- "libbinder",
"libnativehelper",
- "libutils",
],
// Allow dependents to use the header files.
@@ -80,7 +77,6 @@
srcs: [
":iscriptexecutor_aidl",
- ":iscriptexecutorconstants_aidl",
"src/**/*.java"
],
@@ -113,7 +109,6 @@
srcs: [
":iscriptexecutor_aidl",
- ":iscriptexecutorconstants_aidl",
"src/**/*.java",
],
diff --git a/packages/ScriptExecutor/src/LuaEngine.cpp b/packages/ScriptExecutor/src/LuaEngine.cpp
index 023333d..fa5e0f6 100644
--- a/packages/ScriptExecutor/src/LuaEngine.cpp
+++ b/packages/ScriptExecutor/src/LuaEngine.cpp
@@ -19,7 +19,6 @@
#include "BundleWrapper.h"
#include <android-base/logging.h>
-#include <com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorConstants.h>
#include <sstream>
#include <string>
@@ -37,8 +36,6 @@
namespace car {
namespace scriptexecutor {
-using ::com::android::car::telemetry::scriptexecutorinterface::IScriptExecutorConstants;
-
namespace {
enum LuaNumReturnedResults {
@@ -95,8 +92,7 @@
<< MAX_ARRAY_SIZE
<< " elements. This key-value cannot be unpacked successfully. This error "
"is unrecoverable.";
- listener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
- out.str().c_str(), "");
+ listener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR, out.str().c_str(), "");
return false;
}
if (kTableLength <= 0) {
@@ -105,8 +101,7 @@
<< " appears to be a nested table that does not represent an array of data. "
"Such nested tables are not supported yet. This script error is "
"unrecoverable.";
- listener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
- out.str().c_str(), "");
+ listener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR, out.str().c_str(), "");
return false;
}
@@ -133,8 +128,7 @@
<< ", but the element at index=" << i + 1 << " has type=" << currentType
<< ". Integer type codes are defined in lua.h file. This error is "
"unrecoverable.";
- listener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
- out.str().c_str(), "");
+ listener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR, out.str().c_str(), "");
lua_pop(lua, 1);
return false;
}
@@ -255,7 +249,7 @@
int LuaEngine::onSuccess(lua_State* lua) {
// Any script we run can call on_success only with a single argument of Lua table type.
if (lua_gettop(lua) != 1 || !lua_istable(lua, /* index =*/-1)) {
- sListener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
+ sListener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR,
"on_success can push only a single parameter from Lua - a Lua table",
"");
return ZERO_RETURNED_RESULTS;
@@ -276,7 +270,7 @@
int LuaEngine::onScriptFinished(lua_State* lua) {
// Any script we run can call on_success only with a single argument of Lua table type.
if (lua_gettop(lua) != 1 || !lua_istable(lua, /* index =*/-1)) {
- sListener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
+ sListener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR,
"on_script_finished can push only a single parameter from Lua - a Lua "
"table",
"");
@@ -298,12 +292,12 @@
int LuaEngine::onError(lua_State* lua) {
// Any script we run can call on_error only with a single argument of Lua string type.
if (lua_gettop(lua) != 1 || !lua_isstring(lua, /* index = */ -1)) {
- sListener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
+ sListener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR,
"on_error can push only a single string parameter from Lua", "");
return ZERO_RETURNED_RESULTS;
}
- sListener->onError(IScriptExecutorConstants::ERROR_TYPE_LUA_SCRIPT_ERROR,
- lua_tostring(lua, /* index = */ -1), /* stackTrace =*/"");
+ sListener->onError(ERROR_TYPE_LUA_SCRIPT_ERROR, lua_tostring(lua, /* index = */ -1),
+ /* stackTrace =*/"");
return ZERO_RETURNED_RESULTS;
}
diff --git a/packages/ScriptExecutor/src/ScriptExecutorListener.cpp b/packages/ScriptExecutor/src/ScriptExecutorListener.cpp
index 739c71d..fd6677d 100644
--- a/packages/ScriptExecutor/src/ScriptExecutorListener.cpp
+++ b/packages/ScriptExecutor/src/ScriptExecutorListener.cpp
@@ -30,8 +30,8 @@
}
}
-ScriptExecutorListener::ScriptExecutorListener(JNIEnv* env, jobject script_executor_listener) {
- mScriptExecutorListener = env->NewGlobalRef(script_executor_listener);
+ScriptExecutorListener::ScriptExecutorListener(JNIEnv* env, jobject scriptExecutorListener) {
+ mScriptExecutorListener = env->NewGlobalRef(scriptExecutorListener);
env->GetJavaVM(&mJavaVM);
}
@@ -51,14 +51,14 @@
env->CallVoidMethod(mScriptExecutorListener, onScriptFinished, bundle);
}
-void ScriptExecutorListener::onError(const int errorType, const char* message,
+void ScriptExecutorListener::onError(const ErrorType errorType, const char* message,
const char* stackTrace) {
JNIEnv* env = getCurrentJNIEnv();
jclass listenerClass = env->GetObjectClass(mScriptExecutorListener);
jmethodID onErrorMethod =
env->GetMethodID(listenerClass, "onError", "(ILjava/lang/String;Ljava/lang/String;)V");
- env->CallVoidMethod(mScriptExecutorListener, onErrorMethod, errorType,
+ env->CallVoidMethod(mScriptExecutorListener, onErrorMethod, static_cast<int>(errorType),
env->NewStringUTF(message), env->NewStringUTF(stackTrace));
}
diff --git a/packages/ScriptExecutor/src/ScriptExecutorListener.h b/packages/ScriptExecutor/src/ScriptExecutorListener.h
index 392bc77..44e0e2b 100644
--- a/packages/ScriptExecutor/src/ScriptExecutorListener.h
+++ b/packages/ScriptExecutor/src/ScriptExecutorListener.h
@@ -26,10 +26,37 @@
namespace car {
namespace scriptexecutor {
+// Changes in this enum must also be reflected in:
+// p/s/C/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorListener.aidl
+// p/s/C/service/src/com/android/car/telemetry/proto/telemetry.proto
+enum ErrorType {
+ /**
+ * Default error type.
+ */
+ ERROR_TYPE_UNSPECIFIED = 0,
+
+ /**
+ * Used when an error occurs in the ScriptExecutor code.
+ */
+ ERROR_TYPE_SCRIPT_EXECUTOR_ERROR = 1,
+
+ /**
+ * Used when an error occurs while executing the Lua script (such as
+ * errors returned by lua_pcall)
+ */
+ ERROR_TYPE_LUA_RUNTIME_ERROR = 2,
+
+ /**
+ * Used to log errors by a script itself, for instance, when a script received
+ * inputs outside of expected range.
+ */
+ ERROR_TYPE_LUA_SCRIPT_ERROR = 3,
+};
+
// Wrapper class for IScriptExecutorListener.aidl.
class ScriptExecutorListener {
public:
- ScriptExecutorListener(JNIEnv* jni, jobject script_executor_listener);
+ ScriptExecutorListener(JNIEnv* jni, jobject scriptExecutorListener);
virtual ~ScriptExecutorListener();
@@ -37,7 +64,7 @@
void onSuccess(jobject bundle);
- void onError(const int errorType, const char* message, const char* stackTrace);
+ void onError(const ErrorType errorType, const char* message, const char* stackTrace);
JNIEnv* getCurrentJNIEnv();
diff --git a/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java b/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
index 06e318b..3877693 100644
--- a/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
+++ b/packages/ScriptExecutor/src/com/android/car/scriptexecutor/ScriptExecutor.java
@@ -28,7 +28,6 @@
import android.util.Slog;
import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutor;
-import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutorConstants;
import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutorListener;
import java.io.IOException;
@@ -72,7 +71,7 @@
publishedData = PersistableBundle.readFromStream(input);
} catch (IOException e) {
try {
- listener.onError(IScriptExecutorConstants.ERROR_TYPE_SCRIPT_EXECUTOR_ERROR,
+ listener.onError(IScriptExecutorListener.ERROR_TYPE_SCRIPT_EXECUTOR_ERROR,
e.getMessage(), "");
} catch (RemoteException remoteException) {
if (Log.isLoggable(TAG, Log.ERROR)) {
diff --git a/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java b/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
index 52b5cc7..a167b0c 100644
--- a/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
+++ b/packages/ScriptExecutor/tests/unit/src/com/android/car/scriptexecutor/ScriptExecutorTest.java
@@ -34,7 +34,6 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutor;
-import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutorConstants;
import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutorListener;
import org.junit.Before;
@@ -195,7 +194,7 @@
// Verify that expected error is received.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).contains(
"nested tables are not supported");
}
@@ -371,7 +370,7 @@
// Verify that expected error is received.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"Returned table huge_array exceeds maximum allowed size of 1000 "
+ "elements. This key-value cannot be unpacked successfully. This error "
@@ -399,7 +398,7 @@
// Verify that expected error is received.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).contains(
"Returned Lua arrays must have elements of the same type.");
}
@@ -473,7 +472,7 @@
runScriptAndWaitForError(script, "calls_on_error");
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo("one is not equal to two");
}
@@ -490,7 +489,7 @@
runScriptAndWaitForError(script, "too_many_params_in_on_error");
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"on_error can push only a single string parameter from Lua");
}
@@ -508,7 +507,7 @@
runScriptAndWaitForError(script, "only_string");
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"on_error can push only a single string parameter from Lua");
}
@@ -597,7 +596,7 @@
// We expect to get an error here because we expect only 1 input parameter in
// on_script_finished.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"on_script_finished can push only a single parameter from Lua - a Lua table");
}
@@ -617,7 +616,7 @@
// We expect to get an error here because we expect only 1 input parameter in on_success.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"on_success can push only a single parameter from Lua - a Lua table");
}
@@ -637,7 +636,7 @@
// We expect to get an error here because the type of the input parameter for on_success
// must be a Lua table.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"on_success can push only a single parameter from Lua - a Lua table");
}
@@ -657,7 +656,7 @@
// We expect to get an error here because the type of the input parameter for
// on_script_finished must be a Lua table.
assertThat(mFakeScriptExecutorListener.mErrorType).isEqualTo(
- IScriptExecutorConstants.ERROR_TYPE_LUA_SCRIPT_ERROR);
+ IScriptExecutorListener.ERROR_TYPE_LUA_SCRIPT_ERROR);
assertThat(mFakeScriptExecutorListener.mMessage).isEqualTo(
"on_success can push only a single parameter from Lua - a Lua table");
}
diff --git a/service/Android.bp b/service/Android.bp
index 7f4a329..fe07310 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -196,11 +196,3 @@
],
path: "src",
}
-
-filegroup {
- name: "iscriptexecutorconstants_aidl",
- srcs: [
- "src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorConstants.aidl",
- ],
- path: "src",
-}
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index 9cf986d..ffe96c4 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -902,7 +902,6 @@
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.DEVICE_POWER"/>
- <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING"/>
diff --git a/service/res/values-af/strings.xml b/service/res/values-af/strings.xml
index 1c33916..ad5dfd6 100644
--- a/service/res/values-af/strings.xml
+++ b/service/res/values-af/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Beheer motorkragbeleid."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"lewer template"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Lewer template."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"My Toestel"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gas"</string>
<string name="importance_default" msgid="8587741629268312938">"Verstekbelang"</string>
diff --git a/service/res/values-am/strings.xml b/service/res/values-am/strings.xml
index f9096a9..9e0f772 100644
--- a/service/res/values-am/strings.xml
+++ b/service/res/values-am/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"የመኪና ኃይል መመሪያን ተቆጣጠር።"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"የቅንብር ደንቦችን ምስል ሥራ።"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"የቅንብር ደንቦችን ምስል ሥራ።"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"የእኔ መሣሪያ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"እንግዳ"</string>
<string name="importance_default" msgid="8587741629268312938">"ነባሪ አስፈላጊነት"</string>
diff --git a/service/res/values-ar/strings.xml b/service/res/values-ar/strings.xml
index aa89dec..9510aee 100644
--- a/service/res/values-ar/strings.xml
+++ b/service/res/values-ar/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"التحكُّم في سياسة تشغيل ميزات السيارة"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"عرض النماذج"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"عرض النماذج"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"جهازي"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ضيف"</string>
<string name="importance_default" msgid="8587741629268312938">"مدى الأهمية التلقائي"</string>
diff --git a/service/res/values-as/strings.xml b/service/res/values-as/strings.xml
index 1dcaa51..e4c62ea 100644
--- a/service/res/values-as/strings.xml
+++ b/service/res/values-as/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"গাড়ীৰ পাৱাৰ পলিচী নিয়ন্ত্ৰণ কৰে।"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"টেমপ্লে’ট প্ৰদান কৰক"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"টেমপ্লে’ট প্ৰদান কৰক।"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"মোৰ ডিভাইচ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"অতিথি"</string>
<string name="importance_default" msgid="8587741629268312938">"ডিফ’ল্ট গুৰুত্ব"</string>
diff --git a/service/res/values-az/strings.xml b/service/res/values-az/strings.xml
index d15a8a0..c6064e7 100644
--- a/service/res/values-az/strings.xml
+++ b/service/res/values-az/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Avtomobilin enerji siyasətini idarə edə bilir."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"şablonları vizualizasiya edin"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Şablonları vizualizasiya edin."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Cihazım"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Qonaq"</string>
<string name="importance_default" msgid="8587741629268312938">"Defolt önəm"</string>
diff --git a/service/res/values-b+sr+Latn/strings.xml b/service/res/values-b+sr+Latn/strings.xml
index 29fa321..20e1f5c 100644
--- a/service/res/values-b+sr+Latn/strings.xml
+++ b/service/res/values-b+sr+Latn/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrola smernica za napajanje automobila."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"prikazivanje šablona"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Prikazivanje šablona."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moj uređaj"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gost"</string>
<string name="importance_default" msgid="8587741629268312938">"Podrazumevana važnost"</string>
diff --git a/service/res/values-be/strings.xml b/service/res/values-be/strings.xml
index 73aa898..79acbee 100644
--- a/service/res/values-be/strings.xml
+++ b/service/res/values-be/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Кіраваць палітыкай сілкавання аўтамабіля."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"візуалізацыя шаблонаў"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Візуалізацыя шаблонаў."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Мая прылада"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Госць"</string>
<string name="importance_default" msgid="8587741629268312938">"Стандартная важнасць"</string>
diff --git a/service/res/values-bg/strings.xml b/service/res/values-bg/strings.xml
index 7db7094..826b2e6 100644
--- a/service/res/values-bg/strings.xml
+++ b/service/res/values-bg/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Управление на правилата за захранването на автомобила."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"рендериране на шаблони"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Рендериране на шаблони."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Моето устройство"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Гост"</string>
<string name="importance_default" msgid="8587741629268312938">"Важност по подразбиране"</string>
diff --git a/service/res/values-bn/strings.xml b/service/res/values-bn/strings.xml
index 32f7b2a..4d9dfc5 100644
--- a/service/res/values-bn/strings.xml
+++ b/service/res/values-bn/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"গাড়ির পাওয়ার নীতি নিয়ন্ত্রণ করুন।"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"টেম্পলেট রেন্ডার করুন"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"টেম্পলেট রেন্ডার করুন।"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"আমার ডিভাইস"</string>
<string name="default_guest_name" msgid="2912812799433131476">"অতিথি"</string>
<string name="importance_default" msgid="8587741629268312938">"ডিফল্ট গুরুত্ব"</string>
diff --git a/service/res/values-bs/strings.xml b/service/res/values-bs/strings.xml
index 1687754..bcd8028 100644
--- a/service/res/values-bs/strings.xml
+++ b/service/res/values-bs/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Upravljajte pravilima uključivanja/isključivanja komponenti automobila."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"iscrtavanje šablona"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Iscrtavanje šablona."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moj uređaj"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gost"</string>
<string name="importance_default" msgid="8587741629268312938">"Zadana važnost"</string>
diff --git a/service/res/values-ca/strings.xml b/service/res/values-ca/strings.xml
index e033f36..10564d7 100644
--- a/service/res/values-ca/strings.xml
+++ b/service/res/values-ca/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controla la política d\'energia del cotxe."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderitzar plantilles"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderitzar plantilles."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"El meu dispositiu"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Convidat"</string>
<string name="importance_default" msgid="8587741629268312938">"Importància predeterminada"</string>
diff --git a/service/res/values-cs/strings.xml b/service/res/values-cs/strings.xml
index 68f83f4..ea872c3 100644
--- a/service/res/values-cs/strings.xml
+++ b/service/res/values-cs/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Ovládání zásad pro napájení komponentů auta."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"vykreslování šablon"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Vykreslování šablon."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moje zařízení"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Host"</string>
<string name="importance_default" msgid="8587741629268312938">"Výchozí důležitost"</string>
diff --git a/service/res/values-da/strings.xml b/service/res/values-da/strings.xml
index 9022999..3e87aa8 100644
--- a/service/res/values-da/strings.xml
+++ b/service/res/values-da/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Styr bilens politik for aktivering af komponenter."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"gengive skabeloner"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Gengive skabeloner."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Min enhed"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gæst"</string>
<string name="importance_default" msgid="8587741629268312938">"Standardvigtighed"</string>
diff --git a/service/res/values-de/strings.xml b/service/res/values-de/strings.xml
index c9ad990..9746544 100644
--- a/service/res/values-de/strings.xml
+++ b/service/res/values-de/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Richtlinie zur Stromversorgung von Komponenten im Auto steuern."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"Vorlagen werden gerendert"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Vorlagen werden gerendert."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mein Gerät"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gast"</string>
<string name="importance_default" msgid="8587741629268312938">"Wichtigkeit: Standard"</string>
diff --git a/service/res/values-el/strings.xml b/service/res/values-el/strings.xml
index cf46947..e7c562a 100644
--- a/service/res/values-el/strings.xml
+++ b/service/res/values-el/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Έλεγχος πολιτικής ισχύος αυτοκινήτου."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"απόδοση προτύπων"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Να αποδίδει πρότυπα."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Η συσκευή μου"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Επισκέπτης"</string>
<string name="importance_default" msgid="8587741629268312938">"Προεπιλεγμένη βαρύτητα"</string>
diff --git a/service/res/values-en-rAU/strings.xml b/service/res/values-en-rAU/strings.xml
index 3965f97..79fee75 100644
--- a/service/res/values-en-rAU/strings.xml
+++ b/service/res/values-en-rAU/strings.xml
@@ -169,6 +169,8 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Control car power policy."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"render templates"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Render templates."</string>
+ <string name="car_permission_label_control_car_app_launch" msgid="214632389637409226">"control launching applications"</string>
+ <string name="car_permission_desc_control_car_app_launch" msgid="4245527461733374198">"Control launching applications."</string>
<string name="trust_device_default_name" msgid="4213625926070261253">"My Device"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Guest"</string>
<string name="importance_default" msgid="8587741629268312938">"Default importance"</string>
diff --git a/service/res/values-en-rCA/strings.xml b/service/res/values-en-rCA/strings.xml
index 3965f97..79fee75 100644
--- a/service/res/values-en-rCA/strings.xml
+++ b/service/res/values-en-rCA/strings.xml
@@ -169,6 +169,8 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Control car power policy."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"render templates"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Render templates."</string>
+ <string name="car_permission_label_control_car_app_launch" msgid="214632389637409226">"control launching applications"</string>
+ <string name="car_permission_desc_control_car_app_launch" msgid="4245527461733374198">"Control launching applications."</string>
<string name="trust_device_default_name" msgid="4213625926070261253">"My Device"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Guest"</string>
<string name="importance_default" msgid="8587741629268312938">"Default importance"</string>
diff --git a/service/res/values-en-rGB/strings.xml b/service/res/values-en-rGB/strings.xml
index 3965f97..79fee75 100644
--- a/service/res/values-en-rGB/strings.xml
+++ b/service/res/values-en-rGB/strings.xml
@@ -169,6 +169,8 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Control car power policy."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"render templates"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Render templates."</string>
+ <string name="car_permission_label_control_car_app_launch" msgid="214632389637409226">"control launching applications"</string>
+ <string name="car_permission_desc_control_car_app_launch" msgid="4245527461733374198">"Control launching applications."</string>
<string name="trust_device_default_name" msgid="4213625926070261253">"My Device"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Guest"</string>
<string name="importance_default" msgid="8587741629268312938">"Default importance"</string>
diff --git a/service/res/values-en-rIN/strings.xml b/service/res/values-en-rIN/strings.xml
index 3965f97..79fee75 100644
--- a/service/res/values-en-rIN/strings.xml
+++ b/service/res/values-en-rIN/strings.xml
@@ -169,6 +169,8 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Control car power policy."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"render templates"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Render templates."</string>
+ <string name="car_permission_label_control_car_app_launch" msgid="214632389637409226">"control launching applications"</string>
+ <string name="car_permission_desc_control_car_app_launch" msgid="4245527461733374198">"Control launching applications."</string>
<string name="trust_device_default_name" msgid="4213625926070261253">"My Device"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Guest"</string>
<string name="importance_default" msgid="8587741629268312938">"Default importance"</string>
diff --git a/service/res/values-en-rXC/strings.xml b/service/res/values-en-rXC/strings.xml
index 8804ae0..3d8443e 100644
--- a/service/res/values-en-rXC/strings.xml
+++ b/service/res/values-en-rXC/strings.xml
@@ -169,6 +169,8 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Control car power policy."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"render templates"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Render templates."</string>
+ <string name="car_permission_label_control_car_app_launch" msgid="214632389637409226">"control launching applications"</string>
+ <string name="car_permission_desc_control_car_app_launch" msgid="4245527461733374198">"Control launching applications."</string>
<string name="trust_device_default_name" msgid="4213625926070261253">"My Device"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Guest"</string>
<string name="importance_default" msgid="8587741629268312938">"Default importance"</string>
diff --git a/service/res/values-es-rUS/strings.xml b/service/res/values-es-rUS/strings.xml
index d7ae7cd..364b2d8 100644
--- a/service/res/values-es-rUS/strings.xml
+++ b/service/res/values-es-rUS/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controla la política de activación de componentes del vehículo."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderizar plantillas"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderizar plantillas"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mi dispositivo"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Invitado"</string>
<string name="importance_default" msgid="8587741629268312938">"Importancia de config. predeterminada"</string>
diff --git a/service/res/values-es/strings.xml b/service/res/values-es/strings.xml
index 77e1aea..49ab196 100644
--- a/service/res/values-es/strings.xml
+++ b/service/res/values-es/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controlar política de energía del coche."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderizar plantillas"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderizar plantillas."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mi dispositivo"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Invitado"</string>
<string name="importance_default" msgid="8587741629268312938">"Importancia predeterminada"</string>
diff --git a/service/res/values-et/strings.xml b/service/res/values-et/strings.xml
index b9d311a..b5b26ad 100644
--- a/service/res/values-et/strings.xml
+++ b/service/res/values-et/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Auto toitereeglite haldamine."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"mallide renderdamine"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Mallide renderdamine."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Minu seade"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Külaline"</string>
<string name="importance_default" msgid="8587741629268312938">"Vaiketähtsus"</string>
diff --git a/service/res/values-eu/strings.xml b/service/res/values-eu/strings.xml
index fe841c0..c6f8b1e 100644
--- a/service/res/values-eu/strings.xml
+++ b/service/res/values-eu/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrolatu autoaren osagaiak aktibatzeko gidalerroak."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"errendatu txantiloiak"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Errendatu txantiloiak."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Nire gailua"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gonbidatua"</string>
<string name="importance_default" msgid="8587741629268312938">"Garrantzi lehenetsia"</string>
diff --git a/service/res/values-fa/strings.xml b/service/res/values-fa/strings.xml
index 749dc19..886ca2a 100644
--- a/service/res/values-fa/strings.xml
+++ b/service/res/values-fa/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"کنترل خطمشی روشن/خاموش شدن مؤلفههای خودرو."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"پرداز زدن الگوها"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"پرداز زدن الگوها."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"دستگاه من"</string>
<string name="default_guest_name" msgid="2912812799433131476">"مهمان"</string>
<string name="importance_default" msgid="8587741629268312938">"اهمیت پیشفرض"</string>
diff --git a/service/res/values-fi/strings.xml b/service/res/values-fi/strings.xml
index 7f865fc..8790d6a 100644
--- a/service/res/values-fi/strings.xml
+++ b/service/res/values-fi/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Ohjaa auton virtakäytäntöä"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderöidä malleja"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderöi mallit."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Oma laite"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Vieras"</string>
<string name="importance_default" msgid="8587741629268312938">"Oletustärkeys"</string>
diff --git a/service/res/values-fr-rCA/strings.xml b/service/res/values-fr-rCA/strings.xml
index 349edc9..b07851a 100644
--- a/service/res/values-fr-rCA/strings.xml
+++ b/service/res/values-fr-rCA/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Politique sur la gestion de l\'alimentation dans la voiture"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"render effectuer un rendu des modèles"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Effectuer un rendu des modèles."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mon appareil"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Invité"</string>
<string name="importance_default" msgid="8587741629268312938">"Importance par défaut"</string>
diff --git a/service/res/values-fr/strings.xml b/service/res/values-fr/strings.xml
index 4dbf2c3..3ec11ec 100644
--- a/service/res/values-fr/strings.xml
+++ b/service/res/values-fr/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Contrôlez la règle d\'activation pour la voiture."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"afficher les modèles"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Afficher les modèles."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mon appareil"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Invité"</string>
<string name="importance_default" msgid="8587741629268312938">"Importance par défaut"</string>
diff --git a/service/res/values-gl/strings.xml b/service/res/values-gl/strings.xml
index 4893565..61dd97e 100644
--- a/service/res/values-gl/strings.xml
+++ b/service/res/values-gl/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controlar a política de enerxía do coche."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"xerar modelos"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Xerar modelos."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Dispositivo"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Convidado"</string>
<string name="importance_default" msgid="8587741629268312938">"Importancia predeterminada"</string>
diff --git a/service/res/values-gu/strings.xml b/service/res/values-gu/strings.xml
index feb17b3..ed1ea57 100644
--- a/service/res/values-gu/strings.xml
+++ b/service/res/values-gu/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"કારની સુવિધાઓ ચાલુ/બંધ રહેવા વિશેની નીતિને નિયંત્રિત કરો."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"નમૂના જનરેટ કરો"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"નમૂના જનરેટ કરો."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"મારું ડિવાઇસ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"અતિથિ"</string>
<string name="importance_default" msgid="8587741629268312938">"ડિફૉલ્ટ મહત્ત્વ"</string>
diff --git a/service/res/values-hi/strings.xml b/service/res/values-hi/strings.xml
index cd93c95..acb03b0 100644
--- a/service/res/values-hi/strings.xml
+++ b/service/res/values-hi/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"कार पावर नीति कंट्रोल करें."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"टेंप्लेट बनाएं"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"टेंप्लेट बनाएं."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"मेरा डिवाइस"</string>
<string name="default_guest_name" msgid="2912812799433131476">"मेहमान"</string>
<string name="importance_default" msgid="8587741629268312938">"डिफ़ॉल्ट अहमियत"</string>
diff --git a/service/res/values-hr/strings.xml b/service/res/values-hr/strings.xml
index 151e3a1..27ed86f 100644
--- a/service/res/values-hr/strings.xml
+++ b/service/res/values-hr/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Upravljanje pravilom napajanja automobila."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"generirati predloške"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Generirati predloške."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moj uređaj"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gost"</string>
<string name="importance_default" msgid="8587741629268312938">"Zadana važnost"</string>
diff --git a/service/res/values-hu/strings.xml b/service/res/values-hu/strings.xml
index 091983f..b757bf4 100644
--- a/service/res/values-hu/strings.xml
+++ b/service/res/values-hu/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Vezérelheti az autó energiaellátási házirendjét."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"sablonok renderelése"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Sablonok renderelése."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Saját eszköz"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Vendég"</string>
<string name="importance_default" msgid="8587741629268312938">"Alapértelmezett fontosságú"</string>
diff --git a/service/res/values-hy/strings.xml b/service/res/values-hy/strings.xml
index 4b19d02..37714ba 100644
--- a/service/res/values-hy/strings.xml
+++ b/service/res/values-hy/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Կառավարել ավտոմեքենայի հզորության քաղաքականությունը։"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"արտապատկերել ձևանմուշները"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Ձևանմուշների արտապատկերում։"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Իմ սարքը"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Հյուր"</string>
<string name="importance_default" msgid="8587741629268312938">"Կարևորություն (կանխադրված)"</string>
diff --git a/service/res/values-in/strings.xml b/service/res/values-in/strings.xml
index f138fdd..8fe082e 100644
--- a/service/res/values-in/strings.xml
+++ b/service/res/values-in/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrol kebijakan daya mobil."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"merender template"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Merender template."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Perangkat Saya"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Tamu"</string>
<string name="importance_default" msgid="8587741629268312938">"Tingkat kepentingan: default"</string>
diff --git a/service/res/values-is/strings.xml b/service/res/values-is/strings.xml
index a7c8c2d..398b853 100644
--- a/service/res/values-is/strings.xml
+++ b/service/res/values-is/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Stjórna ræsistýringum bíls."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"teikna sniðmát"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Teikna sniðmát."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Tækið mitt"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gestur"</string>
<string name="importance_default" msgid="8587741629268312938">"Sjálfgefið mikilvægi"</string>
diff --git a/service/res/values-it/strings.xml b/service/res/values-it/strings.xml
index d923bb6..c526950 100644
--- a/service/res/values-it/strings.xml
+++ b/service/res/values-it/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controlla i criteri di alimentazione dell\'auto."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"Visualizzazione di modelli"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Consente di visualizzare i modelli."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mio dispositivo"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Ospite"</string>
<string name="importance_default" msgid="8587741629268312938">"Importanza predefinita"</string>
diff --git a/service/res/values-iw/strings.xml b/service/res/values-iw/strings.xml
index 173348b..60fcfae 100644
--- a/service/res/values-iw/strings.xml
+++ b/service/res/values-iw/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"שליטה במדיניות הזנת המתח של הרכב."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"עיבוד תבניות"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"עיבוד תבניות."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"המכשיר שלי"</string>
<string name="default_guest_name" msgid="2912812799433131476">"אורח"</string>
<string name="importance_default" msgid="8587741629268312938">"חשיבות ברירת מחדל"</string>
diff --git a/service/res/values-ja/strings.xml b/service/res/values-ja/strings.xml
index ca74e68..c8f5cca 100644
--- a/service/res/values-ja/strings.xml
+++ b/service/res/values-ja/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"車の電源ポリシーの制御。"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"テンプレートの表示"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"テンプレートの表示。"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"自分のデバイス"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ゲスト"</string>
<string name="importance_default" msgid="8587741629268312938">"重要度: デフォルト"</string>
diff --git a/service/res/values-ka/strings.xml b/service/res/values-ka/strings.xml
index b2fcc4f..5307ac1 100644
--- a/service/res/values-ka/strings.xml
+++ b/service/res/values-ka/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"აკონტროლებს მანქანაში კომპონენტების ჩართვის წესებს."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"შაბლონების ჩვენება"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"შაბლონების ჩვენება."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ჩემი მოწყობილობა"</string>
<string name="default_guest_name" msgid="2912812799433131476">"სტუმარი"</string>
<string name="importance_default" msgid="8587741629268312938">"ნაგულისხმევი მნიშვნელოვნება"</string>
diff --git a/service/res/values-kk/strings.xml b/service/res/values-kk/strings.xml
index c33ff04..e859148 100644
--- a/service/res/values-kk/strings.xml
+++ b/service/res/values-kk/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Көлік қуаты туралы саясатты басқару."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"рендеринг үлгілері"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Рендеринг үлгілері"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Құрылғым"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Қонақ"</string>
<string name="importance_default" msgid="8587741629268312938">"Әдепкі маңыздылық"</string>
diff --git a/service/res/values-km/strings.xml b/service/res/values-km/strings.xml
index c9701c0..3d96082 100644
--- a/service/res/values-km/strings.xml
+++ b/service/res/values-km/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"គ្រប់គ្រងគោលការណ៍ថាមពលរថយន្ត។"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"បំប្លែងទម្រង់គំរូ"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"បំប្លែងទម្រង់គំរូ។"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ឧបករណ៍របស់ខ្ញុំ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ភ្ញៀវ"</string>
<string name="importance_default" msgid="8587741629268312938">"កម្រិតសំខាន់តាមលំនាំដើម"</string>
diff --git a/service/res/values-kn/strings.xml b/service/res/values-kn/strings.xml
index 30f5010..f6f498a 100644
--- a/service/res/values-kn/strings.xml
+++ b/service/res/values-kn/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"ಕಾರಿನ ಪವರ್ ನೀತಿಯನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"ಟೆಂಪ್ಲೇಟ್ಗಳನ್ನು ರೆಂಡರ್ ಮಾಡಿ"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"ಟೆಂಪ್ಲೇಟ್ಗಳನ್ನು ರೆಂಡರ್ ಮಾಡಿ."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ನನ್ನ ಸಾಧನ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ಅತಿಥಿ"</string>
<string name="importance_default" msgid="8587741629268312938">"ಮಹತ್ವವಾದುದು: ಡೀಫಾಲ್ಟ್"</string>
diff --git a/service/res/values-ko/strings.xml b/service/res/values-ko/strings.xml
index e9b09d6..00b0db5 100644
--- a/service/res/values-ko/strings.xml
+++ b/service/res/values-ko/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"차량 전원 정책을 관리합니다."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"템플릿 렌더링"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"템플릿 렌더링"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"내 기기"</string>
<string name="default_guest_name" msgid="2912812799433131476">"게스트"</string>
<string name="importance_default" msgid="8587741629268312938">"중요도가 기본인 알림 채널"</string>
diff --git a/service/res/values-ky/strings.xml b/service/res/values-ky/strings.xml
index 2f1094e..5a91173 100644
--- a/service/res/values-ky/strings.xml
+++ b/service/res/values-ky/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Унаанын компоненттерин өчүрүү/күйгүзүү саясатын башкаруу."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"үлгүлөрдү түзүү"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Үлгүлөрдү түзүү."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Түзмөгүм"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Конок"</string>
<string name="importance_default" msgid="8587741629268312938">"Демейки маанилүүлүк"</string>
diff --git a/service/res/values-lo/strings.xml b/service/res/values-lo/strings.xml
index 4f986e5..19f4f15 100644
--- a/service/res/values-lo/strings.xml
+++ b/service/res/values-lo/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"ຄວບຄຸມນະໂຍບາຍພະລັງງານສຳລັບລົດຍົນ."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"ສະແດງແມ່ແບບ"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"ສະແດງແມ່ແບບ."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ອຸປະກອນຂອງຂ້ອຍ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ແຂກ"</string>
<string name="importance_default" msgid="8587741629268312938">"ຄວາມສຳຄັນເລີ່ມຕົ້ນ"</string>
diff --git a/service/res/values-lt/strings.xml b/service/res/values-lt/strings.xml
index 5e31a58..5c81219 100644
--- a/service/res/values-lt/strings.xml
+++ b/service/res/values-lt/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Valdyti automobilio komponentų suaktyvinimo politiką."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"Pateikti šablonus"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Pateikti šablonus."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mano įrenginys"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Svečias"</string>
<string name="importance_default" msgid="8587741629268312938">"Numatytoji svarba"</string>
diff --git a/service/res/values-lv/strings.xml b/service/res/values-lv/strings.xml
index 955d32b..62b697e 100644
--- a/service/res/values-lv/strings.xml
+++ b/service/res/values-lv/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrolēt automašīnas komponentu aktivizācijas politiku."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"atveidot veidnes"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Atveidot veidnes."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mana ierīce"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Viesis"</string>
<string name="importance_default" msgid="8587741629268312938">"Noklusējuma svarīgums"</string>
diff --git a/service/res/values-mk/strings.xml b/service/res/values-mk/strings.xml
index 54faa26..0680eb2 100644
--- a/service/res/values-mk/strings.xml
+++ b/service/res/values-mk/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Контролирање на правилото за напојување на автомобилот."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"прикажување шаблони"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Прикажување шаблони."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Мојот уред"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Гостин"</string>
<string name="importance_default" msgid="8587741629268312938">"Стандардна важност"</string>
diff --git a/service/res/values-ml/strings.xml b/service/res/values-ml/strings.xml
index 2e9d97b..476115d 100644
--- a/service/res/values-ml/strings.xml
+++ b/service/res/values-ml/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"കാറിന്റെ പവർ പോളിസി നിയന്ത്രിക്കുക."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"ടെംപ്ലേറ്റുകൾ റെൻഡർ ചെയ്യുക"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"ടെംപ്ലേറ്റുകൾ റെൻഡർ ചെയ്യുക."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"എന്റെ ഉപകരണം"</string>
<string name="default_guest_name" msgid="2912812799433131476">"അതിഥി"</string>
<string name="importance_default" msgid="8587741629268312938">"ഡിഫോൾട്ട് പ്രാധാന്യം"</string>
diff --git a/service/res/values-mn/strings.xml b/service/res/values-mn/strings.xml
index aadd3ea..9f802b6 100644
--- a/service/res/values-mn/strings.xml
+++ b/service/res/values-mn/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Машины асаах/унтраах бодлогыг хянана."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"загварыг буулгах"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Загварыг буулгана."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Миний төхөөрөмж"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Зочин"</string>
<string name="importance_default" msgid="8587741629268312938">"Өгөгдмөл ач холбогдол"</string>
diff --git a/service/res/values-mr/strings.xml b/service/res/values-mr/strings.xml
index abc96a9..d5f781b 100644
--- a/service/res/values-mr/strings.xml
+++ b/service/res/values-mr/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"कार पॉवर धोरण नियंत्रित करा."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"टेम्पलेट रेंडर करा"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"टेम्पलेट रेंडर करा."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"माझे डिव्हाइस"</string>
<string name="default_guest_name" msgid="2912812799433131476">"अतिथी"</string>
<string name="importance_default" msgid="8587741629268312938">"डीफॉल्ट महत्त्वाची"</string>
diff --git a/service/res/values-ms/strings.xml b/service/res/values-ms/strings.xml
index bf36586..af016d9 100644
--- a/service/res/values-ms/strings.xml
+++ b/service/res/values-ms/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kawal dasar kuasa kereta."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"paparkan templat"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Paparkan templat."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Peranti Saya"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Tetamu"</string>
<string name="importance_default" msgid="8587741629268312938">"Kepentingan lalai"</string>
diff --git a/service/res/values-my/strings.xml b/service/res/values-my/strings.xml
index 2fe4223..f8b9971 100644
--- a/service/res/values-my/strings.xml
+++ b/service/res/values-my/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"ကား၏စွမ်းအင်အသုံးပြုမှု မူဝါဒကို ထိန်းချုပ်မည်။"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"နမူနာပုံစံများ ပုံဖော်ရန်"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"နမူနာပုံစံများ ပုံဖော်မည်။"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ကျွန်ုပ်၏စက်"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ဧည့်သည်"</string>
<string name="importance_default" msgid="8587741629268312938">"ပုံမှန် အရေးပါမှု"</string>
diff --git a/service/res/values-nb/strings.xml b/service/res/values-nb/strings.xml
index 16b8629..a11572e 100644
--- a/service/res/values-nb/strings.xml
+++ b/service/res/values-nb/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrollér bilens regler for av/på."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"gjengi maler"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Gjengi maler."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Enheten min"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gjest"</string>
<string name="importance_default" msgid="8587741629268312938">"Standard viktighet"</string>
diff --git a/service/res/values-ne/strings.xml b/service/res/values-ne/strings.xml
index 5462e90..193d32b 100644
--- a/service/res/values-ne/strings.xml
+++ b/service/res/values-ne/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"कारको पावरसम्बन्धी नीति नियन्त्रण गर्नुहोस्।"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"टेम्प्लेटहरू रेन्डर गर्ने"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"टेम्प्लेटहरू रेन्डर गर्ने।"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"मेरो डिभाइस"</string>
<string name="default_guest_name" msgid="2912812799433131476">"अतिथि"</string>
<string name="importance_default" msgid="8587741629268312938">"डिफल्ट महत्त्व"</string>
diff --git a/service/res/values-nl/strings.xml b/service/res/values-nl/strings.xml
index 1b8ae40..1828bd1 100644
--- a/service/res/values-nl/strings.xml
+++ b/service/res/values-nl/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"In-/uitschakelbeleid voor auto beheren."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"templates renderen"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Templates renderen."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Mijn apparaat"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gast"</string>
<string name="importance_default" msgid="8587741629268312938">"Standaardbelang"</string>
diff --git a/service/res/values-or/strings.xml b/service/res/values-or/strings.xml
index c9794a4..ef6a1e7 100644
--- a/service/res/values-or/strings.xml
+++ b/service/res/values-or/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"କାର୍ ପାୱାର୍ ନୀତି ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"ଟେମ୍ପଲେଟ୍ ରେଣ୍ଡର୍ କରନ୍ତୁ"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"ଟେମ୍ପଲେଟ୍ ରେଣ୍ଡର୍ କରନ୍ତୁ।"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ମୋ ଡିଭାଇସ୍"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ଅତିଥି"</string>
<string name="importance_default" msgid="8587741629268312938">"ଡିଫଲ୍ଟ ଗୁରୁତ୍ୱ"</string>
diff --git a/service/res/values-pa/strings.xml b/service/res/values-pa/strings.xml
index 6037bee..56d461d 100644
--- a/service/res/values-pa/strings.xml
+++ b/service/res/values-pa/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"ਕਾਰ ਪਾਵਰ ਨੀਤੀ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ।"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"ਟੈਮਪਲੇਟਾਂ ਨੂੰ ਰੈਂਡਰ ਕਰੋ"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"ਟੈਮਪਲੇਟਾਂ ਨੂੰ ਰੈਂਡਰ ਕਰੋ।"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"ਮੇਰਾ ਡੀਵਾਈਸ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ਮਹਿਮਾਨ"</string>
<string name="importance_default" msgid="8587741629268312938">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਮਹੱਤਤਾ"</string>
diff --git a/service/res/values-pl/strings.xml b/service/res/values-pl/strings.xml
index 3c0d085..fc07c11 100644
--- a/service/res/values-pl/strings.xml
+++ b/service/res/values-pl/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Sterowanie zasadami zasilania samochodu."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderowanie szablonów"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderowanie szablonów."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moje urządzenie"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gość"</string>
<string name="importance_default" msgid="8587741629268312938">"Domyślny stopień ważności"</string>
diff --git a/service/res/values-pt-rPT/strings.xml b/service/res/values-pt-rPT/strings.xml
index f13f6c4..30384cb 100644
--- a/service/res/values-pt-rPT/strings.xml
+++ b/service/res/values-pt-rPT/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controlar a política de energia do automóvel."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderizar modelos"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderizar modelos."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Dispositivo"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Convidado"</string>
<string name="importance_default" msgid="8587741629268312938">"Importância predefinida"</string>
diff --git a/service/res/values-pt/strings.xml b/service/res/values-pt/strings.xml
index 0ed6870..2fee366 100644
--- a/service/res/values-pt/strings.xml
+++ b/service/res/values-pt/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controle a política de energia do carro."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"renderizar modelos"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Renderizar modelos."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Meu dispositivo"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Visitante"</string>
<string name="importance_default" msgid="8587741629268312938">"Importância padrão"</string>
diff --git a/service/res/values-ro/strings.xml b/service/res/values-ro/strings.xml
index 23ceb47..1a8bbde 100644
--- a/service/res/values-ro/strings.xml
+++ b/service/res/values-ro/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Controlați politica pentru încărcarea mașinii."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"redați șabloane"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Redați șabloane."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Dispozitivul meu"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Invitat"</string>
<string name="importance_default" msgid="8587741629268312938">"Importanță prestabilită"</string>
diff --git a/service/res/values-ru/strings.xml b/service/res/values-ru/strings.xml
index ee42b35..5de2860 100644
--- a/service/res/values-ru/strings.xml
+++ b/service/res/values-ru/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Управление правилом о питании автомобиля."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"Обработка шаблонов"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Обработка шаблонов."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Мое устройство"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Гость"</string>
<string name="importance_default" msgid="8587741629268312938">"Важность по умолчанию"</string>
diff --git a/service/res/values-si/strings.xml b/service/res/values-si/strings.xml
index 50b9180..9e63f6c 100644
--- a/service/res/values-si/strings.xml
+++ b/service/res/values-si/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"මෝටර් රථයේ බල ප්රතිපත්තිය පාලනය කරන්න."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"අච්චු විදහන්න"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"අච්චු විදහන්න."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"මගේ උපාංගය"</string>
<string name="default_guest_name" msgid="2912812799433131476">"අමුත්තා"</string>
<string name="importance_default" msgid="8587741629268312938">"පෙරනිමි වැදගත්කම"</string>
diff --git a/service/res/values-sk/strings.xml b/service/res/values-sk/strings.xml
index 59d9bcb..c5927cc 100644
--- a/service/res/values-sk/strings.xml
+++ b/service/res/values-sk/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Ovládanie pravidiel pre napájanie komponentov auta."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"vykresľovanie šablón"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Vykresľovanie šablón."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moje zariadenie"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Hosť"</string>
<string name="importance_default" msgid="8587741629268312938">"Predvolená dôležitosť"</string>
diff --git a/service/res/values-sl/strings.xml b/service/res/values-sl/strings.xml
index 2765eb9..9662ac4 100644
--- a/service/res/values-sl/strings.xml
+++ b/service/res/values-sl/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Nadziranje pravilnika o delovanju komponent v avtomobilu."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"upodabljanje predlog"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Upodabljanje predlog."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Moja naprava"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gost"</string>
<string name="importance_default" msgid="8587741629268312938">"Privzeta pomembnost"</string>
diff --git a/service/res/values-sq/strings.xml b/service/res/values-sq/strings.xml
index 54881cc..2bdaaa1 100644
--- a/service/res/values-sq/strings.xml
+++ b/service/res/values-sq/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrollo politikën e makinës për aktivizimin."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"të paraqesë shabllonet"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Të paraqesë shabllonet."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Pajisja ime"</string>
<string name="default_guest_name" msgid="2912812799433131476">"I ftuar"</string>
<string name="importance_default" msgid="8587741629268312938">"Rëndësia e parazgjedhur"</string>
diff --git a/service/res/values-sr/strings.xml b/service/res/values-sr/strings.xml
index ab9aaf8..5e69d4f 100644
--- a/service/res/values-sr/strings.xml
+++ b/service/res/values-sr/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Контрола смерница за напајање аутомобила."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"приказивање шаблона"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Приказивање шаблона."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Мој уређај"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Гост"</string>
<string name="importance_default" msgid="8587741629268312938">"Подразумевана важност"</string>
diff --git a/service/res/values-sv/strings.xml b/service/res/values-sv/strings.xml
index 18c768c..653bc81 100644
--- a/service/res/values-sv/strings.xml
+++ b/service/res/values-sv/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Styr principer för bilens laddning."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"rendera mallar"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Rendera mallar."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Min enhet"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Gäst"</string>
<string name="importance_default" msgid="8587741629268312938">"Standardviktighet"</string>
diff --git a/service/res/values-sw/strings.xml b/service/res/values-sw/strings.xml
index f64453c..dee4351 100644
--- a/service/res/values-sw/strings.xml
+++ b/service/res/values-sw/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Dhibiti sera ya nishati ya gari."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"kutekeleza violezo"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Kutekeleza violezo."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Kifaa Changu"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Mgeni"</string>
<string name="importance_default" msgid="8587741629268312938">"Umuhimu wa kiwango cha chaguomsingi"</string>
diff --git a/service/res/values-ta/strings.xml b/service/res/values-ta/strings.xml
index dbb9377..0f468bd 100644
--- a/service/res/values-ta/strings.xml
+++ b/service/res/values-ta/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"காரின் பவர் கொள்கையைக் கட்டுப்படுத்தும்."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"டெம்ப்ளேட்டுகளைக் காட்டுதல்"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"டெம்ப்ளேட்டுகளைக் காட்டுதல்."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"எனது சாதனம்"</string>
<string name="default_guest_name" msgid="2912812799433131476">"விருந்தினர்"</string>
<string name="importance_default" msgid="8587741629268312938">"இயல்புநிலை முக்கியத்துவம்"</string>
diff --git a/service/res/values-te/strings.xml b/service/res/values-te/strings.xml
index ad75dde..30ab4e3 100644
--- a/service/res/values-te/strings.xml
+++ b/service/res/values-te/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"కారు పవర్ పాలసీని కంట్రోల్ చేయండి."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"టెంప్లేట్లను రెండర్ చేస్తుంది"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"టెంప్లేట్లను రెండర్ చేస్తుంది."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"నా పరికరం"</string>
<string name="default_guest_name" msgid="2912812799433131476">"అతిథి"</string>
<string name="importance_default" msgid="8587741629268312938">"ప్రాముఖ్యత ఆటోమేటిక్ సెట్టింగ్గా ఉన్నది"</string>
diff --git a/service/res/values-th/strings.xml b/service/res/values-th/strings.xml
index 2e734d6..01dd0e0 100644
--- a/service/res/values-th/strings.xml
+++ b/service/res/values-th/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"ควบคุมนโยบายทางไฟฟ้าสำหรับรถยนต์"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"แสดงผลเทมเพลต"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"แสดงผลเทมเพลต"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"อุปกรณ์ของฉัน"</string>
<string name="default_guest_name" msgid="2912812799433131476">"ผู้มาเยือน"</string>
<string name="importance_default" msgid="8587741629268312938">"ความสำคัญเริ่มต้น"</string>
diff --git a/service/res/values-tl/strings.xml b/service/res/values-tl/strings.xml
index 07610d4..8d8a259 100644
--- a/service/res/values-tl/strings.xml
+++ b/service/res/values-tl/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kontrolin ang patakaran sa power ng kotse."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"mag-render nga template"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Mag-render ng mga template."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Aking Device"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Bisita"</string>
<string name="importance_default" msgid="8587741629268312938">"Default na halaga"</string>
diff --git a/service/res/values-tr/strings.xml b/service/res/values-tr/strings.xml
index ee64202..9fb6a42 100644
--- a/service/res/values-tr/strings.xml
+++ b/service/res/values-tr/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Araba gücü politikasını kontrol edin."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"şablonları oluşturma"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Şablonları oluşturma."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Cihazım"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Misafir"</string>
<string name="importance_default" msgid="8587741629268312938">"Varsayılan önem"</string>
diff --git a/service/res/values-uk/strings.xml b/service/res/values-uk/strings.xml
index 8f26fbe..18fa873 100644
--- a/service/res/values-uk/strings.xml
+++ b/service/res/values-uk/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Керувати правилами щодо ввімкнення компонентів автомобіля."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"відображати шаблони"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Відображати шаблони."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Мій пристрій"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Гість"</string>
<string name="importance_default" msgid="8587741629268312938">"Пріоритет за умовчанням"</string>
diff --git a/service/res/values-ur/strings.xml b/service/res/values-ur/strings.xml
index a40f2c2..14063b8 100644
--- a/service/res/values-ur/strings.xml
+++ b/service/res/values-ur/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"کار کے پاور کی پالیسی کو کنٹرول کریں۔"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"تمثیلات تیار کریں"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"تمثیلات تیار کریں۔"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"میرا آلہ"</string>
<string name="default_guest_name" msgid="2912812799433131476">"مہمان"</string>
<string name="importance_default" msgid="8587741629268312938">"ڈیفالٹ اہمیت"</string>
diff --git a/service/res/values-uz/strings.xml b/service/res/values-uz/strings.xml
index 5654872..ed419c5 100644
--- a/service/res/values-uz/strings.xml
+++ b/service/res/values-uz/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Avtomobilning yoqish qoidalarini boshqarish."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"andozalarni renderlash"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Andozalarni renderlash."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Qurilmam"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Mehmon"</string>
<string name="importance_default" msgid="8587741629268312938">"Birlamchi muhimlik"</string>
diff --git a/service/res/values-vi/strings.xml b/service/res/values-vi/strings.xml
index 9859ed3..68df7d3 100644
--- a/service/res/values-vi/strings.xml
+++ b/service/res/values-vi/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Kiểm soát nguyên tắc sử dụng điện của ô tô."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"mẫu kết xuất hình ảnh"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Mẫu kết xuất hình ảnh."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Thiết bị của tôi"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Khách"</string>
<string name="importance_default" msgid="8587741629268312938">"Tầm quan trọng mặc định"</string>
diff --git a/service/res/values-zh-rCN/strings.xml b/service/res/values-zh-rCN/strings.xml
index d79029a..cc1f8ce 100644
--- a/service/res/values-zh-rCN/strings.xml
+++ b/service/res/values-zh-rCN/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"控制汽车电源政策。"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"渲染模板"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"渲染模板。"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"我的设备"</string>
<string name="default_guest_name" msgid="2912812799433131476">"访客"</string>
<string name="importance_default" msgid="8587741629268312938">"重要性:默认"</string>
diff --git a/service/res/values-zh-rHK/strings.xml b/service/res/values-zh-rHK/strings.xml
index 9e21222..64824fa 100644
--- a/service/res/values-zh-rHK/strings.xml
+++ b/service/res/values-zh-rHK/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"控制汽車能源政策。"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"輸出範本"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"輸出範本。"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"我的裝置"</string>
<string name="default_guest_name" msgid="2912812799433131476">"訪客"</string>
<string name="importance_default" msgid="8587741629268312938">"預設重要性"</string>
diff --git a/service/res/values-zh-rTW/strings.xml b/service/res/values-zh-rTW/strings.xml
index 8d9e437..a85efcc 100644
--- a/service/res/values-zh-rTW/strings.xml
+++ b/service/res/values-zh-rTW/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"控制車輛電源政策。"</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"算繪範本"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"算繪範本。"</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"我的裝置"</string>
<string name="default_guest_name" msgid="2912812799433131476">"訪客"</string>
<string name="importance_default" msgid="8587741629268312938">"預設重要性"</string>
diff --git a/service/res/values-zu/strings.xml b/service/res/values-zu/strings.xml
index a572af8..cdcdca7 100644
--- a/service/res/values-zu/strings.xml
+++ b/service/res/values-zu/strings.xml
@@ -169,6 +169,10 @@
<string name="car_permission_desc_control_car_power_policy" msgid="8565782440893507028">"Lawula inqubomgomo yamandla emoto."</string>
<string name="car_permission_label_template_renderer" msgid="3464887382919754850">"nikezela izifanekiso"</string>
<string name="car_permission_desc_template_renderer" msgid="6047233999260920122">"Nikezela izifanekiso."</string>
+ <!-- no translation found for car_permission_label_control_car_app_launch (214632389637409226) -->
+ <skip />
+ <!-- no translation found for car_permission_desc_control_car_app_launch (4245527461733374198) -->
+ <skip />
<string name="trust_device_default_name" msgid="4213625926070261253">"Idivayisi yami"</string>
<string name="default_guest_name" msgid="2912812799433131476">"Isihambeli"</string>
<string name="importance_default" msgid="8587741629268312938">"Ukubaluleka okuzenzakalelayo"</string>
diff --git a/service/src/com/android/car/CarLog.java b/service/src/com/android/car/CarLog.java
index 4585eda..3cec3bb 100644
--- a/service/src/com/android/car/CarLog.java
+++ b/service/src/com/android/car/CarLog.java
@@ -43,6 +43,7 @@
public static final String TAG_SERVICE = "CAR.SERVICE";
public static final String TAG_STORAGE = "CAR.STORAGE";
public static final String TAG_TELEMETRY = "CAR.TELEMETRY";
+ public static final String TAG_TIME = "CAR.TIME";
public static final String TAG_WATCHDOG = "CAR.WATCHDOG";
/**
diff --git a/service/src/com/android/car/CarServiceUtils.java b/service/src/com/android/car/CarServiceUtils.java
index 2dddeeb..c4f77cf 100644
--- a/service/src/com/android/car/CarServiceUtils.java
+++ b/service/src/com/android/car/CarServiceUtils.java
@@ -154,8 +154,17 @@
}
public static float[] toFloatArray(List<Float> list) {
- final int size = list.size();
- final float[] array = new float[size];
+ int size = list.size();
+ float[] array = new float[size];
+ for (int i = 0; i < size; ++i) {
+ array[i] = list.get(i);
+ }
+ return array;
+ }
+
+ public static long[] toLongArray(List<Long> list) {
+ int size = list.size();
+ long[] array = new long[size];
for (int i = 0; i < size; ++i) {
array[i] = list.get(i);
}
@@ -163,8 +172,8 @@
}
public static int[] toIntArray(List<Integer> list) {
- final int size = list.size();
- final int[] array = new int[size];
+ int size = list.size();
+ int[] array = new int[size];
for (int i = 0; i < size; ++i) {
array[i] = list.get(i);
}
@@ -172,8 +181,8 @@
}
public static byte[] toByteArray(List<Byte> list) {
- final int size = list.size();
- final byte[] array = new byte[size];
+ int size = list.size();
+ byte[] array = new byte[size];
for (int i = 0; i < size; ++i) {
array[i] = list.get(i);
}
diff --git a/service/src/com/android/car/evs/CarEvsService.java b/service/src/com/android/car/evs/CarEvsService.java
index 5c1a8ab..7af1adb 100644
--- a/service/src/com/android/car/evs/CarEvsService.java
+++ b/service/src/com/android/car/evs/CarEvsService.java
@@ -121,9 +121,9 @@
private static final int MSG_CHECK_ACTIVITY_REQUEST_TIMEOUT = 0;
// Service request priorities
- private static final int REQUEST_PRIORITY_HIGH = 0;
+ private static final int REQUEST_PRIORITY_LOW = 0;
private static final int REQUEST_PRIORITY_NORMAL = 1;
- private static final int REQUEST_PRIORITY_LOW = 2;
+ private static final int REQUEST_PRIORITY_HIGH = 2;
private static final class EvsHalEvent {
private long mTimestamp;
@@ -412,7 +412,7 @@
break;
case SERVICE_STATE_REQUESTED:
- if (priority > mLastRequestPriority) {
+ if (priority < mLastRequestPriority) {
// A current service request has a lower priority than a previous
// service request.
Slog.e(TAG_EVS,
@@ -425,7 +425,7 @@
break;
case SERVICE_STATE_ACTIVE:
- if (priority > mLastRequestPriority) {
+ if (priority < mLastRequestPriority) {
// We decline a request because CarEvsService is busy with a higher priority
// client.
return ERROR_BUSY;
@@ -503,7 +503,7 @@
case SERVICE_STATE_ACTIVE:
// CarEvsManager will transfer an active video stream to a new client with a
// higher or equal priority.
- if (priority > mLastRequestPriority) {
+ if (priority < mLastRequestPriority) {
Slog.i(TAG_EVS, "Declines a service request with a lower priority.");
break;
}
@@ -1217,7 +1217,8 @@
// Request to stop the rearview activity when the gear is shifted from the reverse
// position to other positions.
if (mStateEngine.execute(REQUEST_PRIORITY_HIGH, SERVICE_STATE_INACTIVE,
- CarEvsManager.SERVICE_TYPE_REARVIEW) != ERROR_NONE) {
+ CarEvsManager.SERVICE_TYPE_REARVIEW, /* token = */ null, mStreamCallback)
+ != ERROR_NONE) {
Slog.d(TAG_EVS, "Failed to stop the rearview activity.");
}
}
diff --git a/service/src/com/android/car/hal/TimeHalService.java b/service/src/com/android/car/hal/TimeHalService.java
new file mode 100644
index 0000000..a166850
--- /dev/null
+++ b/service/src/com/android/car/hal/TimeHalService.java
@@ -0,0 +1,145 @@
+/*
+ * 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.hal;
+
+import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.EPOCH_TIME;
+
+import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.automotive.vehicle.V2_0.VehicleArea;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyStatus;
+import android.util.IndentingPrintWriter;
+
+import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
+
+import java.io.PrintWriter;
+import java.time.Instant;
+import java.util.Collection;
+import java.util.List;
+
+/** Writes the Android System time to EPOCH_TIME in the VHAL, if supported. */
+public final class TimeHalService extends HalServiceBase {
+
+ private static final int[] SUPPORTED_PROPERTIES = new int[]{EPOCH_TIME};
+
+ private final Context mContext;
+
+ private final VehicleHal mHal;
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
+ updateProperty(System.currentTimeMillis());
+ }
+ }
+ };
+
+ private boolean mReceiverRegistered;
+
+ @Nullable
+ private Instant mLastAndroidTimeReported;
+
+ private boolean mAndroidTimeSupported;
+
+ TimeHalService(Context context, VehicleHal hal) {
+ mContext = requireNonNull(context);
+ mHal = requireNonNull(hal);
+ }
+
+ @Override
+ public void init() {
+ if (!mAndroidTimeSupported) {
+ return;
+ }
+
+ updateProperty(System.currentTimeMillis());
+
+ IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
+ mContext.registerReceiver(mReceiver, filter);
+ mReceiverRegistered = true;
+ }
+
+ @Override
+ public void release() {
+ if (mReceiverRegistered) {
+ mContext.unregisterReceiver(mReceiver);
+ mReceiverRegistered = false;
+ }
+
+ mAndroidTimeSupported = false;
+ mLastAndroidTimeReported = null;
+ }
+
+ @Override
+ public int[] getAllSupportedProperties() {
+ return SUPPORTED_PROPERTIES;
+ }
+
+ @Override
+ public void takeProperties(Collection<VehiclePropConfig> properties) {
+ for (VehiclePropConfig property : properties) {
+ switch (property.prop) {
+ case EPOCH_TIME:
+ mAndroidTimeSupported = true;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void onHalEvents(List<VehiclePropValue> values) {
+ }
+
+ public boolean isAndroidTimeSupported() {
+ return mAndroidTimeSupported;
+ }
+
+ private void updateProperty(long timeMillis) {
+ VehiclePropValue propValue = new VehiclePropValue();
+ propValue.prop = EPOCH_TIME;
+ propValue.areaId = VehicleArea.GLOBAL;
+ propValue.status = VehiclePropertyStatus.AVAILABLE;
+ propValue.timestamp = timeMillis;
+ propValue.value.int64Values.add(timeMillis);
+
+ mHal.set(propValue);
+ mLastAndroidTimeReported = Instant.ofEpochMilli(timeMillis);
+ }
+
+ @Override
+ @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
+ public void dump(PrintWriter printWriter) {
+ IndentingPrintWriter writer = new IndentingPrintWriter(printWriter);
+ writer.println("*ExternalTime HAL*");
+ writer.increaseIndent();
+ writer.printf(
+ "mLastAndroidTimeReported: %d millis",
+ mLastAndroidTimeReported.toEpochMilli());
+ writer.decreaseIndent();
+ writer.flush();
+ }
+}
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index 726f34f..6b67b8d 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -19,6 +19,7 @@
import static com.android.car.CarServiceUtils.toByteArray;
import static com.android.car.CarServiceUtils.toFloatArray;
import static com.android.car.CarServiceUtils.toIntArray;
+import static com.android.car.CarServiceUtils.toLongArray;
import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
import static java.lang.Integer.toHexString;
@@ -97,6 +98,7 @@
private final DiagnosticHalService mDiagnosticHal;
private final ClusterHalService mClusterHalService;
private final EvsHalService mEvsHal;
+ private final TimeHalService mTimeHalService;
private final Object mLock = new Object();
@@ -136,6 +138,8 @@
mDiagnosticHal = new DiagnosticHalService(this);
mClusterHalService = new ClusterHalService(this);
mEvsHal = new EvsHalService(this);
+ mTimeHalService = new TimeHalService(context, this);
+ //TODO(b/202396546): Dedupe this assignment with the other one in constructor below
mAllServices.addAll(Arrays.asList(mPowerHal,
mInputHal,
mDiagnosticHal,
@@ -143,6 +147,7 @@
mUserHal,
mClusterHalService,
mEvsHal,
+ mTimeHalService,
mPropertyHal)); // mPropertyHal should be the last.
mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(),
/* callback= */ this);
@@ -160,6 +165,7 @@
UserHalService userHal,
DiagnosticHalService diagnosticHal,
ClusterHalService clusterHalService,
+ TimeHalService timeHalService,
HalClient halClient,
HandlerThread handlerThread) {
mHandlerThread = handlerThread;
@@ -172,12 +178,14 @@
mDiagnosticHal = diagnosticHal;
mClusterHalService = clusterHalService;
mEvsHal = new EvsHalService(this);
+ mTimeHalService = timeHalService;
mAllServices.addAll(Arrays.asList(mPowerHal,
mInputHal,
mDiagnosticHal,
mVmsHal,
mUserHal,
mEvsHal,
+ mTimeHalService,
mPropertyHal));
mHalClient = halClient;
}
@@ -322,6 +330,10 @@
return mEvsHal;
}
+ public TimeHalService getTimeHalService() {
+ return mTimeHalService;
+ }
+
private void assertServiceOwnerLocked(HalServiceBase service, int property) {
if (service != mPropertyHandlers.get(property)) {
throw new IllegalArgumentException("Property 0x" + toHexString(property)
@@ -517,18 +529,25 @@
VehiclePropValue propValue;
propValue = mHalClient.getValue(requestedPropValue);
- if (clazz == Integer.class || clazz == int.class) {
+ if (clazz == Long.class || clazz == long.class) {
+ return (T) propValue.value.int64Values.get(0);
+ } else if (clazz == Integer.class || clazz == int.class) {
return (T) propValue.value.int32Values.get(0);
} else if (clazz == Boolean.class || clazz == boolean.class) {
return (T) Boolean.valueOf(propValue.value.int32Values.get(0) == 1);
} else if (clazz == Float.class || clazz == float.class) {
return (T) propValue.value.floatValues.get(0);
+ } else if (clazz == Long[].class) {
+ Long[] longArray = new Long[propValue.value.int64Values.size()];
+ return (T) propValue.value.int32Values.toArray(longArray);
} else if (clazz == Integer[].class) {
Integer[] intArray = new Integer[propValue.value.int32Values.size()];
return (T) propValue.value.int32Values.toArray(intArray);
} else if (clazz == Float[].class) {
Float[] floatArray = new Float[propValue.value.floatValues.size()];
return (T) propValue.value.floatValues.toArray(floatArray);
+ } else if (clazz == long[].class) {
+ return (T) toLongArray(propValue.value.int64Values);
} else if (clazz == int[].class) {
return (T) toIntArray(propValue.value.int32Values);
} else if (clazz == float[].class) {
diff --git a/service/src/com/android/car/power/CarPowerManagementService.java b/service/src/com/android/car/power/CarPowerManagementService.java
index b9d029b..24830a8 100644
--- a/service/src/com/android/car/power/CarPowerManagementService.java
+++ b/service/src/com/android/car/power/CarPowerManagementService.java
@@ -590,7 +590,7 @@
return;
}
String policyId = policy == null ? fallbackPolicyId : policy.getPolicyId();
- applyPowerPolicy(policyId, /* upToDaemon= */ true);
+ applyPowerPolicy(policyId, /* upToDaemon= */ true, /* force= */ false);
}
/**
@@ -1099,7 +1099,7 @@
Preconditions.checkArgument(policyId != null, "policyId cannot be null");
Preconditions.checkArgument(!policyId.startsWith(PolicyReader.SYSTEM_POWER_POLICY_PREFIX),
"System power policy cannot be applied by apps");
- int status = applyPowerPolicy(policyId, true);
+ int status = applyPowerPolicy(policyId, /* upToDaemon= */ true, /* force= */ false);
if (status != PolicyOperationStatus.OK) {
throw new IllegalArgumentException(PolicyOperationStatus.errorCodeToString(status));
}
@@ -1217,12 +1217,13 @@
// the power policy or the policy group passed from car power policy daemon, and notifies
// the current power policy to the daemon.
if (currentPowerPolicyId == null || currentPowerPolicyId.isEmpty()) {
- int status = applyPowerPolicy(state.policyId, false);
+ int status = applyPowerPolicy(state.policyId, /* upToDaemon= */ false,
+ /* force= */ false);
if (status != PolicyOperationStatus.OK) {
Slogf.w(TAG, PolicyOperationStatus.errorCodeToString(status));
}
} else {
- notifyPowerPolicyChangeToDaemon(currentPowerPolicyId);
+ notifyPowerPolicyChangeToDaemon(currentPowerPolicyId, /* force= */ true);
}
if (currentPolicyGroupId == null || currentPolicyGroupId.isEmpty()) {
int status = setCurrentPowerPolicyGroup(state.policyGroupId);
@@ -1248,7 +1249,7 @@
}
@PolicyOperationStatus.ErrorCode
- private int applyPowerPolicy(@Nullable String policyId, boolean upToDaemon) {
+ private int applyPowerPolicy(@Nullable String policyId, boolean upToDaemon, boolean force) {
CarPowerPolicy policy = mPolicyReader.getPowerPolicy(policyId);
if (policy == null) {
int error = PolicyOperationStatus.ERROR_APPLY_POWER_POLICY;
@@ -1265,7 +1266,7 @@
mCurrentPowerPolicyId = policyId;
}
mPowerComponentHandler.applyPowerPolicy(policy);
- notifyPowerPolicyChange(policyId, upToDaemon);
+ notifyPowerPolicyChange(policyId, upToDaemon, force);
Slogf.i(TAG, "The current power policy is %s", policyId);
return PolicyOperationStatus.OK;
}
@@ -1286,7 +1287,7 @@
mCurrentPowerPolicyId = policyId;
}
mPowerComponentHandler.applyPowerPolicy(policy);
- notifyPowerPolicyChange(policyId, true);
+ notifyPowerPolicyChange(policyId, /* upToDaemon= */ true, /* force= */ true);
Slogf.i(TAG, "The current power policy is %s", policyId);
return PolicyOperationStatus.OK;
}
@@ -1303,14 +1304,14 @@
policyId = mPendingPowerPolicyId;
mPendingPowerPolicyId = null;
}
- int status = applyPowerPolicy(policyId, true);
+ int status = applyPowerPolicy(policyId, /* upToDaemon= */ true, /* force= */ true);
if (status != PolicyOperationStatus.OK) {
Slogf.w(TAG, "Failed to cancel system power policy: %s",
PolicyOperationStatus.errorCodeToString(status));
}
}
- private void notifyPowerPolicyChangeToDaemon(String policyId) {
+ private void notifyPowerPolicyChangeToDaemon(String policyId, boolean force) {
ICarPowerPolicySystemNotification daemon;
boolean hadPendingPolicyNotification;
synchronized (mLock) {
@@ -1325,17 +1326,17 @@
}
}
try {
- daemon.notifyPowerPolicyChange(policyId);
+ daemon.notifyPowerPolicyChange(policyId, force);
} catch (RemoteException | IllegalStateException e) {
Slogf.e(TAG, e, "Failed to notify car power policy daemon of a new power policy(%s)",
policyId);
}
}
- private void notifyPowerPolicyChange(String policyId, boolean upToDaemon) {
+ private void notifyPowerPolicyChange(String policyId, boolean upToDaemon, boolean force) {
// Notify system clients
if (upToDaemon) {
- notifyPowerPolicyChangeToDaemon(policyId);
+ notifyPowerPolicyChangeToDaemon(policyId, force);
}
// Notify Java clients
@@ -1900,7 +1901,7 @@
}
boolean isPreemptive = mPolicyReader.isPreemptivePowerPolicy(powerPolicyId);
int status = isPreemptive ? applyPreemptivePowerPolicy(powerPolicyId)
- : applyPowerPolicy(powerPolicyId, true);
+ : applyPowerPolicy(powerPolicyId, /* upToDaemon= */ true, /* force= */ false);
if (status != PolicyOperationStatus.OK) {
writer.println(PolicyOperationStatus.errorCodeToString(status));
return false;
diff --git a/service/src/com/android/car/telemetry/proto/atoms.proto b/service/src/com/android/car/telemetry/proto/atoms.proto
index 8f14b38..ccb9021 100644
--- a/service/src/com/android/car/telemetry/proto/atoms.proto
+++ b/service/src/com/android/car/telemetry/proto/atoms.proto
@@ -25,6 +25,7 @@
message Atom {
oneof pushed {
+ ActivityForegroundStateChanged activity_foreground_state_changed = 42;
AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
}
@@ -56,3 +57,14 @@
optional int64 cache_in_bytes = 7;
optional int64 swap_in_bytes = 8;
}
+
+message ActivityForegroundStateChanged {
+ optional int32 uid = 1;
+ optional string pkg_name = 2;
+ optional string class_name = 3;
+ enum State {
+ BACKGROUND = 0;
+ FOREGROUND = 1;
+ }
+ optional State state = 4;
+}
diff --git a/service/src/com/android/car/telemetry/proto/stats_log.proto b/service/src/com/android/car/telemetry/proto/stats_log.proto
index 04308d2..ec76cb8 100644
--- a/service/src/com/android/car/telemetry/proto/stats_log.proto
+++ b/service/src/com/android/car/telemetry/proto/stats_log.proto
@@ -99,3 +99,15 @@
reserved 1, 10;
}
+
+message StatsdStatsReport {
+ message ConfigStats {
+ optional int32 uid = 1;
+ optional int64 id = 2;
+ optional bool is_valid = 9;
+ }
+
+ repeated ConfigStats config_stats = 3;
+
+ reserved 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19;
+}
diff --git a/service/src/com/android/car/telemetry/proto/telemetry.proto b/service/src/com/android/car/telemetry/proto/telemetry.proto
index b06f519..4106098 100644
--- a/service/src/com/android/car/telemetry/proto/telemetry.proto
+++ b/service/src/com/android/car/telemetry/proto/telemetry.proto
@@ -85,6 +85,8 @@
APP_START_MEMORY_STATE_CAPTURED = 1;
// Collects memory state of processes in 5-minute buckets (1 memory measurement per bucket).
PROCESS_MEMORY_STATE = 2;
+ // Collects activity foreground/background transition events.
+ ACTIVITY_FOREGROUND_STATE_CHANGED = 3;
}
// Required.
@@ -121,7 +123,8 @@
// A message that encapsulates an error that's produced when collecting metrics.
// Any changes here should also be reflected on
-// p/s/C/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorConstants.aidl
+// p/s/C/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorListener.aidl
+// p/s/C/package/ScriptExecutor/src/ScriptExecutorListener.h
message TelemetryError {
enum ErrorType {
// Not used.
diff --git a/service/src/com/android/car/telemetry/publisher/HashUtils.java b/service/src/com/android/car/telemetry/publisher/HashUtils.java
index 7fbd19f..98cc702 100644
--- a/service/src/com/android/car/telemetry/publisher/HashUtils.java
+++ b/service/src/com/android/car/telemetry/publisher/HashUtils.java
@@ -40,7 +40,7 @@
* Returns the hash code of the given string using SHA-256 algorithm. Returns only the first
* 8 bytes if the hash code, as SHA-256 is uniformly distributed.
*/
- static long sha256(@NonNull String data) {
+ public static long sha256(@NonNull String data) {
try {
return asLong(MessageDigest.getInstance("SHA-256").digest(data.getBytes()));
} catch (NoSuchAlgorithmException e) {
@@ -58,7 +58,7 @@
* @param str the string to be hashed.
* @return hash of the string.
*/
- static long murmur2Hash64(String str) {
+ public static long murmur2Hash64(String str) {
final byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
diff --git a/service/src/com/android/car/telemetry/publisher/StatsManagerImpl.java b/service/src/com/android/car/telemetry/publisher/StatsManagerImpl.java
index b184f28..ef54b3c 100644
--- a/service/src/com/android/car/telemetry/publisher/StatsManagerImpl.java
+++ b/service/src/com/android/car/telemetry/publisher/StatsManagerImpl.java
@@ -41,4 +41,9 @@
public void removeConfig(long configKey) throws StatsUnavailableException {
mStatsManager.removeConfig(configKey);
}
+
+ @Override
+ public byte[] getStatsMetadata() throws StatsUnavailableException {
+ return mStatsManager.getStatsMetadata();
+ }
}
diff --git a/service/src/com/android/car/telemetry/publisher/StatsManagerProxy.java b/service/src/com/android/car/telemetry/publisher/StatsManagerProxy.java
index 046ac44..5507e28 100644
--- a/service/src/com/android/car/telemetry/publisher/StatsManagerProxy.java
+++ b/service/src/com/android/car/telemetry/publisher/StatsManagerProxy.java
@@ -29,4 +29,7 @@
/** See {@link StatsManager#removeConfig(long)}. */
void removeConfig(long configKey) throws StatsUnavailableException;
+
+ /** See {@link StatsManager#getStatsMetadata()}. */
+ byte[] getStatsMetadata() throws StatsUnavailableException;
}
diff --git a/service/src/com/android/car/telemetry/publisher/StatsPublisher.java b/service/src/com/android/car/telemetry/publisher/StatsPublisher.java
index b3226a9..98406dc 100644
--- a/service/src/com/android/car/telemetry/publisher/StatsPublisher.java
+++ b/service/src/com/android/car/telemetry/publisher/StatsPublisher.java
@@ -16,11 +16,14 @@
package com.android.car.telemetry.publisher;
+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_MEMORY_STATE_FIELD_NUMBER;
import android.app.StatsManager.StatsUnavailableException;
import android.os.Handler;
import android.os.PersistableBundle;
+import android.os.Process;
import android.util.LongSparseArray;
import android.util.Slog;
@@ -32,6 +35,8 @@
import com.android.car.telemetry.TelemetryProto;
import com.android.car.telemetry.TelemetryProto.Publisher.PublisherCase;
import com.android.car.telemetry.databroker.DataSubscriber;
+import com.android.car.telemetry.publisher.statsconverters.ConfigMetricsReportListConverter;
+import com.android.car.telemetry.publisher.statsconverters.StatsConversionException;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
@@ -65,11 +70,17 @@
static final long PROCESS_MEMORY_STATE_MATCHER_ID = 3;
@VisibleForTesting
static final long PROCESS_MEMORY_STATE_GAUGE_METRIC_ID = 4;
+ @VisibleForTesting
+ static final long ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID = 5;
+ @VisibleForTesting
+ static final long ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID = 6;
// The file that contains stats config key and stats config version
@VisibleForTesting
static final String SAVED_STATS_CONFIGS_FILE = "stats_config_keys_versions";
+ // TODO(b/202115033): Flatten the load spike by pulling reports for each MetricsConfigs
+ // using separate periodical timers.
private static final Duration PULL_REPORTS_PERIOD = Duration.ofMinutes(10);
private static final String BUNDLE_CONFIG_KEY_PREFIX = "statsd-publisher-config-id-";
@@ -79,7 +90,7 @@
static final StatsdConfigProto.FieldMatcher PROCESS_MEMORY_STATE_FIELDS_MATCHER =
StatsdConfigProto.FieldMatcher.newBuilder()
.setField(
- AtomsProto.Atom.PROCESS_MEMORY_STATE_FIELD_NUMBER)
+ PROCESS_MEMORY_STATE_FIELD_NUMBER)
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
.setField(
AtomsProto.ProcessMemoryState.OOM_ADJ_SCORE_FIELD_NUMBER))
@@ -180,8 +191,6 @@
}
private void processReport(long configKey, StatsLogProto.ConfigMetricsReportList report) {
- // TODO(b/197269115): if StatsD reports invalid StatsdConfig, it should
- // onPublisherFailure() and provide the affected MetricsConfigs.
Slog.i(CarLog.TAG_TELEMETRY, "Received reports: " + report.getReportsCount());
if (report.getReportsCount() == 0) {
return;
@@ -198,53 +207,72 @@
Slog.e(CarLog.TAG_TELEMETRY, "Stats conversion exception for config " + configKey, ex);
return;
}
+ Long metricId;
switch (subscriber.getPublisherParam().getStats().getSystemMetric()) {
case APP_START_MEMORY_STATE_CAPTURED:
- if (!metricBundles.containsKey(APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID)) {
- Slog.w(CarLog.TAG_TELEMETRY,
- "Reports do not contain metric with id "
- + APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID
- + " for config " + configKey);
- return;
- }
- subscriber.push(
- metricBundles.get(APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID));
+ metricId = APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID;
break;
case PROCESS_MEMORY_STATE:
- if (!metricBundles.containsKey(PROCESS_MEMORY_STATE_GAUGE_METRIC_ID)) {
- Slog.w(CarLog.TAG_TELEMETRY,
- "Reports do not contain metric with id "
- + PROCESS_MEMORY_STATE_GAUGE_METRIC_ID
- + " for config " + configKey);
- return;
- }
- subscriber.push(metricBundles.get(PROCESS_MEMORY_STATE_GAUGE_METRIC_ID));
+ metricId = PROCESS_MEMORY_STATE_GAUGE_METRIC_ID;
+ break;
+ case ACTIVITY_FOREGROUND_STATE_CHANGED:
+ metricId = ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID;
break;
default:
- break;
+ return;
+ }
+ if (!metricBundles.containsKey(metricId)) {
+ Slog.w(CarLog.TAG_TELEMETRY,
+ "No reports for metric id " + metricId + " for config " + configKey);
+ return;
+ }
+ subscriber.push(metricBundles.get(metricId));
+ }
+
+ private void processStatsMetadata(StatsLogProto.StatsdStatsReport statsReport) {
+ int myUid = Process.myUid();
+ // configKey and StatsdConfig.id are the same, see this#addStatsConfig().
+ HashSet<Long> activeConfigKeys = new HashSet<>(getActiveConfigKeys());
+ HashSet<TelemetryProto.MetricsConfig> failedConfigs = new HashSet<>();
+ for (int i = 0; i < statsReport.getConfigStatsCount(); i++) {
+ StatsLogProto.StatsdStatsReport.ConfigStats stats = statsReport.getConfigStats(i);
+ if (stats.getUid() != myUid || !activeConfigKeys.contains(stats.getId())) {
+ continue;
+ }
+ if (!stats.getIsValid()) {
+ Slog.w(CarLog.TAG_TELEMETRY, "Config key " + stats.getId() + " is invalid.");
+ failedConfigs.add(mConfigKeyToSubscribers.get(stats.getId()).getMetricsConfig());
+ }
+ }
+ if (!failedConfigs.isEmpty()) {
+ // Notify DataBroker so it can disable invalid MetricsConfigs.
+ onPublisherFailure(
+ new ArrayList<>(failedConfigs),
+ new IllegalStateException("Found invalid configs"));
}
}
private void pullReportsPeriodically() {
- for (long configKey : getActiveConfigKeys()) {
- try {
- processReport(configKey, StatsLogProto.ConfigMetricsReportList.parseFrom(
- mStatsManager.getReports(configKey)));
- } catch (StatsUnavailableException e) {
- // If the StatsD is not available, retry in the next pullReportsPeriodically call.
- break;
- } catch (InvalidProtocolBufferException e) {
- // This case should never happen.
- Slog.w(CarLog.TAG_TELEMETRY,
- "Failed to parse report from statsd, configKey=" + configKey);
- }
- }
-
if (mIsPullingReports) {
Slog.d(CarLog.TAG_TELEMETRY, "Stats report will be pulled in "
+ PULL_REPORTS_PERIOD.toMinutes() + " minutes.");
mTelemetryHandler.postDelayed(mPullReportsPeriodically, PULL_REPORTS_PERIOD.toMillis());
}
+
+ try {
+ // TODO(b/202131100): Get the active list of configs using
+ // StatsManager#setActiveConfigsChangedOperation()
+ processStatsMetadata(
+ StatsLogProto.StatsdStatsReport.parseFrom(mStatsManager.getStatsMetadata()));
+
+ for (long configKey : getActiveConfigKeys()) {
+ processReport(configKey, StatsLogProto.ConfigMetricsReportList.parseFrom(
+ mStatsManager.getReports(configKey)));
+ }
+ } catch (InvalidProtocolBufferException | StatsUnavailableException e) {
+ // If the StatsD is not available, retry in the next pullReportsPeriodically call.
+ Slog.w(CarLog.TAG_TELEMETRY, e);
+ }
}
private List<Long> getActiveConfigKeys() {
@@ -330,11 +358,11 @@
/** Returns all the {@link TelemetryProto.MetricsConfig} associated with added subscribers. */
private List<TelemetryProto.MetricsConfig> getMetricsConfigs() {
- HashSet<TelemetryProto.MetricsConfig> failedConfigs = new HashSet<>();
+ HashSet<TelemetryProto.MetricsConfig> uniqueConfigs = new HashSet<>();
for (int i = 0; i < mConfigKeyToSubscribers.size(); i++) {
- failedConfigs.add(mConfigKeyToSubscribers.valueAt(i).getMetricsConfig());
+ uniqueConfigs.add(mConfigKeyToSubscribers.valueAt(i).getMetricsConfig());
}
- return new ArrayList<>(failedConfigs);
+ return new ArrayList<>(uniqueConfigs);
}
/**
@@ -435,12 +463,15 @@
.setId(configId)
.addAllowedLogSource("AID_SYSTEM");
- if (metric == TelemetryProto.StatsPublisher.SystemMetric.APP_START_MEMORY_STATE_CAPTURED) {
- return buildAppStartMemoryStateStatsdConfig(builder);
- } else if (metric == TelemetryProto.StatsPublisher.SystemMetric.PROCESS_MEMORY_STATE) {
- return buildProcessMemoryStateStatsdConfig(builder);
- } else {
- throw new IllegalArgumentException("Unsupported metric " + metric.name());
+ switch (metric) {
+ case APP_START_MEMORY_STATE_CAPTURED:
+ return buildAppStartMemoryStateStatsdConfig(builder);
+ case PROCESS_MEMORY_STATE:
+ return buildProcessMemoryStateStatsdConfig(builder);
+ case ACTIVITY_FOREGROUND_STATE_CHANGED:
+ return buildActivityForegroundStateStatsdConfig(builder);
+ default:
+ throw new IllegalArgumentException("Unsupported metric " + metric.name());
}
}
@@ -464,13 +495,13 @@
// The id must be unique within StatsdConfig/matchers
.setId(PROCESS_MEMORY_STATE_MATCHER_ID)
.setSimpleAtomMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(AtomsProto.Atom.PROCESS_MEMORY_STATE_FIELD_NUMBER)))
+ .setAtomId(PROCESS_MEMORY_STATE_FIELD_NUMBER)))
.addGaugeMetric(StatsdConfigProto.GaugeMetric.newBuilder()
// The id must be unique within StatsdConfig/metrics
.setId(PROCESS_MEMORY_STATE_GAUGE_METRIC_ID)
.setWhat(PROCESS_MEMORY_STATE_MATCHER_ID)
.setDimensionsInWhat(StatsdConfigProto.FieldMatcher.newBuilder()
- .setField(AtomsProto.Atom.PROCESS_MEMORY_STATE_FIELD_NUMBER)
+ .setField(PROCESS_MEMORY_STATE_FIELD_NUMBER)
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
.setField(1)) // ProcessMemoryState.uid
.addChild(StatsdConfigProto.FieldMatcher.newBuilder()
@@ -484,8 +515,23 @@
.setBucket(StatsdConfigProto.TimeUnit.FIVE_MINUTES)
)
.addPullAtomPackages(StatsdConfigProto.PullAtomPackages.newBuilder()
- .setAtomId(AtomsProto.Atom.PROCESS_MEMORY_STATE_FIELD_NUMBER)
+ .setAtomId(PROCESS_MEMORY_STATE_FIELD_NUMBER)
.addPackages("AID_SYSTEM"))
.build();
}
+
+ private static StatsdConfig buildActivityForegroundStateStatsdConfig(
+ StatsdConfig.Builder builder) {
+ return builder
+ .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder()
+ // The id must be unique within StatsdConfig/matchers
+ .setId(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID)
+ .setSimpleAtomMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder()
+ .setAtomId(ACTIVITY_FOREGROUND_STATE_CHANGED_FIELD_NUMBER)))
+ .addEventMetric(StatsdConfigProto.EventMetric.newBuilder()
+ // The id must be unique within StatsdConfig/metrics
+ .setId(ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID)
+ .setWhat(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID))
+ .build();
+ }
}
diff --git a/service/src/com/android/car/telemetry/publisher/AbstractAtomConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java
similarity index 99%
rename from service/src/com/android/car/telemetry/publisher/AbstractAtomConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java
index 869ab01..730b064 100644
--- a/service/src/com/android/car/telemetry/publisher/AbstractAtomConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/AbstractAtomConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.os.PersistableBundle;
import android.util.SparseArray;
diff --git a/service/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverter.java
new file mode 100644
index 0000000..dc7da9f
--- /dev/null
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ActivityForegroundStateChanged;
+import com.android.car.telemetry.AtomsProto.Atom;
+
+/**
+ * Atom data converter for atoms of type {@link ActivityForegroundStateChanged}.
+ */
+public class ActivityForegroundStateChangedConverter
+ extends AbstractAtomConverter<ActivityForegroundStateChanged> {
+ private static final SparseArray<
+ AtomFieldAccessor<ActivityForegroundStateChanged>> sAtomFieldAccessorMap =
+ new SparseArray<>();
+ static {
+ sAtomFieldAccessorMap.append(1, new AtomFieldAccessor<>(
+ "uid",
+ a -> a.hasUid(),
+ a -> a.getUid()
+ ));
+ sAtomFieldAccessorMap.append(2, new AtomFieldAccessor<>(
+ "pkg_name",
+ a -> a.hasPkgName(),
+ a -> a.getPkgName()
+ ));
+ sAtomFieldAccessorMap.append(3, new AtomFieldAccessor<>(
+ "class_name",
+ a -> a.hasClassName(),
+ a -> a.getClassName()
+ ));
+ sAtomFieldAccessorMap.append(4, new AtomFieldAccessor<>(
+ "state",
+ a -> a.hasState(),
+ a -> a.getState().getNumber()
+ ));
+ }
+
+ ActivityForegroundStateChangedConverter() {
+ super();
+ }
+
+ @Override
+ SparseArray<AtomFieldAccessor<ActivityForegroundStateChanged>> getAtomFieldAccessorMap() {
+ return sAtomFieldAccessorMap;
+ }
+
+ @Override
+ ActivityForegroundStateChanged getAtomData(Atom atom) {
+ return atom.getActivityForegroundStateChanged();
+ }
+
+ @Override
+ String getAtomDataClassName() {
+ return ActivityForegroundStateChanged.class.getSimpleName();
+ }
+}
diff --git a/service/src/com/android/car/telemetry/publisher/AppStartMemoryStateCapturedConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverter.java
similarity index 97%
rename from service/src/com/android/car/telemetry/publisher/AppStartMemoryStateCapturedConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverter.java
index d324e59..b8c554f 100644
--- a/service/src/com/android/car/telemetry/publisher/AppStartMemoryStateCapturedConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.util.SparseArray;
diff --git a/service/src/com/android/car/telemetry/publisher/AtomFieldAccessor.java b/service/src/com/android/car/telemetry/publisher/statsconverters/AtomFieldAccessor.java
similarity index 96%
rename from service/src/com/android/car/telemetry/publisher/AtomFieldAccessor.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/AtomFieldAccessor.java
index ec24b9c..9df25ec 100644
--- a/service/src/com/android/car/telemetry/publisher/AtomFieldAccessor.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/AtomFieldAccessor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import com.google.protobuf.MessageLite;
diff --git a/service/src/com/android/car/telemetry/publisher/AtomListConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java
similarity index 92%
rename from service/src/com/android/car/telemetry/publisher/AtomListConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java
index 69559d8..a854b3a 100644
--- a/service/src/com/android/car/telemetry/publisher/AtomListConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.os.PersistableBundle;
@@ -32,7 +32,9 @@
// Map of pushed atom cases to corresponding atom converter.
private static Map<Atom.PushedCase, AbstractAtomConverter> sPushedCaseConverters = Map.of(
Atom.PushedCase.APP_START_MEMORY_STATE_CAPTURED,
- new AppStartMemoryStateCapturedConverter());
+ new AppStartMemoryStateCapturedConverter(),
+ Atom.PushedCase.ACTIVITY_FOREGROUND_STATE_CHANGED,
+ new ActivityForegroundStateChangedConverter());
// Map of pulled atom cases to corresponding atom converter.
private static Map<Atom.PulledCase, AbstractAtomConverter> sPulledCaseConverters = Map.of(
diff --git a/service/src/com/android/car/telemetry/publisher/ConfigMetricsReportListConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/ConfigMetricsReportListConverter.java
similarity index 97%
rename from service/src/com/android/car/telemetry/publisher/ConfigMetricsReportListConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/ConfigMetricsReportListConverter.java
index 22a14f9..8e6f2b0 100644
--- a/service/src/com/android/car/telemetry/publisher/ConfigMetricsReportListConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/ConfigMetricsReportListConverter.java
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.os.PersistableBundle;
import com.android.car.telemetry.StatsLogProto;
+import com.android.car.telemetry.publisher.HashUtils;
import java.util.ArrayList;
import java.util.HashMap;
@@ -73,7 +74,7 @@
* @return a {@link PersistableBundle} containing mapping of metric id to metric data.
* @throws StatsConversionException if atom field mismatch or can't convert dimension value.
*/
- static Map<Long, PersistableBundle> convert(
+ public static Map<Long, PersistableBundle> convert(
StatsLogProto.ConfigMetricsReportList reportList) throws StatsConversionException {
// Map metric id to StatsLogReport list so that separate reports can be combined.
Map<Long, List<StatsLogProto.StatsLogReport>> metricsStatsReportMap = new HashMap<>();
diff --git a/service/src/com/android/car/telemetry/publisher/EventMetricDataConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java
similarity index 97%
rename from service/src/com/android/car/telemetry/publisher/EventMetricDataConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java
index 806ba71..52f9713 100644
--- a/service/src/com/android/car/telemetry/publisher/EventMetricDataConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.os.PersistableBundle;
diff --git a/service/src/com/android/car/telemetry/publisher/GaugeMetricDataConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java
similarity index 98%
rename from service/src/com/android/car/telemetry/publisher/GaugeMetricDataConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java
index 078d196..32a139c 100644
--- a/service/src/com/android/car/telemetry/publisher/GaugeMetricDataConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.os.PersistableBundle;
diff --git a/service/src/com/android/car/telemetry/publisher/ProcessMemoryStateConverter.java b/service/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverter.java
similarity index 97%
rename from service/src/com/android/car/telemetry/publisher/ProcessMemoryStateConverter.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverter.java
index 4af09b7..95b0b1d 100644
--- a/service/src/com/android/car/telemetry/publisher/ProcessMemoryStateConverter.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import android.util.SparseArray;
diff --git a/service/src/com/android/car/telemetry/publisher/StatsConversionException.java b/service/src/com/android/car/telemetry/publisher/statsconverters/StatsConversionException.java
similarity index 92%
rename from service/src/com/android/car/telemetry/publisher/StatsConversionException.java
rename to service/src/com/android/car/telemetry/publisher/statsconverters/StatsConversionException.java
index 5be3bb9..45f5bb5 100644
--- a/service/src/com/android/car/telemetry/publisher/StatsConversionException.java
+++ b/service/src/com/android/car/telemetry/publisher/statsconverters/StatsConversionException.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
/**
* Class for exceptions that occur when converting statsd data.
diff --git a/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorConstants.aidl b/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorConstants.aidl
deleted file mode 100644
index 52f4cbe..0000000
--- a/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorConstants.aidl
+++ /dev/null
@@ -1,45 +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.telemetry.scriptexecutorinterface;
-
-// TODO(b/194324369): Investigate if we could combine it
-// with IScriptExecutorListener.aidl
-
-interface IScriptExecutorConstants {
- /**
- * Default error type.
- */
- const int ERROR_TYPE_UNSPECIFIED = 0;
-
- /**
- * Used when an error occurs in the ScriptExecutor code.
- */
- const int ERROR_TYPE_SCRIPT_EXECUTOR_ERROR = 1;
-
- /**
- * Used when an error occurs while executing the Lua script (such as
- * errors returned by lua_pcall)
- */
- const int ERROR_TYPE_LUA_RUNTIME_ERROR = 2;
-
- /**
- * Used to log errors by a script itself, for instance, when a script received
- * inputs outside of expected range.
- */
- const int ERROR_TYPE_LUA_SCRIPT_ERROR = 3;
-}
-
diff --git a/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorListener.aidl b/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorListener.aidl
index dc64732..99fed2d 100644
--- a/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorListener.aidl
+++ b/service/src/com/android/car/telemetry/scriptexecutorinterface/IScriptExecutorListener.aidl
@@ -52,5 +52,33 @@
* @param stackTrace the stack trace of the error if available.
*/
void onError(int errorType, String message, @nullable String stackTrace);
+
+ /**
+ * Any changes to the following ERROR_TYPE_* constants must be also reflected in the following files:
+ * p/s/C/package/ScriptExecutor/src/ScriptExecutorListener.h
+ * p/s/C/service/src/com/android/car/telemetry/proto/telemetry.proto
+ */
+
+ /**
+ * Default error type.
+ */
+ const int ERROR_TYPE_UNSPECIFIED = 0;
+
+ /**
+ * Used when an error occurs in the ScriptExecutor code.
+ */
+ const int ERROR_TYPE_SCRIPT_EXECUTOR_ERROR = 1;
+
+ /**
+ * Used when an error occurs while executing the Lua script (such as
+ * errors returned by lua_pcall)
+ */
+ const int ERROR_TYPE_LUA_RUNTIME_ERROR = 2;
+
+ /**
+ * Used to log errors by a script itself, for instance, when a script received
+ * inputs outside of expected range.
+ */
+ const int ERROR_TYPE_LUA_SCRIPT_ERROR = 3;
}
diff --git a/service/src/com/android/car/watchdog/CarWatchdogService.java b/service/src/com/android/car/watchdog/CarWatchdogService.java
index 93243d4..318d132 100644
--- a/service/src/com/android/car/watchdog/CarWatchdogService.java
+++ b/service/src/com/android/car/watchdog/CarWatchdogService.java
@@ -77,6 +77,7 @@
"com.android.server.jobscheduler.GARAGE_MODE_ON";
static final String ACTION_GARAGE_MODE_OFF =
"com.android.server.jobscheduler.GARAGE_MODE_OFF";
+ static final int MISSING_ARG_VALUE = -1;
static final TimeSourceInterface SYSTEM_INSTANCE = new TimeSourceInterface() {
@Override
public Instant now() {
@@ -106,25 +107,15 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- boolean isGarageMode = false;
- if (action.equals(ACTION_GARAGE_MODE_ON)) {
- isGarageMode = true;
- } else if (!action.equals(ACTION_GARAGE_MODE_OFF)) {
- return;
- }
- if (isGarageMode) {
- mWatchdogStorage.shrinkDatabase();
- }
- try {
- mCarWatchdogDaemonHelper.notifySystemStateChange(StateType.GARAGE_MODE,
- isGarageMode ? GarageMode.GARAGE_MODE_ON : GarageMode.GARAGE_MODE_OFF,
- /* arg2= */ -1);
- if (DEBUG) {
- Slogf.d(TAG, "Notified car watchdog daemon of garage mode(%s)",
- isGarageMode ? "ON" : "OFF");
- }
- } catch (RemoteException | RuntimeException e) {
- Slogf.w(TAG, "Notifying garage mode state change failed: %s", e);
+ switch (action) {
+ case ACTION_GARAGE_MODE_ON:
+ case ACTION_GARAGE_MODE_OFF:
+ handleGarageModeIntent(action.equals(ACTION_GARAGE_MODE_ON));
+ break;
+ case Intent.ACTION_USER_REMOVED:
+ UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
+ mWatchdogPerfHandler.deleteUser(user.getIdentifier());
+ break;
}
}
};
@@ -361,6 +352,23 @@
mWatchdogPerfHandler.setTimeSource(timeSource);
}
+ private void handleGarageModeIntent(boolean isOn) {
+ if (isOn) {
+ mWatchdogStorage.shrinkDatabase();
+ }
+ try {
+ mCarWatchdogDaemonHelper.notifySystemStateChange(StateType.GARAGE_MODE,
+ isOn ? GarageMode.GARAGE_MODE_ON : GarageMode.GARAGE_MODE_OFF,
+ /* arg2= */ MISSING_ARG_VALUE);
+ if (DEBUG) {
+ Slogf.d(TAG, "Notified car watchdog daemon of garage mode(%s)",
+ isOn ? "ON" : "OFF");
+ }
+ } catch (RemoteException | RuntimeException e) {
+ Slogf.w(TAG, e, "Notifying garage mode state change failed");
+ }
+ }
+
private void postRegisterToDaemonMessage() {
CarServiceUtils.runOnMain(() -> {
synchronized (mLock) {
@@ -447,7 +455,7 @@
}
try {
mCarWatchdogDaemonHelper.notifySystemStateChange(StateType.POWER_CYCLE,
- powerCycle, /* arg2= */ -1);
+ powerCycle, /* arg2= */ MISSING_ARG_VALUE);
if (DEBUG) {
Slogf.d(TAG, "Notified car watchdog daemon of power cycle(%d)", powerCycle);
}
@@ -499,6 +507,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_GARAGE_MODE_ON);
filter.addAction(ACTION_GARAGE_MODE_OFF);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
mContext.registerReceiverForAllUsers(mBroadcastReceiver, filter, null, null);
}
diff --git a/service/src/com/android/car/watchdog/WatchdogPerfHandler.java b/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
index 6cf7794..956161b 100644
--- a/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
+++ b/service/src/com/android/car/watchdog/WatchdogPerfHandler.java
@@ -68,7 +68,6 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -401,12 +400,11 @@
}
private void setPackageKillableStateForAllUsers(String packageName, boolean isKillable) {
- UserManager userManager = UserManager.get(mContext);
- List<UserInfo> userInfos = userManager.getAliveUsers();
+ int[] userIds = getAliveUserIds();
String genericPackageName = null;
synchronized (mLock) {
- for (int i = 0; i < userInfos.size(); ++i) {
- int userId = userInfos.get(i).id;
+ for (int i = 0; i < userIds.length; ++i) {
+ int userId = userIds[i];
String name = mPackageInfoHandler.getNameForUserPackage(packageName, userId);
if (name == null) {
continue;
@@ -449,11 +447,10 @@
return getPackageKillableStatesForUserId(userHandle.getIdentifier(), pm);
}
List<PackageKillableState> packageKillableStates = new ArrayList<>();
- UserManager userManager = UserManager.get(mContext);
- List<UserInfo> userInfos = userManager.getAliveUsers();
- for (int i = 0; i < userInfos.size(); ++i) {
+ int[] userIds = getAliveUserIds();
+ for (int i = 0; i < userIds.length; ++i) {
packageKillableStates.addAll(
- getPackageKillableStatesForUserId(userInfos.get(i).id, pm));
+ getPackageKillableStatesForUserId(userIds[i], pm));
}
if (DEBUG) {
Slogf.d(TAG, "Returning all package killable states for all users");
@@ -749,6 +746,21 @@
}
}
+ /** Deletes all data for specific user. */
+ public void deleteUser(@UserIdInt int userId) {
+ synchronized (mLock) {
+ for (int i = mUsageByUserPackage.size() - 1; i >= 0; --i) {
+ if (userId == mUsageByUserPackage.valueAt(i).userId) {
+ mUsageByUserPackage.removeAt(i);
+ }
+ }
+ mWatchdogStorage.syncUsers(getAliveUserIds());
+ }
+ if (DEBUG) {
+ Slogf.d(TAG, "Resource usage for user id: %d was deleted.", userId);
+ }
+ }
+
/** Sets the time source. */
public void setTimeSource(TimeSourceInterface timeSource) {
synchronized (mLock) {
@@ -801,6 +813,7 @@
}
private void readFromDatabase() {
+ mWatchdogStorage.syncUsers(getAliveUserIds());
List<WatchdogStorage.UserPackageSettingsEntry> settingsEntries =
mWatchdogStorage.getUserPackageSettings();
Slogf.i(TAG, "Read %d user package settings from database", settingsEntries.size());
@@ -1225,6 +1238,17 @@
}
}
+ private int[] getAliveUserIds() {
+ UserManager userManager = UserManager.get(mContext);
+ List<UserHandle> aliveUsers = userManager.getUserHandles(/* excludeDying= */ true);
+ int userSize = aliveUsers.size();
+ int[] userIds = new int[userSize];
+ for (int i = 0; i < userSize; ++i) {
+ userIds[i] = aliveUsers.get(i).getIdentifier();
+ }
+ return userIds;
+ }
+
private static String getUserPackageUniqueId(int userId, String genericPackageName) {
return String.valueOf(userId) + ":" + genericPackageName;
}
diff --git a/service/src/com/android/car/watchdog/WatchdogStorage.java b/service/src/com/android/car/watchdog/WatchdogStorage.java
index 78b6927..42f6313 100644
--- a/service/src/com/android/car/watchdog/WatchdogStorage.java
+++ b/service/src/com/android/car/watchdog/WatchdogStorage.java
@@ -32,6 +32,7 @@
import android.os.Process;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.Slog;
import com.android.car.CarLog;
@@ -196,6 +197,25 @@
}
}
+ /**
+ * Deletes all user package settings and resource stats for all non-alive users.
+ *
+ * @param aliveUserIds Array of alive user ids.
+ */
+ public void syncUsers(int[] aliveUserIds) {
+ IntArray aliveUsers = IntArray.wrap(aliveUserIds);
+ for (int i = mUserPackagesByKey.size() - 1; i >= 0; --i) {
+ UserPackage userPackage = mUserPackagesByKey.valueAt(i);
+ if (aliveUsers.indexOf(userPackage.getUserId()) == -1) {
+ mUserPackagesByKey.removeAt(i);
+ mUserPackagesById.remove(userPackage.getUniqueId());
+ }
+ }
+ try (SQLiteDatabase db = mDbHelper.getWritableDatabase()) {
+ UserPackageSettingsTable.syncUserPackagesWithAliveUsers(db, aliveUsers);
+ }
+ }
+
@VisibleForTesting
boolean saveIoUsageStats(List<IoUsageStatsEntry> entries, boolean shouldCheckRetention) {
ZonedDateTime currentDate =
@@ -371,6 +391,24 @@
Slogf.i(TAG, "Deleted %d user package settings db rows for user %d and package %s",
deletedRows, userId, packageName);
}
+
+ public static void syncUserPackagesWithAliveUsers(SQLiteDatabase db, IntArray aliveUsers) {
+ StringBuilder queryBuilder = new StringBuilder();
+ for (int i = 0; i < aliveUsers.size(); ++i) {
+ if (i == 0) {
+ queryBuilder.append(COLUMN_USER_ID).append(" NOT IN (");
+ } else {
+ queryBuilder.append(", ");
+ }
+ queryBuilder.append(aliveUsers.get(i));
+ if (i == aliveUsers.size() - 1) {
+ queryBuilder.append(")");
+ }
+ }
+ int deletedRows = db.delete(TABLE_NAME, queryBuilder.toString(), new String[]{});
+ Slogf.i(TAG, "Deleted %d user package settings db rows while syncing with alive users",
+ deletedRows);
+ }
}
/** Defines the I/O usage entry stored in the IoUsageStatsTable. */
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml b/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml
index 3110d82..39c53fa 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/car_telemetry_test.xml
@@ -19,47 +19,64 @@
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
- android:id="@+id/on_gear_change_layout"
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/gear_change_config"/>
<Button
android:id="@+id/send_on_gear_change_config"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/send_on_gear_change"/>
+ android:text="@string/add_metrics_config"/>
<Button
android:id="@+id/remove_on_gear_change_config"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/remove_on_gear_change"/>
+ android:text="@string/remove_metrics_config"/>
<Button
android:id="@+id/get_on_gear_change_report"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/get_on_gear_change"/>
+ android:text="@string/get_report"/>
</LinearLayout>
<LinearLayout
- android:id="@+id/on_process_memory_state_layout"
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_memory_config"/>
<Button
android:id="@+id/send_on_process_memory_config"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/send_process_memory_state_config"/>
+ android:text="@string/add_metrics_config"/>
<Button
android:id="@+id/remove_on_process_memory_config"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/remove_process_memory_state_config"/>
+ android:text="@string/remove_metrics_config"/>
<Button
android:id="@+id/get_on_process_memory_report"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/get_report_process_memory_state_config"/>
+ 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"
+ android:layout_height="wrap_content"
+ android:text="@string/show_mem_info"/>
</LinearLayout>
<TextView
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml b/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml
index ed3f100..7aaa3e0 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/notification_fragment.xml
@@ -127,6 +127,16 @@
android:textSize="30sp"/>
<Button
+ android:id="@+id/category_long_message_same_person_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:background="#ffa9a8"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:text="Long message from same person"
+ android:textSize="30sp"/>
+
+ <Button
android:id="@+id/category_message_mute_action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
index 77e3989..4fcb9f3 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
@@ -383,10 +383,10 @@
<string name="cancel" translatable="false">Cancel</string>
<!-- CarTelemetryService Test -->
- <string name="send_on_gear_change" translatable="false">Send MetricsConfig on_gear_change</string>
- <string name="remove_on_gear_change" translatable="false">Remove MetricsConfig on_gear_change</string>
- <string name="get_on_gear_change" translatable="false">Get Report on_gear_change</string>
- <string name="send_process_memory_state_config" translatable="false">Send MetricsConfig process_memory</string>
- <string name="remove_process_memory_state_config" translatable="false">Remove MetricsConfig process_memory</string>
- <string name="get_report_process_memory_state_config" translatable="false">Get Report process_memory</string>
+ <string name="gear_change_config" translate="false">on_gear_change:</string>
+ <string name="process_memory_config" translate="false">process_memory:</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>
+ <string name="show_mem_info" translate="false">Show Memory Info</string>
</resources>
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java
index 9dbef65..f7378af 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/notification/NotificationFragment.java
@@ -95,6 +95,7 @@
initOngoingButton(view);
initMessagingStyleButtonForDiffPerson(view);
initMessagingStyleButtonForSamePerson(view);
+ initMessagingStyleButtonForLongMessageSamePerson(view);
initMessagingStyleButtonWithMuteAction(view);
initTestMessagesButton(view);
initProgressButton(view);
@@ -435,6 +436,54 @@
});
}
+ private void initMessagingStyleButtonForLongMessageSamePerson(View view) {
+ view.findViewById(R.id.category_long_message_same_person_button).setOnClickListener(v -> {
+ int id = mCurrentNotificationId++;
+
+ PendingIntent replyIntent = createServiceIntent(id, "reply");
+ PendingIntent markAsReadIntent = createServiceIntent(id, "read");
+
+
+
+ Person person = new Person.Builder().setName("John Doe").build();
+ MessagingStyle messagingStyle =
+ new MessagingStyle(person).setConversationTitle("Hello!");
+ NotificationCompat.Builder builder = new NotificationCompat
+ .Builder(mContext, IMPORTANCE_HIGH_ID)
+ .setContentTitle("Message from someone")
+ .setContentText("hi")
+ .setShowWhen(true)
+ .setCategory(Notification.CATEGORY_MESSAGE)
+ .setSmallIcon(R.drawable.car_ic_mode)
+ .setAutoCancel(true)
+ .setColor(mContext.getColor(android.R.color.holo_green_light))
+ .addAction(
+ new Action.Builder(R.drawable.ic_check_box, "read", markAsReadIntent)
+ .setSemanticAction(Action.SEMANTIC_ACTION_MARK_AS_READ)
+ .setShowsUserInterface(false)
+ .build())
+ .addAction(
+ new Action.Builder(R.drawable.ic_check_box, "reply", replyIntent)
+ .setSemanticAction(Action.SEMANTIC_ACTION_REPLY)
+ .setShowsUserInterface(false)
+ .addRemoteInput(new RemoteInput.Builder("input").build())
+ .build());
+
+ String messageText = "";
+ for (int i = 0; i < 100; i++) {
+ messageText += " test";
+ }
+
+ NotificationCompat.Builder updateNotification =
+ builder.setStyle(messagingStyle.addMessage(
+ new MessagingStyle.Message(
+ id + messageText,
+ System.currentTimeMillis(),
+ person)));
+ mManager.notify(12345, updateNotification.build());
+ });
+ }
+
private void initMessagingStyleButtonWithMuteAction(View view) {
view.findViewById(R.id.category_message_mute_action_button).setOnClickListener(v -> {
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 5a76abc..5f548ed 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
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.car.telemetry.CarTelemetryManager;
import android.car.telemetry.MetricsConfigKey;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
@@ -28,7 +29,6 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
@@ -41,6 +41,8 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -146,30 +148,30 @@
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.car_telemetry_test, container, false);
-
mOutputTextView = view.findViewById(R.id.output_textview);
- Button sendGearConfigBtn = view.findViewById(R.id.send_on_gear_change_config);
- Button getGearReportBtn = view.findViewById(R.id.get_on_gear_change_report);
- Button removeGearConfigBtn = view.findViewById(R.id.remove_on_gear_change_config);
-
- sendGearConfigBtn.setOnClickListener(this::onSendGearChangeConfigBtnClick);
- removeGearConfigBtn.setOnClickListener(this::onRemoveGearChangeConfigBtnClick);
- getGearReportBtn.setOnClickListener(this::onGetGearChangeReportBtnClick);
-
- mOutputTextView = view.findViewById(R.id.output_textview);
- Button sendProcessMemConfigBtn = view.findViewById(R.id.send_on_process_memory_config);
- Button getProcessMemReportBtn = view.findViewById(R.id.get_on_process_memory_report);
- Button removeProcessMemConfigBtn = view.findViewById(R.id.remove_on_process_memory_config);
-
- sendProcessMemConfigBtn.setOnClickListener(this::onSendProcessMemoryConfigBtnClick);
- removeProcessMemConfigBtn.setOnClickListener(this::onRemoveProcessMemoryConfigBtnClick);
- getProcessMemReportBtn.setOnClickListener(this::onGetProcessMemoryReportBtnClick);
-
+ view.findViewById(R.id.send_on_gear_change_config)
+ .setOnClickListener(this::onSendGearChangeConfigBtnClick);
+ view.findViewById(R.id.remove_on_gear_change_config)
+ .setOnClickListener(this::onRemoveGearChangeConfigBtnClick);
+ view.findViewById(R.id.get_on_gear_change_report)
+ .setOnClickListener(this::onGetGearChangeReportBtnClick);
+ view.findViewById(R.id.send_on_process_memory_config)
+ .setOnClickListener(this::onSendProcessMemoryConfigBtnClick);
+ view.findViewById(R.id.remove_on_process_memory_config)
+ .setOnClickListener(this::onRemoveProcessMemoryConfigBtnClick);
+ view.findViewById(R.id.get_on_process_memory_report)
+ .setOnClickListener(this::onGetProcessMemoryReportBtnClick);
+ view.findViewById(R.id.show_mem_info_btn).setOnClickListener(this::onShowMemInfoBtnClick);
return view;
}
private void showOutput(String s) {
- mActivity.runOnUiThread(() -> mOutputTextView.setText(s));
+ mActivity.runOnUiThread(() -> {
+ String now = LocalDateTime.now()
+ .format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS"));
+ mOutputTextView.setText(
+ now + " : " + s + "\n" + mOutputTextView.getText());
+ });
}
private void onSendGearChangeConfigBtnClick(View view) {
@@ -184,13 +186,13 @@
}
private void onGetGearChangeReportBtnClick(View view) {
- showOutput("Fetching report... If nothing shows up after a few seconds, "
- + "then no result exists");
+ showOutput("Fetching report for on_gear_change... If nothing shows up within 5 seconds, "
+ + "there is no result yet");
mCarTelemetryManager.sendFinishedReports(ON_GEAR_CHANGE_KEY_V1);
}
private void onSendProcessMemoryConfigBtnClick(View view) {
- showOutput("Sending MetricsConfig that listen for process memory state...");
+ showOutput("Sending MetricsConfig that listens for process memory state...");
mCarTelemetryManager.addMetricsConfig(PROCESS_MEMORY_KEY_V1,
METRICS_CONFIG_PROCESS_MEMORY_V1.toByteArray());
}
@@ -201,11 +203,27 @@
}
private void onGetProcessMemoryReportBtnClick(View view) {
- showOutput("Fetching report for process memory state... If nothing shows up after "
- + "a few seconds, then no result exists");
+ showOutput("Fetching report for process memory state... If nothing shows up within 5 "
+ + "seconds, there is no result yet");
mCarTelemetryManager.sendFinishedReports(PROCESS_MEMORY_KEY_V1);
}
+ /** Gets a MemoryInfo object for the device's current memory status. */
+ private ActivityManager.MemoryInfo getAvailableMemory() {
+ ActivityManager activityManager = getActivity().getSystemService(ActivityManager.class);
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ activityManager.getMemoryInfo(memoryInfo);
+ return memoryInfo;
+ }
+
+ private void onShowMemInfoBtnClick(View view) {
+ // Use android's "alloc-stress" system tool to create an artificial memory pressure.
+ ActivityManager.MemoryInfo info = getAvailableMemory();
+ showOutput("MemoryInfo availMem=" + (info.availMem / 1024 / 1024) + "/"
+ + (info.totalMem / 1024 / 1024) + "mb, isLowMem=" + info.lowMemory
+ + ", threshold=" + (info.threshold / 1024 / 1024) + "mb");
+ }
+
@Override
public void onDestroyView() {
super.onDestroyView();
@@ -227,7 +245,7 @@
} catch (IOException e) {
bundle = null;
}
- showOutput("Result is " + bundle.toString());
+ showOutput("Result for " + key.getName() + ": " + bundle.toString());
}
@Override
@@ -235,16 +253,34 @@
try {
TelemetryProto.TelemetryError telemetryError =
TelemetryProto.TelemetryError.parseFrom(error);
- showOutput("Error is " + telemetryError);
+ showOutput("Error for " + key.getName() + ": " + telemetryError);
} catch (InvalidProtocolBufferException e) {
showOutput("Unable to parse error result for MetricsConfig " + key.getName()
- + ". " + e.getMessage());
+ + ": " + e.getMessage());
}
}
@Override
public void onAddMetricsConfigStatus(@NonNull MetricsConfigKey key, int statusCode) {
- showOutput("Add MetricsConfig status: " + statusCode);
+ showOutput("Add MetricsConfig status for " + key.getName() + ": "
+ + statusCodeToString(statusCode));
+ }
+
+ private String statusCodeToString(int statusCode) {
+ switch (statusCode) {
+ case CarTelemetryManager.ERROR_METRICS_CONFIG_NONE:
+ return "SUCCESS";
+ case CarTelemetryManager.ERROR_METRICS_CONFIG_ALREADY_EXISTS:
+ return "ERROR ALREADY_EXISTS";
+ case CarTelemetryManager.ERROR_METRICS_CONFIG_VERSION_TOO_OLD:
+ return "ERROR VERSION_TOO_OLD";
+ case CarTelemetryManager.ERROR_METRICS_CONFIG_PARSE_FAILED:
+ return "ERROR PARSE_FAILED";
+ case CarTelemetryManager.ERROR_METRICS_CONFIG_SIGNATURE_VERIFICATION_FAILED:
+ return "ERROR SIGNATURE_VERIFICATION_FAILED";
+ default:
+ return "ERROR UNKNOWN";
+ }
}
}
}
diff --git a/tests/carservice_test/src/com/android/car/CarTelemetryManagerTest.java b/tests/carservice_test/src/com/android/car/CarTelemetryManagerTest.java
index 11181de..1a489d7 100644
--- a/tests/carservice_test/src/com/android/car/CarTelemetryManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarTelemetryManagerTest.java
@@ -101,6 +101,23 @@
}
@Test
+ public void testApiInvocationWithoutSettingListener() {
+ mCarTelemetryManager.clearListener();
+
+ assertThrows(IllegalStateException.class,
+ () -> mCarTelemetryManager.addMetricsConfig(
+ KEY_V1, METRICS_CONFIG_V1.toByteArray()));
+ assertThrows(IllegalStateException.class,
+ () -> mCarTelemetryManager.removeMetricsConfig(KEY_V1));
+ assertThrows(IllegalStateException.class,
+ () -> mCarTelemetryManager.removeAllMetricsConfigs());
+ assertThrows(IllegalStateException.class,
+ () -> mCarTelemetryManager.sendFinishedReports(KEY_V1));
+ assertThrows(IllegalStateException.class,
+ () -> mCarTelemetryManager.sendAllFinishedReports());
+ }
+
+ @Test
public void testAddMetricsConfig() throws Exception {
// invalid config, should fail
mCarTelemetryManager.addMetricsConfig(KEY_V1, INVALID_METRICS_CONFIG);
diff --git a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
index 4119b8c..4a02dab 100644
--- a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
+++ b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
@@ -559,7 +559,7 @@
}
@Override
- public void notifyPowerPolicyChange(String policyId) {
+ public void notifyPowerPolicyChange(String policyId, boolean force) {
// do nothing
}
diff --git a/tests/carservice_test/src/com/android/car/watchdog/CarWatchdogServiceTest.java b/tests/carservice_test/src/com/android/car/watchdog/CarWatchdogServiceTest.java
index ba01d41..9a24a7e 100644
--- a/tests/carservice_test/src/com/android/car/watchdog/CarWatchdogServiceTest.java
+++ b/tests/carservice_test/src/com/android/car/watchdog/CarWatchdogServiceTest.java
@@ -77,8 +77,8 @@
private final Executor mExecutor =
InstrumentationRegistry.getInstrumentation().getTargetContext().getMainExecutor();
private final UserInfo[] mUserInfos = new UserInfo[] {
- new UserInfoBuilder(10).setName("user 1").build(),
- new UserInfoBuilder(11).setName("user 2").build()
+ new UserInfoBuilder(100).setName("user 1").build(),
+ new UserInfoBuilder(101).setName("user 2").build()
};
@Mock private Context mMockContext;
@@ -101,8 +101,8 @@
when(mServiceBinder.queryLocalInterface(anyString())).thenReturn(mCarWatchdogService);
when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mockUmGetAllUsers(mUserManager, mUserInfos);
- mockUmIsUserRunning(mUserManager, 10, true);
- mockUmIsUserRunning(mUserManager, 11, false);
+ mockUmIsUserRunning(mUserManager, 100, true);
+ mockUmIsUserRunning(mUserManager, 101, false);
mCarWatchdogService.init();
mWatchdogServiceForSystemImpl = registerCarWatchdogService();
@@ -224,11 +224,11 @@
}
private void expectRunningUser() {
- doReturn(10).when(() -> UserHandle.getUserId(Binder.getCallingUid()));
+ doReturn(100).when(() -> UserHandle.getUserId(Binder.getCallingUid()));
}
private void expectStoppedUser() {
- doReturn(11).when(() -> UserHandle.getUserId(Binder.getCallingUid()));
+ doReturn(101).when(() -> UserHandle.getUserId(Binder.getCallingUid()));
}
private final class TestClient {
diff --git a/tests/carservice_unit_test/src/com/android/car/hal/MockedPowerHalService.java b/tests/carservice_unit_test/src/com/android/car/hal/MockedPowerHalService.java
index 2ab14dc..fd15435 100644
--- a/tests/carservice_unit_test/src/com/android/car/hal/MockedPowerHalService.java
+++ b/tests/carservice_unit_test/src/com/android/car/hal/MockedPowerHalService.java
@@ -49,6 +49,7 @@
mock(UserHalService.class),
mock(DiagnosticHalService.class),
mock(ClusterHalService.class),
+ mock(TimeHalService.class),
mock(HalClient.class),
CarServiceUtils.getHandlerThread(VehicleHal.class.getSimpleName()));
return mockedVehicleHal;
diff --git a/tests/carservice_unit_test/src/com/android/car/hal/TimeHalServiceTest.java b/tests/carservice_unit_test/src/com/android/car/hal/TimeHalServiceTest.java
new file mode 100644
index 0000000..adc5153
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/hal/TimeHalServiceTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.hal;
+
+import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.EPOCH_TIME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.verify;
+
+import android.car.test.util.BroadcastingFakeContext;
+import android.car.test.util.VehicleHalTestingHelper;
+import android.content.Intent;
+import android.hardware.automotive.vehicle.V2_0.VehicleArea;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyStatus;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Collections;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class TimeHalServiceTest {
+
+ private static final VehiclePropConfig ANDROID_TIME_PROP =
+ VehicleHalTestingHelper.newConfig(EPOCH_TIME);
+
+ @Mock private VehicleHal mVehicleHal;
+ private BroadcastingFakeContext mFakeContext;
+
+ private TimeHalService mTimeHalService;
+
+ @Before
+ public void setUp() {
+ mFakeContext = new BroadcastingFakeContext();
+ mTimeHalService = new TimeHalService(mFakeContext, mVehicleHal);
+ }
+
+ @Test
+ public void testInitDoesNothing() {
+ mTimeHalService.takeProperties(Collections.emptyList());
+
+ mTimeHalService.init();
+
+ mFakeContext.verifyReceiverNotRegistered();
+ }
+
+ @Test
+ public void testInitRegistersBroadcastReceiver() {
+ mTimeHalService.takeProperties(Collections.singletonList(ANDROID_TIME_PROP));
+
+ mTimeHalService.init();
+
+ assertThat(mTimeHalService.isAndroidTimeSupported()).isTrue();
+ mFakeContext.verifyReceiverRegistered(Intent.ACTION_TIME_CHANGED);
+ }
+
+ @Test
+ public void testInitSendsAndroidTimeUpdate() {
+ mTimeHalService.takeProperties(Collections.singletonList(ANDROID_TIME_PROP));
+ long sysTimeMillis = System.currentTimeMillis();
+
+ mTimeHalService.init();
+
+ assertThat(mTimeHalService.isAndroidTimeSupported()).isTrue();
+ ArgumentCaptor<VehiclePropValue> captor = ArgumentCaptor.forClass(VehiclePropValue.class);
+ verify(mVehicleHal).set(captor.capture());
+ VehiclePropValue propValue = captor.getValue();
+ assertThat(propValue.prop).isEqualTo(EPOCH_TIME);
+ assertThat(propValue.areaId).isEqualTo(VehicleArea.GLOBAL);
+ assertThat(propValue.status).isEqualTo(VehiclePropertyStatus.AVAILABLE);
+ assertThat(propValue.timestamp).isAtLeast(sysTimeMillis);
+ assertThat(propValue.value.int64Values).hasSize(1);
+ assertThat(propValue.value.int64Values.get(0)).isAtLeast(sysTimeMillis);
+ }
+
+ @Test
+ public void testReleaseUnregistersBroadcastReceiver() {
+ mTimeHalService.takeProperties(Collections.singletonList(ANDROID_TIME_PROP));
+ mTimeHalService.init();
+ clearInvocations(mVehicleHal);
+
+ mTimeHalService.release();
+
+ mFakeContext.verifyReceiverNotRegistered();
+ assertThat(mTimeHalService.isAndroidTimeSupported()).isFalse();
+ }
+
+ @Test
+ public void testSendsAndroidTimeUpdateWhenBroadcast() {
+ mTimeHalService.takeProperties(Collections.singletonList(ANDROID_TIME_PROP));
+ mTimeHalService.init();
+ clearInvocations(mVehicleHal);
+ long sysTimeMillis = System.currentTimeMillis();
+
+ mFakeContext.sendBroadcast(new Intent(Intent.ACTION_TIME_CHANGED));
+
+ ArgumentCaptor<VehiclePropValue> captor = ArgumentCaptor.forClass(VehiclePropValue.class);
+ verify(mVehicleHal).set(captor.capture());
+ VehiclePropValue propValue = captor.getValue();
+ assertThat(propValue.prop).isEqualTo(EPOCH_TIME);
+ assertThat(propValue.areaId).isEqualTo(VehicleArea.GLOBAL);
+ assertThat(propValue.status).isEqualTo(VehiclePropertyStatus.AVAILABLE);
+ assertThat(propValue.timestamp).isAtLeast(sysTimeMillis);
+ assertThat(propValue.value.int64Values).hasSize(1);
+ assertThat(propValue.value.int64Values.get(0)).isAtLeast(sysTimeMillis);
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/hal/VehicleHalTest.java b/tests/carservice_unit_test/src/com/android/car/hal/VehicleHalTest.java
index 4aa9a81..2a39046 100644
--- a/tests/carservice_unit_test/src/com/android/car/hal/VehicleHalTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/hal/VehicleHalTest.java
@@ -71,6 +71,7 @@
@Mock private UserHalService mUserHalService;
@Mock private DiagnosticHalService mDiagnosticHalService;
@Mock private ClusterHalService mClusterHalService;
+ @Mock private TimeHalService mTimeHalService;
@Mock private HalClient mHalClient;
private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
@@ -86,7 +87,8 @@
public void setUp() throws Exception {
mVehicleHal = new VehicleHal(mPowerHalService,
mPropertyHalService, mInputHalService, mVmsHalService, mUserHalService,
- mDiagnosticHalService, mClusterHalService, mHalClient, mHandlerThread);
+ mDiagnosticHalService, mClusterHalService, mTimeHalService, mHalClient,
+ mHandlerThread);
mConfigs.clear();
diff --git a/tests/carservice_unit_test/src/com/android/car/power/CarPowerManagementServiceUnitTest.java b/tests/carservice_unit_test/src/com/android/car/power/CarPowerManagementServiceUnitTest.java
index 1ad6b7e..9698f12 100644
--- a/tests/carservice_unit_test/src/com/android/car/power/CarPowerManagementServiceUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/power/CarPowerManagementServiceUnitTest.java
@@ -883,7 +883,7 @@
}
@Override
- public void notifyPowerPolicyChange(String policyId) {
+ public void notifyPowerPolicyChange(String policyId, boolean force) {
mLastNofitiedPolicyId = policyId;
}
diff --git a/tests/carservice_unit_test/src/com/android/car/power/SilentModeHandlerUnitTest.java b/tests/carservice_unit_test/src/com/android/car/power/SilentModeHandlerUnitTest.java
index 6c3637b..2be3075 100644
--- a/tests/carservice_unit_test/src/com/android/car/power/SilentModeHandlerUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/power/SilentModeHandlerUnitTest.java
@@ -71,11 +71,11 @@
writeStringToFile(mFileHwStateMonitoring.getFile(), VALUE_SILENT_MODE);
- assertSilentMode(handler, /* expectedMode= */ true);
+ assertSilentMode(handler, /* isForcedMode= */ false, /* expectedMode= */ true);
writeStringToFile(mFileHwStateMonitoring.getFile(), VALUE_NON_SILENT_MODE);
- assertSilentMode(handler, /* expectedMode= */ false);
+ assertSilentMode(handler, /* isForcedMode= */ false, /* expectedMode= */ false);
}
@Test
@@ -169,14 +169,14 @@
writeStringToFile(mFileHwStateMonitoring.getFile(),
initSilentMode ? VALUE_SILENT_MODE : VALUE_NON_SILENT_MODE);
- assertSilentMode(handler, initSilentMode);
+ assertSilentMode(handler, /* isForcedMode= */ false, initSilentMode);
handler.setSilentMode(expectedSilentMode ? SilentModeHandler.SILENT_MODE_FORCED_SILENT
: SilentModeHandler.SILENT_MODE_FORCED_NON_SILENT);
writeStringToFile(mFileHwStateMonitoring.getFile(),
- expectedSilentMode ? VALUE_SILENT_MODE : VALUE_NON_SILENT_MODE);
+ expectedSilentMode ? VALUE_NON_SILENT_MODE : VALUE_SILENT_MODE);
- assertSilentMode(handler, expectedSilentMode);
+ assertSilentMode(handler, /* isForcedMode= */ true, expectedSilentMode);
}
private void testSetSilentMode_toNonForced(boolean initSilentMode) throws Exception {
@@ -191,7 +191,7 @@
writeStringToFile(mFileHwStateMonitoring.getFile(),
initSilentMode ? VALUE_NON_SILENT_MODE : VALUE_SILENT_MODE);
- assertSilentMode(handler, !initSilentMode);
+ assertSilentMode(handler, /* isForcedMode= */ false, !initSilentMode);
verify(mCarPowerManagementService, timeout(BUFFER_TIME_TO_AVOID_RACE_CONDITION))
.notifySilentModeChange(!initSilentMode);
}
@@ -212,12 +212,13 @@
}
}
- private void assertSilentMode(SilentModeHandler handler, boolean expectedMode)
- throws Exception {
+ private void assertSilentMode(SilentModeHandler handler, boolean isForcedMode,
+ boolean expectedMode) throws Exception {
String expectedValue = expectedMode ? VALUE_SILENT_MODE : VALUE_NON_SILENT_MODE;
for (int i = 0; i < MAX_POLLING_TRIES; i++) {
String contents = readFileAsString(mFileKernelSilentMode.getPath());
- if (handler.isSilentMode() == expectedMode && contents.equals(expectedValue)) {
+ if (handler.isSilentMode() == expectedMode
+ && (isForcedMode || contents.equals(expectedValue))) {
return;
}
SystemClock.sleep(POLLING_DELAY_MS);
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 da35258..25076a1 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
@@ -16,10 +16,14 @@
package com.android.car.telemetry.publisher;
+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_MEMORY_STATE_FIELD_NUMBER;
+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_MEMORY_STATE;
+import static com.android.car.telemetry.publisher.StatsPublisher.ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID;
+import static com.android.car.telemetry.publisher.StatsPublisher.ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID;
import static com.android.car.telemetry.publisher.StatsPublisher.APP_START_MEMORY_STATE_CAPTURED_ATOM_MATCHER_ID;
import static com.android.car.telemetry.publisher.StatsPublisher.APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID;
import static com.android.car.telemetry.publisher.StatsPublisher.PROCESS_MEMORY_STATE_FIELDS_MATCHER;
@@ -31,6 +35,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -39,6 +45,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.SystemClock;
import com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured;
@@ -86,6 +93,11 @@
.setStats(TelemetryProto.StatsPublisher.newBuilder()
.setSystemMetric(PROCESS_MEMORY_STATE))
.build();
+ private static final TelemetryProto.Publisher STATS_PUBLISHER_PARAMS_3 =
+ TelemetryProto.Publisher.newBuilder()
+ .setStats(TelemetryProto.StatsPublisher.newBuilder()
+ .setSystemMetric(ACTIVITY_FOREGROUND_STATE_CHANGED))
+ .build();
private static final TelemetryProto.Subscriber SUBSCRIBER_1 =
TelemetryProto.Subscriber.newBuilder()
.setHandler("handler_fn_1")
@@ -96,17 +108,25 @@
.setHandler("handler_fn_2")
.setPublisher(STATS_PUBLISHER_PARAMS_2)
.build();
+ private static final TelemetryProto.Subscriber SUBSCRIBER_3 =
+ TelemetryProto.Subscriber.newBuilder()
+ .setHandler("handler_fn_3")
+ .setPublisher(STATS_PUBLISHER_PARAMS_3)
+ .build();
private static final TelemetryProto.MetricsConfig METRICS_CONFIG =
TelemetryProto.MetricsConfig.newBuilder()
.setName("myconfig")
.setVersion(1)
.addSubscribers(SUBSCRIBER_1)
.addSubscribers(SUBSCRIBER_2)
+ .addSubscribers(SUBSCRIBER_3)
.build();
- private static final long SUBSCRIBER_1_HASH = -8101507323446050791L; // Used as ID.
- private static final long SUBSCRIBER_2_HASH = 2778197004730583271L; // Used as ID.
+ private static final long SUBSCRIBER_1_HASH = -8101507323446050791L; // Used as configKey.
+ private static final long SUBSCRIBER_2_HASH = 2778197004730583271L; // Used as configKey.
+ private static final long SUBSCRIBER_3_HASH = 7046592220837963576L; // Used as configKey.
+ // This StatsdConfig is generated for SUBSCRIBER_1.
private static final StatsdConfigProto.StatsdConfig STATSD_CONFIG_1 =
StatsdConfigProto.StatsdConfig.newBuilder()
.setId(SUBSCRIBER_1_HASH)
@@ -122,6 +142,7 @@
.addAllowedLogSource("AID_SYSTEM")
.build();
+ // This StatsdConfig is generated for SUBSCRIBER_2.
private static final StatsdConfigProto.StatsdConfig STATSD_CONFIG_2 =
StatsdConfigProto.StatsdConfig.newBuilder()
.setId(SUBSCRIBER_2_HASH)
@@ -153,6 +174,23 @@
.addPackages("AID_SYSTEM"))
.build();
+ // This StatsdConfig is generated for SUBSCRIBER_3.
+ private static final StatsdConfigProto.StatsdConfig STATSD_CONFIG_3 =
+ StatsdConfigProto.StatsdConfig.newBuilder()
+ .setId(SUBSCRIBER_3_HASH)
+ .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder()
+ .setId(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID)
+ .setSimpleAtomMatcher(
+ StatsdConfigProto.SimpleAtomMatcher.newBuilder()
+ .setAtomId(
+ ACTIVITY_FOREGROUND_STATE_CHANGED_FIELD_NUMBER)
+ ))
+ .addEventMetric(StatsdConfigProto.EventMetric.newBuilder()
+ .setId(ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID)
+ .setWhat(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID))
+ .addAllowedLogSource("AID_SYSTEM")
+ .build();
+
private static final EventMetricData EVENT_DATA =
EventMetricData.newBuilder()
.setElapsedTimestampNanos(99999999L)
@@ -175,7 +213,7 @@
.setValueInt(234))
.build();
- private static final StatsLogProto.ConfigMetricsReportList STATS_REPORT =
+ private static final StatsLogProto.ConfigMetricsReportList METRICS_REPORT =
StatsLogProto.ConfigMetricsReportList.newBuilder()
.addReports(ConfigMetricsReport.newBuilder()
.addMetrics(StatsLogReport.newBuilder()
@@ -195,7 +233,22 @@
.setField(1))))))
.build();
- private static final StatsLogProto.ConfigMetricsReportList EMPTY_STATS_REPORT =
+ // By default the test assumes all the StatsdConfigs are valid.
+ private static final StatsLogProto.StatsdStatsReport CONFIG_STATS_REPORT =
+ StatsLogProto.StatsdStatsReport.newBuilder()
+ .addConfigStats(StatsLogProto.StatsdStatsReport.ConfigStats.newBuilder()
+ // in unit tests UID of test and app are the same
+ .setUid(Process.myUid())
+ .setId(SUBSCRIBER_1_HASH) // id is the same as configKey
+ .setIsValid(true))
+ .addConfigStats(StatsLogProto.StatsdStatsReport.ConfigStats.newBuilder()
+ // in unit tests UID of test and app are the same
+ .setUid(Process.myUid())
+ .setId(SUBSCRIBER_2_HASH) // id is the same as configKey
+ .setIsValid(true))
+ .build();
+
+ private static final StatsLogProto.ConfigMetricsReportList EMPTY_METRICS_REPORT =
StatsLogProto.ConfigMetricsReportList.newBuilder().build();
private static final DataSubscriber DATA_SUBSCRIBER_1 =
@@ -219,6 +272,7 @@
public void setUp() throws Exception {
mRootDirectory = Files.createTempDirectory("telemetry_test").toFile();
mPublisher = createRestartedPublisher();
+ when(mStatsManager.getStatsMetadata()).thenReturn(CONFIG_STATS_REPORT.toByteArray());
}
/**
@@ -278,6 +332,19 @@
}
@Test
+ public void testAddDataSubscriber_forActivityForegroundState_generatesStatsdMetrics()
+ throws Exception {
+ DataSubscriber activityForegroundStateSubscriber =
+ new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_3);
+
+ mPublisher.addDataSubscriber(activityForegroundStateSubscriber);
+
+ verify(mStatsManager, times(1))
+ .addConfig(SUBSCRIBER_3_HASH, STATSD_CONFIG_3.toByteArray());
+ assertThat(mPublisher.hasDataSubscriber(activityForegroundStateSubscriber)).isTrue();
+ }
+
+ @Test
public void testRemoveDataSubscriber_removesFromStatsd() throws Exception {
mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1);
@@ -355,7 +422,7 @@
public void testAfterDispatchItSchedulesANewPullReportTask() throws Exception {
mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1);
Message firstMessage = mFakeHandlerWrapper.getQueuedMessages().get(0);
- when(mStatsManager.getReports(anyLong())).thenReturn(EMPTY_STATS_REPORT.toByteArray());
+ when(mStatsManager.getReports(anyLong())).thenReturn(EMPTY_METRICS_REPORT.toByteArray());
mFakeHandlerWrapper.dispatchQueuedMessages();
@@ -378,7 +445,7 @@
when(subscriber2.getMetricsConfig()).thenReturn(METRICS_CONFIG);
when(subscriber2.getPublisherParam()).thenReturn(SUBSCRIBER_2.getPublisher());
mPublisher.addDataSubscriber(subscriber2);
- when(mStatsManager.getReports(anyLong())).thenReturn(STATS_REPORT.toByteArray());
+ when(mStatsManager.getReports(anyLong())).thenReturn(METRICS_REPORT.toByteArray());
mFakeHandlerWrapper.dispatchQueuedMessages();
@@ -398,7 +465,28 @@
.asList().containsExactly(445678901L);
}
- // TODO(b/199211673): add test case when StatsdConfig is invalid and StatsPublisher fails.
+ @Test
+ public void testOnInvalidConfig_notifiesPublisherFailureListener() throws Exception {
+ DataSubscriber subscriber = spy(new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_1));
+ mPublisher.addDataSubscriber(subscriber);
+ reset(mStatsManager);
+ when(mStatsManager.getStatsMetadata()).thenReturn(
+ StatsLogProto.StatsdStatsReport.newBuilder()
+ .addConfigStats(StatsLogProto.StatsdStatsReport.ConfigStats.newBuilder()
+ // in unit tests UID of test and app are the same
+ .setUid(Process.myUid())
+ .setId(SUBSCRIBER_1_HASH) // id is the same as configKey
+ .setIsValid(false))
+ .build().toByteArray());
+ when(mStatsManager.getReports(anyLong())).thenReturn(EMPTY_METRICS_REPORT.toByteArray());
+
+ mFakeHandlerWrapper.dispatchQueuedMessages();
+
+ // subscriber shouldn't get data, because of EMPTY_METRICS_REPORT.
+ verify(subscriber, times(0)).push(any());
+ assertThat(mFailedConfigs).containsExactly(METRICS_CONFIG);
+ assertThat(mPublisherFailure).hasMessageThat().contains("Found invalid configs");
+ }
private PersistableBundle getSavedStatsConfigs() throws Exception {
File savedConfigsFile = new File(mRootDirectory, StatsPublisher.SAVED_STATS_CONFIGS_FILE);
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
new file mode 100644
index 0000000..98a0925
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ActivityForegroundStateChangedConverterTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.ActivityForegroundStateChanged.CLASS_NAME_FIELD_NUMBER;
+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.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.ActivityForegroundStateChanged;
+import com.android.car.telemetry.AtomsProto.ActivityForegroundStateChanged.State;
+import com.android.car.telemetry.AtomsProto.Atom;
+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 ActivityForegroundStateChangedConverterTest {
+ private static final Atom ATOM_A =
+ Atom.newBuilder()
+ .setActivityForegroundStateChanged(ActivityForegroundStateChanged.newBuilder()
+ .setClassName("className1")
+ .setState(State.BACKGROUND))
+ .build();
+
+ private static final Atom ATOM_B =
+ Atom.newBuilder()
+ .setActivityForegroundStateChanged(ActivityForegroundStateChanged.newBuilder()
+ .setClassName("className2")
+ .setState(State.FOREGROUND))
+ .build();
+
+ private static final Atom ATOM_MISMATCH =
+ Atom.newBuilder()
+ .setActivityForegroundStateChanged(ActivityForegroundStateChanged.newBuilder()
+ // Some fields are not set, creating mismatch with above atoms
+ .setClassName("className2"))
+ .build();
+
+ private static final List<Integer> DIM_FIELDS_IDS = Arrays.asList(1, 2);
+ private static final Long HASH_1 = HashUtils.murmur2Hash64("package.name.1");
+ private static final Long HASH_2 = HashUtils.murmur2Hash64("package.name.2");
+ private static final Map<Long, String> HASH_STR_MAP = Map.of(
+ HASH_1, "package.name.1",
+ HASH_2, "package.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 ActivityForegroundStateChangedConverter mConverter =
+ new ActivityForegroundStateChangedConverter();
+
+ @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<ActivityForegroundStateChanged>> 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(PKG_NAME_FIELD_NUMBER).getFieldName())))
+ .containsExactly("package.name.1", "package.name.2").inOrder();
+ assertThat(Arrays.asList(
+ bundle.getStringArray(accessorMap.get(CLASS_NAME_FIELD_NUMBER).getFieldName())))
+ .containsExactly("className1", "className2").inOrder();
+ assertThat(bundle.getIntArray(accessorMap.get(STATE_FIELD_NUMBER).getFieldName()))
+ .asList().containsExactly(0, 1).inOrder(); // States background=0 and foreground=1
+ }
+
+ @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/AppStartMemoryStateCapturedConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java
similarity index 71%
rename from tests/carservice_unit_test/src/com/android/car/telemetry/publisher/AppStartMemoryStateCapturedConverterTest.java
rename to tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java
index 0a235c6..1579e00 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/AppStartMemoryStateCapturedConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AppStartMemoryStateCapturedConverterTest.java
@@ -14,7 +14,16 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
+
+import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.ACTIVITY_NAME_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.CACHE_IN_BYTES_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.PAGE_FAULT_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.PAGE_MAJOR_FAULT_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured.PROCESS_NAME_FIELD_NUMBER;
+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.google.common.truth.Truth.assertThat;
@@ -26,13 +35,13 @@
import com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured;
import com.android.car.telemetry.AtomsProto.Atom;
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.HashMap;
import java.util.List;
import java.util.Map;
@@ -73,11 +82,9 @@
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 = new HashMap<>();
- static {
- HASH_STR_MAP.put(HASH_1, "process.name.1");
- HASH_STR_MAP.put(HASH_2, "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(
@@ -95,35 +102,41 @@
// Wrong format since leaf level dimension value should set value, not field
DimensionsValue.newBuilder().setField(3).build());
+ // Subject of the test.
+ private AppStartMemoryStateCapturedConverter mConverter =
+ new AppStartMemoryStateCapturedConverter();
+
@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);
- AppStartMemoryStateCapturedConverter converter =
- new AppStartMemoryStateCapturedConverter();
- SparseArray<AtomFieldAccessor<AppStartMemoryStateCaptured>> accessorMap =
- converter.getAtomFieldAccessorMap();
- PersistableBundle bundle = converter.convert(atomsList, DIM_FIELDS_IDS,
+ SparseArray<AtomFieldAccessor<AppStartMemoryStateCaptured>> accessorMap =
+ mConverter.getAtomFieldAccessorMap();
+
+ PersistableBundle bundle = mConverter.convert(atomsList, DIM_FIELDS_IDS,
dimensionsValuesList, HASH_STR_MAP);
assertThat(bundle.size()).isEqualTo(8);
- assertThat(bundle.getIntArray(accessorMap.get(1).getFieldName()))
+ assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 2000).inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(2).getFieldName())))
+ assertThat(Arrays.asList(
+ bundle.getStringArray(accessorMap.get(PROCESS_NAME_FIELD_NUMBER).getFieldName())))
.containsExactly("process.name.1", "process.name.2").inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(3).getFieldName())))
+ assertThat(Arrays.asList(
+ bundle.getStringArray(accessorMap.get(ACTIVITY_NAME_FIELD_NUMBER).getFieldName())))
.containsExactly("activityName1", "activityName2").inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(4).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(PAGE_FAULT_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(59L, 99L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(5).getFieldName()))
+ assertThat(bundle.getLongArray(
+ accessorMap.get(PAGE_MAJOR_FAULT_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(34L, 55L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(6).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(RSS_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1234L, 2345L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(7).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(CACHE_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(234L, 345L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(8).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(SWAP_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(111L, 222L).inOrder();
}
@@ -132,12 +145,9 @@
List<Atom> atomsList = Arrays.asList(ATOM_A, ATOM_MISMATCH);
List<List<DimensionsValue>> dimensionsValuesList = Arrays.asList(DV_PAIR_A, DV_PAIR_B);
- AppStartMemoryStateCapturedConverter converter =
- new AppStartMemoryStateCapturedConverter();
-
assertThrows(
StatsConversionException.class,
- () -> converter.convert(
+ () -> mConverter.convert(
atomsList,
DIM_FIELDS_IDS,
dimensionsValuesList,
@@ -150,12 +160,9 @@
List<List<DimensionsValue>> dimensionsValuesList =
Arrays.asList(DV_PAIR_A, DV_PAIR_MALFORMED);
- AppStartMemoryStateCapturedConverter converter =
- new AppStartMemoryStateCapturedConverter();
-
assertThrows(
StatsConversionException.class,
- () -> converter.convert(
+ () -> mConverter.convert(
atomsList,
DIM_FIELDS_IDS,
dimensionsValuesList,
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/AtomListConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java
similarity index 80%
rename from tests/carservice_unit_test/src/com/android/car/telemetry/publisher/AtomListConverterTest.java
rename to tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java
index 74408a8..a8cc426 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/AtomListConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/AtomListConverterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import static com.google.common.truth.Truth.assertThat;
@@ -59,11 +59,16 @@
PersistableBundle bundle = AtomListConverter.convert(pushedAtomsList, null, null, null);
assertThat(bundle.size()).isEqualTo(3);
- assertThat(bundle.getIntArray(accessorMap.get(1).getFieldName()))
+ assertThat(bundle.getIntArray(
+ accessorMap.get(AppStartMemoryStateCaptured.UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 1100).inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(3).getFieldName())))
+ assertThat(Arrays.asList(bundle.getStringArray(
+ accessorMap.get(AppStartMemoryStateCaptured.ACTIVITY_NAME_FIELD_NUMBER)
+ .getFieldName())))
.containsExactly("activityName1", "activityName2").inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(6).getFieldName()))
+ assertThat(bundle.getLongArray(
+ accessorMap.get(AppStartMemoryStateCaptured.RSS_IN_BYTES_FIELD_NUMBER)
+ .getFieldName()))
.asList().containsExactly(1234L, 2345L).inOrder();
}
@@ -90,11 +95,14 @@
PersistableBundle bundle = AtomListConverter.convert(pulledAtomsList, null, null, null);
assertThat(bundle.size()).isEqualTo(3);
- assertThat(bundle.getIntArray(accessorMap.get(1).getFieldName()))
+ assertThat(bundle.getIntArray(
+ accessorMap.get(ProcessMemoryState.UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 1100).inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(2).getFieldName())))
+ assertThat(Arrays.asList(bundle.getStringArray(
+ accessorMap.get(ProcessMemoryState.PROCESS_NAME_FIELD_NUMBER).getFieldName())))
.containsExactly("processName1", "processName2").inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(6).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(
+ ProcessMemoryState.RSS_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1234L, 2345L).inOrder();
}
}
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/ConfigMetricsReportListConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ConfigMetricsReportListConverterTest.java
similarity index 83%
rename from tests/carservice_unit_test/src/com/android/car/telemetry/publisher/ConfigMetricsReportListConverterTest.java
rename to tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ConfigMetricsReportListConverterTest.java
index dbbd51c..8d71b63 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/ConfigMetricsReportListConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ConfigMetricsReportListConverterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
import static com.google.common.truth.Truth.assertThat;
@@ -32,6 +32,7 @@
import com.android.car.telemetry.StatsLogProto.GaugeBucketInfo;
import com.android.car.telemetry.StatsLogProto.GaugeMetricData;
import com.android.car.telemetry.StatsLogProto.StatsLogReport;
+import com.android.car.telemetry.publisher.HashUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -103,19 +104,28 @@
assertThat(new ArrayList<Long>(map.keySet())).containsExactly(12345L, 23456L);
assertThat(eventBundle.getLongArray(EventMetricDataConverter.ELAPSED_TIME_NANOS))
.asList().containsExactly(99999999L);
- assertThat(eventBundle.getIntArray(appMemAccessorMap.get(1).getFieldName()))
+ assertThat(eventBundle.getIntArray(
+ appMemAccessorMap.get(AppStartMemoryStateCaptured.UID_FIELD_NUMBER)
+ .getFieldName()))
.asList().containsExactly(1000);
- assertThat(Arrays.asList(
- eventBundle.getStringArray(appMemAccessorMap.get(3).getFieldName())))
+ assertThat(Arrays.asList(eventBundle.getStringArray(
+ appMemAccessorMap.get(AppStartMemoryStateCaptured.ACTIVITY_NAME_FIELD_NUMBER)
+ .getFieldName())))
.containsExactly("activityName");
- assertThat(eventBundle.getLongArray(appMemAccessorMap.get(6).getFieldName()))
+ assertThat(eventBundle.getLongArray(
+ appMemAccessorMap.get(AppStartMemoryStateCaptured.RSS_IN_BYTES_FIELD_NUMBER)
+ .getFieldName()))
.asList().containsExactly(1234L);
- assertThat(gaugeBundle.getIntArray(procMemAccessorMap.get(1).getFieldName()))
+ assertThat(gaugeBundle.getIntArray(
+ procMemAccessorMap.get(ProcessMemoryState.UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(234);
- assertThat(Arrays.asList(
- gaugeBundle.getStringArray(procMemAccessorMap.get(2).getFieldName())))
+ assertThat(Arrays.asList(gaugeBundle.getStringArray(
+ procMemAccessorMap.get(ProcessMemoryState.PROCESS_NAME_FIELD_NUMBER)
+ .getFieldName())))
.containsExactly("process.name");
- assertThat(gaugeBundle.getLongArray(procMemAccessorMap.get(6).getFieldName()))
+ assertThat(gaugeBundle.getLongArray(
+ procMemAccessorMap.get(ProcessMemoryState.RSS_IN_BYTES_FIELD_NUMBER)
+ .getFieldName()))
.asList().containsExactly(4567L);
assertThat(gaugeBundle.getLongArray(GaugeMetricDataConverter.ELAPSED_TIME_NANOS))
.asList().containsExactly(445678901L);
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/EventMetricDataConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java
similarity index 81%
rename from tests/carservice_unit_test/src/com/android/car/telemetry/publisher/EventMetricDataConverterTest.java
rename to tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java
index 829ef4e..dac3310 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/EventMetricDataConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/EventMetricDataConverterTest.java
@@ -14,7 +14,11 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
+
+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.google.common.truth.Truth.assertThat;
@@ -65,11 +69,12 @@
assertThat(bundle.size()).isEqualTo(4);
assertThat(bundle.getLongArray(EventMetricDataConverter.ELAPSED_TIME_NANOS))
.asList().containsExactly(12345678L, 23456789L).inOrder();
- assertThat(bundle.getIntArray(accessorMap.get(1).getFieldName()))
+ assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 1100).inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(3).getFieldName())))
+ assertThat(Arrays.asList(bundle.getStringArray(
+ accessorMap.get(ACTIVITY_NAME_FIELD_NUMBER).getFieldName())))
.containsExactly("activityName1", "activityName2").inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(6).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(RSS_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1234L, 2345L).inOrder();
}
}
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/GaugeMetricDataConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java
similarity index 82%
rename from tests/carservice_unit_test/src/com/android/car/telemetry/publisher/GaugeMetricDataConverterTest.java
rename to tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java
index 8f3d3a1..8e747ae 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/GaugeMetricDataConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/GaugeMetricDataConverterTest.java
@@ -14,7 +14,13 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
+
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.PAGE_FAULT_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.PROCESS_NAME_FIELD_NUMBER;
+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.google.common.truth.Truth.assertThat;
@@ -23,13 +29,13 @@
import com.android.car.telemetry.AtomsProto;
import com.android.car.telemetry.StatsLogProto;
+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.HashMap;
import java.util.List;
import java.util.Map;
@@ -86,9 +92,9 @@
.build()
);
List<Integer> dimensionsFieldsIds = Arrays.asList(1, 2, 8);
- Map<Long, String> hashToStringMap = new HashMap<>();
- hashToStringMap.put(hash1, "process.name.1");
- hashToStringMap.put(hash2, "process.name.2");
+ Map<Long, String> hashToStringMap = Map.of(
+ hash1, "process.name.1",
+ hash2, "process.name.2");
SparseArray<AtomFieldAccessor<AtomsProto.ProcessMemoryState>> accessorMap =
new ProcessMemoryStateConverter().getAtomFieldAccessorMap();
@@ -98,16 +104,17 @@
// 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(6);
- assertThat(bundle.getIntArray(accessorMap.get(1).getFieldName()))
+ assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(123, 123, 123, 234).inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(2).getFieldName())))
+ assertThat(Arrays.asList(bundle.getStringArray(
+ accessorMap.get(PROCESS_NAME_FIELD_NUMBER).getFieldName())))
.containsExactly("process.name.1", "process.name.1",
"process.name.1", "process.name.2").inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(4).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(PAGE_FAULT_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000L, 1100L, 1200L, 1300L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(6).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(RSS_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1234L, 2345L, 3456L, 4567L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(8).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(SWAP_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(11111111L, 11111111L, 11111111L, 22222222L).inOrder();
assertThat(bundle.getLongArray(GaugeMetricDataConverter.ELAPSED_TIME_NANOS))
.asList().containsExactly(12345678L, 23456789L, 34567890L, 445678901L).inOrder();
diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/ProcessMemoryStateConverterTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java
similarity index 71%
rename from tests/carservice_unit_test/src/com/android/car/telemetry/publisher/ProcessMemoryStateConverterTest.java
rename to tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java
index fbc39e5..f922d17 100644
--- a/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/ProcessMemoryStateConverterTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/telemetry/publisher/statsconverters/ProcessMemoryStateConverterTest.java
@@ -14,7 +14,16 @@
* limitations under the License.
*/
-package com.android.car.telemetry.publisher;
+package com.android.car.telemetry.publisher.statsconverters;
+
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.CACHE_IN_BYTES_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.OOM_ADJ_SCORE_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.PAGE_FAULT_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.PAGE_MAJOR_FAULT_FIELD_NUMBER;
+import static com.android.car.telemetry.AtomsProto.ProcessMemoryState.PROCESS_NAME_FIELD_NUMBER;
+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.google.common.truth.Truth.assertThat;
@@ -26,13 +35,13 @@
import com.android.car.telemetry.AtomsProto.Atom;
import com.android.car.telemetry.AtomsProto.ProcessMemoryState;
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.HashMap;
import java.util.List;
import java.util.Map;
@@ -73,11 +82,9 @@
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 = new HashMap<>();
- static {
- HASH_STR_MAP.put(HASH_1, "process.name.1");
- HASH_STR_MAP.put(HASH_2, "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(
@@ -95,34 +102,39 @@
// Wrong format since leaf level dimension value should set value, not field
DimensionsValue.newBuilder().setField(3).build());
+ // Subject of the test.
+ private ProcessMemoryStateConverter mConverter = new ProcessMemoryStateConverter();
+
@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);
- ProcessMemoryStateConverter converter = new ProcessMemoryStateConverter();
SparseArray<AtomFieldAccessor<ProcessMemoryState>> accessorMap =
- converter.getAtomFieldAccessorMap();
+ mConverter.getAtomFieldAccessorMap();
- PersistableBundle bundle = converter.convert(atomsList, DIM_FIELDS_IDS,
+ PersistableBundle bundle = mConverter.convert(atomsList, DIM_FIELDS_IDS,
dimensionsValuesList, HASH_STR_MAP);
assertThat(bundle.size()).isEqualTo(8);
- assertThat(bundle.getIntArray(accessorMap.get(1).getFieldName()))
+ assertThat(bundle.getIntArray(accessorMap.get(UID_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1000, 2000).inOrder();
- assertThat(Arrays.asList(bundle.getStringArray(accessorMap.get(2).getFieldName())))
+ assertThat(Arrays.asList(
+ bundle.getStringArray(accessorMap.get(PROCESS_NAME_FIELD_NUMBER).getFieldName())))
.containsExactly("process.name.1", "process.name.2").inOrder();
- assertThat(bundle.getIntArray(accessorMap.get(3).getFieldName()))
+ assertThat(bundle.getIntArray(accessorMap.get(OOM_ADJ_SCORE_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(100, 200).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(4).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(PAGE_FAULT_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(59L, 99L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(5).getFieldName()))
+ assertThat(bundle.getLongArray(
+ accessorMap.get(PAGE_MAJOR_FAULT_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(34L, 55L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(6).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(RSS_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(1234L, 2345L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(7).getFieldName()))
+ assertThat(bundle.getLongArray(
+ accessorMap.get(CACHE_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(234L, 345L).inOrder();
- assertThat(bundle.getLongArray(accessorMap.get(8).getFieldName()))
+ assertThat(bundle.getLongArray(accessorMap.get(SWAP_IN_BYTES_FIELD_NUMBER).getFieldName()))
.asList().containsExactly(111L, 222L).inOrder();
}
@@ -131,11 +143,9 @@
List<Atom> atomsList = Arrays.asList(ATOM_A, ATOM_MISMATCH);
List<List<DimensionsValue>> dimensionsValuesList = Arrays.asList(DV_PAIR_A, DV_PAIR_B);
- ProcessMemoryStateConverter converter = new ProcessMemoryStateConverter();
-
assertThrows(
StatsConversionException.class,
- () -> converter.convert(
+ () -> mConverter.convert(
atomsList,
DIM_FIELDS_IDS,
dimensionsValuesList,
@@ -148,11 +158,9 @@
List<List<DimensionsValue>> dimensionsValuesList =
Arrays.asList(DV_PAIR_A, DV_PAIR_MALFORMED);
- ProcessMemoryStateConverter converter = new ProcessMemoryStateConverter();
-
assertThrows(
StatsConversionException.class,
- () -> converter.convert(
+ () -> mConverter.convert(
atomsList,
DIM_FIELDS_IDS,
dimensionsValuesList,
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 c1e3938..6734322 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
@@ -18,8 +18,8 @@
import static android.automotive.watchdog.internal.ResourceOveruseActionType.KILLED;
import static android.automotive.watchdog.internal.ResourceOveruseActionType.NOT_KILLED;
-import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetAliveUsers;
import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetAllUsers;
+import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetUserHandles;
import static android.car.watchdog.CarWatchdogManager.TIMEOUT_CRITICAL;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
@@ -283,6 +283,15 @@
}
@Test
+ public void testUserRemovedBroadcast() throws Exception {
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 101, 102);
+ mBroadcastReceiver.onReceive(mMockContext,
+ new Intent().setAction(Intent.ACTION_USER_REMOVED)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(100)));
+ verify(mMockWatchdogStorage).syncUsers(new int[] {101, 102});
+ }
+
+ @Test
public void testGetResourceOveruseStats() throws Exception {
int uid = Binder.getCallingUid();
injectPackageInfos(Collections.singletonList(
@@ -1001,7 +1010,7 @@
@Test
public void testSetKillablePackageAsUser() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("third_party_package", 1103456, null),
constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null),
@@ -1029,7 +1038,7 @@
() -> mCarWatchdogService.setKillablePackageAsUser("vendor_package.critical",
userHandle, /* isKillable= */ true));
- mockUmGetAliveUsers(mMockUserManager, 11, 12, 13);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12, 13);
injectPackageInfos(Collections.singletonList(
constructPackageManagerPackageInfo("third_party_package", 1303456, null)));
@@ -1049,7 +1058,7 @@
@Test
public void testSetKillablePackageAsUserWithSharedUids() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"third_party_package.A", 1103456, "third_party_shared_package.A"),
@@ -1094,7 +1103,7 @@
@Test
public void testSetKillablePackageAsUserForAllUsers() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("third_party_package", 1103456, null),
constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null),
@@ -1121,7 +1130,7 @@
() -> mCarWatchdogService.setKillablePackageAsUser("vendor_package.critical",
UserHandle.ALL, /* isKillable= */ true));
- mockUmGetAliveUsers(mMockUserManager, 11, 12, 13);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12, 13);
injectPackageInfos(Collections.singletonList(
constructPackageManagerPackageInfo("third_party_package", 1303456, null)));
@@ -1141,7 +1150,7 @@
@Test
public void testSetKillablePackageAsUsersForAllUsersWithSharedUids() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"third_party_package.A", 1103456, "third_party_shared_package.A"),
@@ -1174,7 +1183,7 @@
new PackageKillableState("third_party_package.B", 12,
PackageKillableState.KILLABLE_STATE_NO));
- mockUmGetAliveUsers(mMockUserManager, 11, 12, 13);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12, 13);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"third_party_package.A", 1303456, "third_party_shared_package.A"),
@@ -1192,7 +1201,7 @@
@Test
public void testGetPackageKillableStatesAsUser() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("third_party_package", 1103456, null),
constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null),
@@ -1210,7 +1219,7 @@
@Test
public void testGetPackageKillableStatesAsUserWithSafeToKillPackages() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("system_package.non_critical.A", 1102459, null),
constructPackageManagerPackageInfo("third_party_package", 1103456, null),
@@ -1242,7 +1251,7 @@
@Test
public void testGetPackageKillableStatesAsUserWithVendorPackagePrefixes() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11);
/* Package names which start with "system" are constructed as system packages. */
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("system_package_as_vendor", 1102459, null)));
@@ -1273,7 +1282,7 @@
@Test
public void testGetPackageKillableStatesAsUserWithSharedUids() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"system_package.A", 1103456, "vendor_shared_package.A"),
@@ -1304,7 +1313,7 @@
@Test
public void testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillPackages()
throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"vendor_package.non_critical.A", 1103456, "vendor_shared_package.A"),
@@ -1343,7 +1352,7 @@
@Test
public void testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillSharedPackage()
throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"vendor_package.non_critical.A", 1103456, "vendor_shared_package.B"),
@@ -1374,7 +1383,7 @@
@Test
public void testGetPackageKillableStatesAsUserForAllUsers() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("third_party_package", 1103456, null),
constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null),
@@ -1395,7 +1404,7 @@
@Test
public void testGetPackageKillableStatesAsUserForAllUsersWithSharedUids() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"system_package.A", 1103456, "vendor_shared_package.A"),
@@ -1897,7 +1906,7 @@
@Test
public void testPersistStatsOnShutdownEnter() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 10, 11, 12);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 10, 11, 12);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo(
"third_party_package", 1103456, "vendor_shared_package.critical"),
@@ -1961,7 +1970,7 @@
@Test
public void testPersistIoOveruseStatsOnDateChange() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 10);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 10);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("system_package", 1011200, null),
constructPackageManagerPackageInfo("third_party_package", 1001100, null)));
@@ -2053,7 +2062,7 @@
@Test
public void testResetResourceOveruseStatsResetsUserPackageSettings() throws Exception {
- mockUmGetAliveUsers(mMockUserManager, 100, 101);
+ mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100, 101);
injectPackageInfos(Arrays.asList(
constructPackageManagerPackageInfo("third_party_package.A", 10001278, null),
constructPackageManagerPackageInfo("third_party_package.A", 10101278, null),
@@ -2388,6 +2397,7 @@
*/
CarServiceUtils.getHandlerThread(CarWatchdogService.class.getSimpleName())
.getThreadHandler().post(() -> {});
+ verify(mMockWatchdogStorage, times(wantedInvocations)).syncUsers(any());
verify(mMockWatchdogStorage, times(wantedInvocations)).getUserPackageSettings();
verify(mMockWatchdogStorage, times(wantedInvocations)).getTodayIoUsageStats();
}
diff --git a/tests/carservice_unit_test/src/com/android/car/watchdog/WatchdogStorageUnitTest.java b/tests/carservice_unit_test/src/com/android/car/watchdog/WatchdogStorageUnitTest.java
index 3f16750..e2c12bb 100644
--- a/tests/carservice_unit_test/src/com/android/car/watchdog/WatchdogStorageUnitTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/watchdog/WatchdogStorageUnitTest.java
@@ -346,6 +346,68 @@
}
@Test
+ public void testSyncUsers() throws Exception {
+ List<WatchdogStorage.UserPackageSettingsEntry> settingsEntries = sampleSettings();
+ List<WatchdogStorage.IoUsageStatsEntry> ioUsageStatsEntries = sampleStatsForToday();
+
+ assertThat(mService.saveUserPackageSettings(settingsEntries)).isTrue();
+ assertThat(mService.saveIoUsageStats(ioUsageStatsEntries)).isTrue();
+
+ mService.syncUsers(/* aliveUserIds= */ new int[] {101});
+
+ settingsEntries.removeIf((s) -> s.userId == 100);
+ ioUsageStatsEntries.removeIf((e) -> e.userId == 100);
+
+ UserPackageSettingsEntrySubject.assertThat(mService.getUserPackageSettings())
+ .containsExactlyElementsIn(settingsEntries);
+
+ IoUsageStatsEntrySubject.assertThat(mService.getTodayIoUsageStats())
+ .containsExactlyElementsIn(ioUsageStatsEntries);
+ }
+
+ @Test
+ public void testSyncUsersWithHistoricalIoOveruseStats() throws Exception {
+ List<WatchdogStorage.UserPackageSettingsEntry> settingsEntries = sampleSettings();
+
+ assertThat(mService.saveUserPackageSettings(settingsEntries)).isTrue();
+ assertThat(mService.saveIoUsageStats(sampleStatsBetweenDates(
+ /* includingStartDaysAgo= */ 1, /* excludingEndDaysAgo= */ 6))).isTrue();
+
+ mService.syncUsers(/* aliveUserIds= */ new int[] {101});
+
+ settingsEntries.removeIf((s) -> s.userId == 100);
+
+ UserPackageSettingsEntrySubject.assertThat(mService.getUserPackageSettings())
+ .containsExactlyElementsIn(settingsEntries);
+
+ IoOveruseStats actualSystemPackage = mService.getHistoricalIoOveruseStats(
+ /* userId= */ 100, "system_package.non_critical.A", /* numDaysAgo= */ 7);
+ IoOveruseStats actualVendorPackage = mService.getHistoricalIoOveruseStats(
+ /* userId= */ 100, "vendor_package.critical.C", /* numDaysAgo= */ 7);
+
+ assertWithMessage("System I/O overuse stats for deleted user")
+ .that(actualSystemPackage).isNull();
+ assertWithMessage("Vendor I/O overuse stats for deleted user")
+ .that(actualVendorPackage).isNull();
+ }
+
+ @Test
+ public void testSyncUsersWithNoDataForDeletedUser() throws Exception {
+ List<WatchdogStorage.UserPackageSettingsEntry> settingsEntries = sampleSettings();
+ List<WatchdogStorage.IoUsageStatsEntry> ioUsageStatsEntries = sampleStatsForToday();
+
+ assertThat(mService.saveUserPackageSettings(settingsEntries)).isTrue();
+ assertThat(mService.saveIoUsageStats(ioUsageStatsEntries)).isTrue();
+
+ mService.syncUsers(/* aliveUserIds= */ new int[] {100, 101});
+
+ UserPackageSettingsEntrySubject.assertThat(mService.getUserPackageSettings())
+ .containsExactlyElementsIn(settingsEntries);
+ IoUsageStatsEntrySubject.assertThat(mService.getTodayIoUsageStats())
+ .containsExactlyElementsIn(ioUsageStatsEntries);
+ }
+
+ @Test
public void testTruncateStatsOutsideRetentionPeriodOnDateChange() throws Exception {
injectSampleUserPackageSettings();
setDate(/* numDaysAgo= */ 1);
@@ -454,7 +516,7 @@
private static ArrayList<WatchdogStorage.IoUsageStatsEntry> sampleStatsForDate(
long statsDateEpoch, long duration) {
ArrayList<WatchdogStorage.IoUsageStatsEntry> entries = new ArrayList<>();
- for (int i = 100; i < 101; ++i) {
+ for (int i = 100; i <= 101; ++i) {
entries.add(constructIoUsageStatsEntry(
/* userId= */ i, "system_package.non_critical.A", statsDateEpoch, duration,
/* remainingWriteBytes= */