Merge "Enable HVAC button selected state" into sc-v2-dev
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_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/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/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/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/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/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/telemetry.proto b/service/src/com/android/car/telemetry/proto/telemetry.proto
index b06f519..2b58e9f 100644
--- a/service/src/com/android/car/telemetry/proto/telemetry.proto
+++ b/service/src/com/android/car/telemetry/proto/telemetry.proto
@@ -121,7 +121,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/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/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/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/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_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);