Merge "Add new sticky battery saver strings"
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 7ab18a4..3424e76 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -1541,6 +1541,22 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    <color name="bt_outline_color">#1f000000</color> <!-- icon outline color -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="160"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="                android:background=&quot;@color/lock_pattern_background&quot; />"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 59ed4c4..c333edb 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -156,4 +156,6 @@
     <color name="bt_color_bg_5">#fdcfe8</color> <!-- Material Pink 100 -->
     <color name="bt_color_bg_6">#e9d2fd</color> <!-- Material Purple 100 -->
     <color name="bt_color_bg_7">#cbf0f8</color> <!-- Material Cyan 100 -->
+
+    <color name="bt_outline_color">#1f000000</color> <!-- icon outline color -->
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 248fb81..4a65bc9 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -404,4 +404,13 @@
 
     <!-- Wi-Fi DPP fragment icon size -->
     <dimen name="wifi_dpp_fragment_icon_width_height">48dp</dimen>
+
+    <!-- Size of nearby icon -->
+    <dimen name="bt_nearby_icon_size">24dp</dimen>
+
+    <!-- Stroke size of adaptive outline -->
+    <dimen name="adaptive_outline_stroke">1dp</dimen>
+
+    <!-- Elevation of bluetooth icon -->
+    <dimen name="bt_icon_elevation">4dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 33ec2e8..89d1044 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10658,20 +10658,20 @@
     <string name="mobile_network_list_add_more">Add more</string>
     <!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
          that service is active and is tied to a physical SIM card [CHAR LIMIT=40] -->
-    <string name="mobile_network_active_sim">Active SIM</string>
+    <string name="mobile_network_active_sim">Active / SIM</string>
     <!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
          that service is inactive and is tied to a physical SIM card [CHAR LIMIT=40] -->
-    <string name="mobile_network_inactive_sim">Inactive SIM</string>
+    <string name="mobile_network_inactive_sim">Inactive / SIM</string>
     <!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
          that service is active and is tied to an eSIM profile [CHAR LIMIT=40] -->
-    <string name="mobile_network_active_esim">Active eSIM</string>
+    <string name="mobile_network_active_esim">Active / Downloaded SIM</string>
     <!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
          that service is inactive and is tied to an eSIM profile [CHAR LIMIT=40] -->
-    <string name="mobile_network_inactive_esim">Inactive eSIM</string>
+    <string name="mobile_network_inactive_esim">Inactive / Downloaded SIM</string>
     <!-- Title of a dialog that lets a user modify the display name used for a mobile network
          subscription in various places in the Settings app. The default name is typically just the
-          carrier name, but especially in multi-SIM configurations users may want to use a different
-           name. [CHAR LIMIT=40] -->
+         carrier name, but especially in multi-SIM configurations users may want to use a different
+         name. [CHAR LIMIT=40] -->
     <string name="mobile_network_sim_name">SIM name</string>
     <!-- Label on the confirmation button of a dialog that lets a user set the display name of a
          mobile network subscription [CHAR LIMIT=20] -->
@@ -10683,6 +10683,35 @@
          disabling/enabling a SIM. The SIM is disabled in this state. [CHAR LIMIT=40] -->
     <string name="mobile_network_use_sim_off">Off</string>
 
+    <!-- Mobile network details page. Label for an option that lets the user delete an eSIM from
+         the device. [CHAR LIMIT=60] -->
+    <string name="mobile_network_erase_sim">Erase SIM</string>
+    <!-- Title of a confirmation dialog for deleting an eSIM from the device.
+         [CHAR LIMIT=60] -->
+    <string name="mobile_network_erase_sim_dialog_title">Erase this downloaded SIM?</string>
+    <!-- Body text of of a confirmation dialog for deleting an eSIM from the device.
+         [CHAR LIMIT=NONE] -->
+    <string name="mobile_network_erase_sim_dialog_body">
+        Erasing this SIM removes <xliff:g id="carrier" example="Verizon">%1$s</xliff:g> service
+        from this device.\n\nService for <xliff:g id="carrier" example="Verizon">%2$s</xliff:g>
+        won\u2019t be canceled.
+    </string>
+    <!-- OK button on a confirmation dialog for deleting an eSIM from the device.
+         [CHAR LIMIT=30] -->
+    <string name="mobile_network_erase_sim_dialog_ok">Erase</string>
+    <!-- Body text of the progress dialog we show while deleting an eSIM from the device.
+         [CHAR LIMIT=NONE] -->
+    <string name="mobile_network_erase_sim_dialog_progress">Erasing SIM\u2026</string>
+
+    <!-- Title of a dialog indicating that an error ocurred when deleting an eSIM from the device
+         [CHAR LIMIT=60] -->
+    <string name="mobile_network_erase_sim_error_dialog_title">Can\u2019t erase SIM</string>
+    <!-- Body of a dialog indicating that an error ocurred when deleting an eSIM from the device
+         [CHAR LIMIT=NONE] -->
+    <string name="mobile_network_erase_sim_error_dialog_body">
+        This SIM can\u2019t be erased due to an error.\n\nRestart your device and try again.
+    </string>
+
     <!-- Title for preferred network type [CHAR LIMIT=NONE] -->
     <string name="preferred_network_mode_title">Preferred network type</string>
     <!-- Summary for preferred network type [CHAR LIMIT=NONE] -->
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index d2d9e35..f39880c 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -63,12 +63,25 @@
         settings:searchable="false"/>
 
     <!-- Content Capture -->
+
+    <!-- NOTE: content capture has a different preference, depending whether or not the
+         ContentCaptureService implementations defines a custom settings activitiy on its manifest.
+         Hence, we show both here, but the controller itself will decide if it's available or not.
+    -->
+
     <SwitchPreference
         android:key="content_capture"
         android:title="@string/content_capture"
         android:summary="@string/content_capture_summary"
         settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
 
+    <com.android.settings.widget.MasterSwitchPreference
+        android:key="content_capture_custom_settings"
+        android:title="@string/content_capture"
+        android:summary="@string/content_capture_summary"
+        settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController">
+    </com.android.settings.widget.MasterSwitchPreference>
+
     <!-- Privacy Service -->
     <PreferenceCategory
         android:key="privacy_services"/>
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index 3860352..fe73a2e 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -80,8 +80,10 @@
 
     @Override
     protected void refresh() {
-        setHeaderProperties();
-        mHeaderController.done(mFragment.getActivity(), true /* rebindActions */);
+        if (isAvailable()) {
+            setHeaderProperties();
+            mHeaderController.done(mFragment.getActivity(), true /* rebindActions */);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index 8d727eb..4a7ca27 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -164,6 +164,8 @@
         final ImageView imageView = (ImageView) view.findViewById(android.R.id.icon);
         if (imageView != null) {
             imageView.setContentDescription(contentDescription);
+            imageView.setElevation(
+                    getContext().getResources().getDimension(R.dimen.bt_icon_elevation));
         }
         super.onBindViewHolder(view);
     }
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
index e02ddc4..ecf40b6 100755
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -22,8 +22,11 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.provider.MediaStore;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Pair;
@@ -33,14 +36,18 @@
 import androidx.appcompat.app.AlertDialog;
 
 import com.android.settings.R;
+import com.android.settings.homepage.AdaptiveIconShapeDrawable;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.AdaptiveIcon;
+import com.android.settings.widget.AdaptiveOutlineDrawable;
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback;
 
+import java.io.IOException;
+
 /**
  * Utils is a helper class that contains constants for various
  * Android resource IDs, debug logging flags, and static methods
@@ -165,6 +172,7 @@
         if (bluetoothDevice == null) {
             return false;
         }
+
         return Boolean.parseBoolean(bluetoothDevice.getMetadata(key));
     }
 
@@ -193,7 +201,36 @@
             CachedBluetoothDevice cachedDevice) {
         final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
                 context, cachedDevice);
+        final boolean untetheredHeadset = Utils.getBooleanMetaData(cachedDevice.getDevice(),
+                BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET);
+        final int iconSize = context.getResources().getDimensionPixelSize(
+                R.dimen.bt_nearby_icon_size);
         final Resources resources = context.getResources();
+
+        // Deal with untethered headset
+        if (untetheredHeadset) {
+            final String uriString = Utils.getStringMetaData(cachedDevice.getDevice(),
+                    BluetoothDevice.METADATA_MAIN_ICON);
+            final Uri iconUri = uriString != null ? Uri.parse(uriString) : null;
+            if (iconUri != null) {
+                try {
+                    final Bitmap bitmap = MediaStore.Images.Media.getBitmap(
+                            context.getContentResolver(), iconUri);
+                    if (bitmap != null) {
+                        final Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, iconSize,
+                                iconSize, false);
+                        bitmap.recycle();
+                        final AdaptiveOutlineDrawable drawable = new AdaptiveOutlineDrawable(
+                                resources, resizedBitmap);
+                        return new Pair<>(drawable, pair.second);
+                    }
+                } catch (IOException e) {
+                    Log.e(TAG, "Failed to get drawable for: " + iconUri, e);
+                }
+            }
+        }
+
+        // Deal with normal headset
         final int[] iconFgColors = resources.getIntArray(R.array.bt_icon_fg_colors);
         final int[] iconBgColors = resources.getIntArray(R.array.bt_icon_bg_colors);
 
diff --git a/src/com/android/settings/fuelgauge/BatterySaverController.java b/src/com/android/settings/fuelgauge/BatterySaverController.java
index c4ed88b..acb5e32 100644
--- a/src/com/android/settings/fuelgauge/BatterySaverController.java
+++ b/src/com/android/settings/fuelgauge/BatterySaverController.java
@@ -90,10 +90,10 @@
         final int percent = Settings.Global.getInt(resolver,
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
         final int mode = Settings.Global.getInt(resolver,
-                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Global.AUTOMATIC_POWER_SAVE_MODE, PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         if (isPowerSaveOn) {
             return mContext.getString(R.string.battery_saver_on_summary);
-        } else if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+        } else if (mode == PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE) {
             if (percent != 0) {
                 return mContext.getString(R.string.battery_saver_off_scheduled_summary,
                         Utils.formatPercentage(percent));
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
index 2cc73d1..0b129ef 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceController.java
@@ -61,9 +61,9 @@
     @Override
     public CharSequence getSummary() {
         final ContentResolver resolver = mContext.getContentResolver();
-        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
-        if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
+        if (mode == PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE) {
             final int threshold =
                     Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
             if (threshold <= 0) {
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
index d49eb0a..796df46 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
@@ -29,7 +29,7 @@
  *
  * Will call the appropriate power manager APIs and modify the correct settings to enable
  * users to control their automatic battery saver toggling preferences.
- * See {@link Settings.Global#AUTOMATIC_POWER_SAVER_MODE} for more details.
+ * See {@link Settings.Global#AUTOMATIC_POWER_SAVE_MODE} for more details.
  */
 public class BatterySaverScheduleRadioButtonsController {
 
@@ -48,12 +48,12 @@
 
     public String getDefaultKey() {
         final ContentResolver resolver = mContext.getContentResolver();
-        // Note: this can also be obtained via PowerManager.getPowerSaveMode()
-        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        // Note: this can also be obtained via PowerManager.getPowerSaveModeTrigger()
+        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         // if mode is "dynamic" we are in routine mode, percentage with non-zero threshold is
         // percentage mode, otherwise it is no schedule mode
-        if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+        if (mode == PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE) {
             final int threshold =
                     Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
             if (threshold <= 0) {
@@ -68,18 +68,18 @@
         final ContentResolver resolver = mContext.getContentResolver();
         switch(key) {
             case KEY_NO_SCHEDULE:
-                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                        PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                        PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
                 Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
                 break;
             case KEY_PERCENTAGE:
-                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                        PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                        PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
                 Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
                 break;
             case KEY_ROUTINE:
-                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                        PowerManager.POWER_SAVER_MODE_DYNAMIC);
+                Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                        PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
                 break;
             default:
                 throw new IllegalStateException(
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
index 6253947..b704fde 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
@@ -39,7 +39,7 @@
  *
  * Will call the appropriate power manager APIs and modify the correct settings to enable
  * users to control their automatic battery saver toggling preferences.
- * See {@link Settings.Global#AUTOMATIC_POWER_SAVER_MODE} for more details.
+ * See {@link Settings.Global#AUTOMATIC_POWER_SAVE_MODE} for more details.
  */
 public class BatterySaverScheduleSeekBarController implements
         OnPreferenceChangeListener {
@@ -76,12 +76,12 @@
 
     public void updateSeekBar() {
         final ContentResolver resolver = mContext.getContentResolver();
-        // Note: this can also be obtained via PowerManager.getPowerSaveMode()
-        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        // Note: this can also be obtained via PowerManager.getPowerSaveModeTrigger()
+        final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         // if mode is "dynamic" we are in routine mode, percentage with non-zero threshold is
         // percentage mode, otherwise it is no schedule mode
-        if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
+        if (mode == PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE) {
             final int threshold =
                     Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
             if (threshold <= 0) {
diff --git a/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java b/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java
index b3ea9a7..47610aa 100644
--- a/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java
+++ b/src/com/android/settings/privacy/EnableContentCapturePreferenceController.java
@@ -16,43 +16,34 @@
 
 package com.android.settings.privacy;
 
+import android.annotation.NonNull;
 import android.content.Context;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.view.contentcapture.ContentCaptureManager;
 
 import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.utils.ContentCaptureUtils;
 
-public class EnableContentCapturePreferenceController extends TogglePreferenceController {
+public final class EnableContentCapturePreferenceController extends TogglePreferenceController {
 
-    private static final String KEY_SHOW_PASSWORD = "content_capture";
-    private static final int MY_USER_ID = UserHandle.myUserId();
-
-    public EnableContentCapturePreferenceController(Context context) {
-        super(context, KEY_SHOW_PASSWORD);
+    public EnableContentCapturePreferenceController(@NonNull Context context, @NonNull String key) {
+        super(context, key);
     }
 
     @Override
     public boolean isChecked() {
-        boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, MY_USER_ID) == 1;
-        return enabled;
+        return ContentCaptureUtils.isEnabledForUser(mContext);
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
-        Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                Settings.Secure.CONTENT_CAPTURE_ENABLED, isChecked ? 1 : 0, MY_USER_ID);
+        ContentCaptureUtils.setEnabledForUser(mContext, isChecked);
         return true;
     }
 
     @Override
     public int getAvailabilityStatus() {
-        // We cannot look for ContentCaptureManager, because it's not available if the service
-        // didn't whitelist Settings
-        IBinder service = ServiceManager.checkService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
-        return service != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        boolean available = ContentCaptureUtils.isFeatureAvailable()
+                && ContentCaptureUtils.getServiceSettingsComponentName() == null;
+        return available ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 }
diff --git a/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
new file mode 100644
index 0000000..1456c2d
--- /dev/null
+++ b/src/com/android/settings/privacy/EnableContentCaptureWithServiceSettingsPreferenceController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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.settings.privacy;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.utils.ContentCaptureUtils;
+import com.android.settings.widget.MasterSwitchPreference;
+
+public final class EnableContentCaptureWithServiceSettingsPreferenceController
+        extends TogglePreferenceController {
+
+    private static final String TAG = "ContentCaptureController";
+
+    public EnableContentCaptureWithServiceSettingsPreferenceController(@NonNull Context context,
+            @NonNull String key) {
+        super(context, key);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return ContentCaptureUtils.isEnabledForUser(mContext);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        ContentCaptureUtils.setEnabledForUser(mContext, isChecked);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+
+        ComponentName componentName = ContentCaptureUtils.getServiceSettingsComponentName();
+        if (componentName != null) {
+            preference.setIntent(new Intent(Intent.ACTION_MAIN).setComponent(componentName));
+        } else {
+            // Should not happen - preference should be disabled by controller
+            Log.w(TAG, "No component name for custom service settings");
+            preference.setSelectable(false);
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        boolean available = ContentCaptureUtils.isFeatureAvailable()
+                && ContentCaptureUtils.getServiceSettingsComponentName() != null;
+        return available ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+}
diff --git a/src/com/android/settings/utils/ContentCaptureUtils.java b/src/com/android/settings/utils/ContentCaptureUtils.java
new file mode 100644
index 0000000..a92651f
--- /dev/null
+++ b/src/com/android/settings/utils/ContentCaptureUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.settings.utils;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager;
+
+public final class ContentCaptureUtils {
+
+    private static final String TAG = ContentCaptureUtils.class.getSimpleName();
+    private static final int MY_USER_ID = UserHandle.myUserId();
+
+    public static boolean isEnabledForUser(@NonNull Context context) {
+        boolean enabled = Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, MY_USER_ID) == 1;
+        return enabled;
+    }
+
+    public static void setEnabledForUser(@NonNull Context context, boolean enabled) {
+        Settings.Secure.putIntForUser(context.getContentResolver(),
+                Settings.Secure.CONTENT_CAPTURE_ENABLED, enabled ? 1 : 0, MY_USER_ID);
+    }
+
+    public static boolean isFeatureAvailable() {
+        // We cannot look for ContentCaptureManager, because it's not available if the service
+        // didn't whitelist Settings
+        IBinder service = ServiceManager.checkService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
+        return service != null;
+    }
+
+    @Nullable
+    public static ComponentName getServiceSettingsComponentName() {
+        try {
+            return ContentCaptureManager.getServiceSettingsComponentName();
+        } catch (RuntimeException e) {
+            Log.w(TAG, "Could not get service settings: " + e);
+            return null;
+        }
+    }
+
+    private ContentCaptureUtils() {
+        throw new UnsupportedOperationException("contains only static methods");
+    }
+}
diff --git a/src/com/android/settings/widget/AdaptiveOutlineDrawable.java b/src/com/android/settings/widget/AdaptiveOutlineDrawable.java
new file mode 100644
index 0000000..84c4e2f
--- /dev/null
+++ b/src/com/android/settings/widget/AdaptiveOutlineDrawable.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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.settings.widget;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.DrawableWrapper;
+import android.util.PathParser;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.homepage.AdaptiveIconShapeDrawable;
+
+/**
+ * Adaptive outline drawable with white plain background color and black outline
+ */
+public class AdaptiveOutlineDrawable extends DrawableWrapper {
+    @VisibleForTesting
+    final Paint mOutlinePaint;
+    private Path mPath;
+    private final int mInsetPx;
+    private final Bitmap mBitmap;
+
+    public AdaptiveOutlineDrawable(Resources resources, Bitmap bitmap) {
+        super(new AdaptiveIconShapeDrawable(resources));
+
+        getDrawable().setTint(Color.WHITE);
+        mPath = new Path(PathParser.createPathFromPathData(
+                resources.getString(com.android.internal.R.string.config_icon_mask)));
+        mOutlinePaint = new Paint();
+        mOutlinePaint.setColor(resources.getColor(R.color.bt_outline_color, null));
+        mOutlinePaint.setStyle(Paint.Style.STROKE);
+        mOutlinePaint.setStrokeWidth(resources.getDimension(R.dimen.adaptive_outline_stroke));
+        mOutlinePaint.setAntiAlias(true);
+
+        mInsetPx = resources
+                .getDimensionPixelSize(R.dimen.dashboard_tile_foreground_image_inset);
+        mBitmap = bitmap;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        final Rect bounds = getBounds();
+        final float pathSize = AdaptiveIconDrawable.MASK_SIZE;
+
+        final float scaleX = (bounds.right - bounds.left) / pathSize;
+        final float scaleY = (bounds.bottom - bounds.top) / pathSize;
+
+        final int count = canvas.save();
+        canvas.scale(scaleX, scaleY);
+        // Draw outline
+        canvas.drawPath(mPath, mOutlinePaint);
+        canvas.restoreToCount(count);
+
+        // Draw the foreground icon
+        canvas.drawBitmap(mBitmap, bounds.left + mInsetPx, bounds.top + mInsetPx, null);
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mBitmap.getHeight() + 2 * mInsetPx;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mBitmap.getWidth() + 2 * mInsetPx;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java b/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java
index 51e559f..a956518 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/UtilsTest.java
@@ -29,6 +29,8 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.widget.AdaptiveIcon;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
@@ -39,6 +41,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
 public class UtilsTest {
@@ -51,6 +54,8 @@
     private Context mContext;
     @Mock
     private BluetoothDevice mBluetoothDevice;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
 
     private MetricsFeatureProvider mMetricsFeatureProvider;
 
@@ -107,4 +112,16 @@
                 BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET)).isEqualTo(true);
     }
 
+    @Test
+    public void getBtRainbowDrawableWithDescription_normalHeadset_returnAdaptiveIcon() {
+        when(mBluetoothDevice.getMetadata(
+                BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET)).thenReturn("false");
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+        when(mCachedBluetoothDevice.getAddress()).thenReturn("1f:aa:bb");
+
+        assertThat(Utils.getBtRainbowDrawableWithDescription(RuntimeEnvironment.application,
+                mCachedBluetoothDevice).first).isInstanceOf(
+                AdaptiveIcon.class);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/development/OverlayCategoryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/OverlayCategoryPreferenceControllerTest.java
index 8a90b20..b2e8013 100644
--- a/tests/robotests/src/com/android/settings/development/OverlayCategoryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/OverlayCategoryPreferenceControllerTest.java
@@ -221,6 +221,7 @@
 
         return new OverlayInfo(pkg /* packageName */,
                 "android" /* targetPackageName */,
+                null /* targetOverlayableName */,
                 TEST_CATEGORY/* category */,
                 pkg + ".baseCodePath" /* baseCodePath */,
                 state /* state */,
diff --git a/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java
index 41947a0..5133ae6 100644
--- a/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java
@@ -84,7 +84,7 @@
         when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
                 new PackageInfo());
         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
-                .thenReturn(Arrays.asList(new OverlayInfo("", "", "", "", 0, 0, 0, false)));
+                .thenReturn(Arrays.asList(new OverlayInfo("", "", "", "", "", 0, 0, 0, false)));
         assertThat(mController.isAvailable()).isFalse();
     }
 
@@ -94,8 +94,9 @@
                 new PackageInfo());
         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
                 .thenReturn(Arrays.asList(
-                        new OverlayInfo("", "", OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true),
-                        new OverlayInfo("", "", OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true)));
+                        new OverlayInfo("", "", "", OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true),
+                        new OverlayInfo("", "", "", OverlayInfo.CATEGORY_THEME, "", 0, 0, 0,
+                                true)));
         assertThat(mController.isAvailable()).isTrue();
     }
 
@@ -140,9 +141,9 @@
 
     @Test
     public void getCurrentTheme_withEnabledState() throws Exception {
-        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android",
+        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_ENABLED, 0, 0, true);
-        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android",
+        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true);
         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
                 Arrays.asList(info1, info2));
@@ -154,9 +155,9 @@
 
     @Test
     public void testGetCurrentTheme_withoutEnabledState() throws Exception {
-        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android",
+        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_DISABLED, 0, 0, true);
-        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android",
+        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true);
         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
                 Arrays.asList(info1, info2));
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java
index d1d21f3..a6c8534 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSchedulePreferenceControllerTest.java
@@ -62,7 +62,7 @@
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
         Settings.Global.putInt(mContext.getContentResolver(),
-                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Global.AUTOMATIC_POWER_SAVE_MODE, PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
 
         mController.updateState(mPreference);
 
@@ -74,7 +74,7 @@
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
         Settings.Global.putInt(mContext.getContentResolver(),
-                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+                Global.AUTOMATIC_POWER_SAVE_MODE, PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
 
         mController.updateState(mPreference);
 
@@ -87,7 +87,7 @@
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
         Settings.Global.putInt(mContext.getContentResolver(),
-                Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_DYNAMIC);
+                Global.AUTOMATIC_POWER_SAVE_MODE, PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
 
         mController.updateState(mPreference);
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
index 6d412ee..6012dbb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
@@ -31,16 +31,16 @@
 
     @Test
     public void getDefaultKey_routine_returnsCorrectValue() {
-        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_DYNAMIC);
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
         assertThat(mController.getDefaultKey())
                 .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_ROUTINE);
     }
 
     @Test
     public void getDefaultKey_automatic_returnsCorrectValue() {
-        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
         assertThat(mController.getDefaultKey())
                 .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_PERCENTAGE);
@@ -48,8 +48,8 @@
 
     @Test
     public void getDefaultKey_none_returnsCorrectValue() {
-        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
         assertThat(mController.getDefaultKey())
                 .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
index 8aac9d8..03c9b0a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
@@ -39,16 +39,16 @@
 
     @Test
     public void updateSeekBar_routineMode_hasCorrectProperties() {
-        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_DYNAMIC);
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
         mController.updateSeekBar();
         assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
     }
 
     @Test
     public void updateSeekBar_percentageMode_hasCorrectProperties() {
-        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
         mController.updateSeekBar();
         assertThat(mController.mSeekBarPreference.isVisible()).isTrue();
@@ -56,8 +56,8 @@
 
     @Test
     public void updateSeekBar_noneMode_hasCorrectProperties() {
-        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
-                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
         Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
         mController.updateSeekBar();
         assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
diff --git a/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java
index a379858..179063d 100644
--- a/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/EnableContentCapturePreferenceControllerTest.java
@@ -51,7 +51,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mController = new EnableContentCapturePreferenceController(mContext);
+        mController = new EnableContentCapturePreferenceController(mContext, "THE_KEY_TO_SUCCESS");
         mPreference = new Preference(mContext);
         mPreference.setKey(mController.getPreferenceKey());
     }
diff --git a/tests/robotests/src/com/android/settings/widget/AdaptiveOutlineDrawableTest.java b/tests/robotests/src/com/android/settings/widget/AdaptiveOutlineDrawableTest.java
new file mode 100644
index 0000000..f21fc34
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/AdaptiveOutlineDrawableTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.settings.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.res.Resources;
+import android.graphics.Paint;
+
+import com.android.settings.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class AdaptiveOutlineDrawableTest {
+
+    @Test
+    public void constructor_initPaint() {
+        final Resources resources = RuntimeEnvironment.application.getResources();
+        final AdaptiveOutlineDrawable drawable = new AdaptiveOutlineDrawable(resources, null);
+
+        assertThat(drawable.mOutlinePaint.getStyle()).isEqualTo(Paint.Style.STROKE);
+        assertThat(drawable.mOutlinePaint.getStrokeWidth()).isWithin(0.01f).of(
+                resources.getDimension(R.dimen.adaptive_outline_stroke));
+    }
+
+}
diff --git a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
index 3cdfb7c..c5ee000 100644
--- a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
@@ -69,9 +69,9 @@
 
     @Test
     public void testUpdateState() throws Exception {
-        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android",
+        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_ENABLED, 0, 0, true);
-        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android",
+        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true);
         when(mMockPackageManager.getApplicationInfo(any(), anyInt())).thenAnswer(inv -> {
             ApplicationInfo info = mock(ApplicationInfo.class);
@@ -105,9 +105,9 @@
 
     @Test
     public void testUpdateState_withStaticOverlay() throws Exception {
-        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android",
+        OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_ENABLED, 0, 0, true);
-        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android",
+        OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android", "",
                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_ENABLED, 0, 0, true);
         when(mMockPackageManager.getApplicationInfo(any(), anyInt())).thenAnswer(inv -> {
             ApplicationInfo info = mock(ApplicationInfo.class);