Merge "Use a boolean Consumer instead of RoleManagerCallback."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 96e3dd1..7625e78 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1245,6 +1245,10 @@
                 <action android:name="android.settings.PRIVACY_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.REQUEST_ENABLE_CONTENT_CAPTURE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                        android:value="com.android.settings.privacy.PrivacyDashboardFragment" />
         </activity>
@@ -1575,19 +1579,12 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.FINGERPRINT_ENROLL" />
             </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.dismiss"
-                android:value="5,9,30" />
             <meta-data android:name="com.android.settings.require_feature"
                 android:value="android.hardware.fingerprint" />
             <meta-data android:name="com.android.settings.title"
                 android:resource="@string/suggestion_additional_fingerprints" />
             <meta-data android:name="com.android.settings.summary"
                 android:resource="@string/suggestion_additional_fingerprints_summary" />
-            <meta-data android:name="com.android.settings.icon_tintable" android:value="true" />
         </activity>
 
         <!-- Note this must not be exported since it returns the password in the intent -->
@@ -1651,8 +1648,7 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
             </intent-filter>
-            <meta-data android:name="com.android.settings.dismiss"
-                       android:value="2,6,30" />
+            <meta-data android:name="com.android.settings.dismiss" android:value="2," />
             <meta-data android:name="com.android.settings.require_feature"
                 android:value="android.hardware.fingerprint" />
             <meta-data android:name="com.android.settings.title"
diff --git a/res/drawable/ic_face_header.xml b/res/drawable/ic_face_header.xml
index 4493d66..0bf2c07 100644
--- a/res/drawable/ic_face_header.xml
+++ b/res/drawable/ic_face_header.xml
@@ -15,8 +15,9 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="24dp"
-    android:width="24dp"
+    android:height="32dp"
+    android:width="32dp"
+    android:tint="?android:attr/colorPrimary"
     android:viewportWidth="24"
     android:viewportHeight="24">
     <path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 71ce0ad..a626205 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -140,6 +140,46 @@
                     android:labelFor="@+id/routes"/>
             <EditText style="@style/vpn_value" android:id="@+id/routes"
                     android:hint="@string/vpn_not_used"/>
+
+            <TextView android:id="@+id/vpn_proxy_settings_title"
+                      style="@style/vpn_label"
+                      android:text="@string/proxy_settings_title"
+                      android:labelFor="@+id/vpn_proxy_settings" />
+
+            <Spinner android:id="@+id/vpn_proxy_settings"
+                     style="@style/vpn_value"
+                     android:prompt="@string/proxy_settings_title"
+                     android:entries="@array/vpn_proxy_settings" />
+
+            <LinearLayout
+                android:id="@+id/vpn_proxy_fields"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone" >
+
+                <TextView
+                    style="@style/vpn_label"
+                    android:text="@string/proxy_hostname_label"
+                    android:labelFor="@+id/vpn_proxy_host" />
+
+                <EditText
+                    android:id="@+id/vpn_proxy_host"
+                    style="@style/vpn_value"
+                    android:hint="@string/proxy_hostname_hint"
+                    android:inputType="textNoSuggestions" />
+
+                <TextView
+                    style="@style/vpn_label"
+                    android:text="@string/proxy_port_label"
+                    android:labelFor="@+id/vpn_proxy_port" />
+
+                <EditText
+                    android:id="@+id/vpn_proxy_port"
+                    style="@style/vpn_value"
+                    android:hint="@string/proxy_port_hint"
+                    android:inputType="number" />
+            </LinearLayout>
         </LinearLayout>
 
         <LinearLayout android:id="@+id/login"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 6a03582..dc91f22 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -931,6 +931,14 @@
         <item>IPSec VPN with certificates and hybrid authentication</item>
     </string-array>
 
+    <!-- VPN proxy settings. -->
+    <string-array name="vpn_proxy_settings">
+        <!-- No HTTP proxy is used for the current VPN [CHAR LIMIT=25] -->
+        <item>None</item>
+        <!-- Manual HTTP proxy settings are used for the current VPN [CHAR LIMIT=25] -->
+        <item>Manual</item>
+    </string-array>
+
     <!-- Match this with the constants in LegacyVpnInfo. --> <skip />
     <!-- Status for a VPN network. [CHAR LIMIT=100] -->
     <string-array name="vpn_states">
diff --git a/res/xml/mobile_network_list.xml b/res/xml/mobile_network_list.xml
index 5bffa2f..b72540f 100644
--- a/res/xml/mobile_network_list.xml
+++ b/res/xml/mobile_network_list.xml
@@ -24,7 +24,10 @@
         android:title="@string/mobile_network_list_add_more"
         android:icon="@drawable/ic_menu_add"
         android:order="100" >
-        <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
+        <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION">
+            <extra android:name="android.telephony.euicc.extra.FORCE_PROVISION"
+                   android:value="true"/>
+        </intent>
     </Preference>
 
 </PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/BalanceSeekBar.java b/src/com/android/settings/accessibility/BalanceSeekBar.java
index e18a593..b108e18 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBar.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBar.java
@@ -28,6 +28,8 @@
 import android.util.AttributeSet;
 import android.widget.SeekBar;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settings.R;
 
 /**
@@ -37,14 +39,13 @@
  * Updates Settings.System for balance on progress changed.
  */
 public class BalanceSeekBar extends SeekBar {
-    private static final String TAG = "BalanceSeekBar";
     private final Context mContext;
     private final Object mListenerLock = new Object();
     private OnSeekBarChangeListener mOnSeekBarChangeListener;
     private final OnSeekBarChangeListener mProxySeekBarListener = new OnSeekBarChangeListener() {
         @Override
         public void onStopTrackingTouch(SeekBar seekBar) {
-            synchronized(mListenerLock) {
+            synchronized (mListenerLock) {
                 if (mOnSeekBarChangeListener != null) {
                     mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
                 }
@@ -53,7 +54,7 @@
 
         @Override
         public void onStartTrackingTouch(SeekBar seekBar) {
-            synchronized(mListenerLock) {
+            synchronized (mListenerLock) {
                 if (mOnSeekBarChangeListener != null) {
                     mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
                 }
@@ -79,7 +80,7 @@
 
             // after adjusting the seekbar, notify downstream listener.
             // note that progress may have been adjusted in the code above to mCenter.
-            synchronized(mListenerLock) {
+            synchronized (mListenerLock) {
                 if (mOnSeekBarChangeListener != null) {
                     mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
                 }
@@ -88,7 +89,8 @@
     };
 
     // Percentage of max to be used as a snap to threshold
-    private static final float SNAP_TO_PERCENTAGE = 0.03f;
+    @VisibleForTesting
+    static final float SNAP_TO_PERCENTAGE = 0.03f;
     private final Paint mCenterMarkerPaint;
     private final Rect mCenterMarkerRect;
     // changed in setMax()
@@ -122,7 +124,7 @@
 
     @Override
     public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
-        synchronized(mListenerLock) {
+        synchronized (mListenerLock) {
             mOnSeekBarChangeListener = listener;
         }
     }
@@ -148,5 +150,10 @@
         canvas.restore();
         super.onDraw(canvas);
     }
+
+    @VisibleForTesting
+    OnSeekBarChangeListener getProxySeekBarListener() {
+        return mProxySeekBarListener;
+    }
 }
 
diff --git a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
index a40282c..b03c8ab 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
@@ -34,7 +34,9 @@
 
 /** A slider preference that directly controls audio balance **/
 public class BalanceSeekBarPreference extends SeekBarPreference {
-    private static final String TAG = "BalanceSeekBarPreference";
+    private static final int BALANCE_CENTER_VALUE = 100;
+    private static final int BALANCE_MAX_VALUE = 200;
+
     private final Context mContext;
     private BalanceSeekBar mSeekBar;
     private ImageView mIconView;
@@ -62,9 +64,9 @@
         final float balance = Settings.System.getFloatForUser(
                 mContext.getContentResolver(), Settings.System.MASTER_BALANCE,
                 0.f /* default */, UserHandle.USER_CURRENT);
-        // Rescale balance to range 0-200 centered at 100.
-        mSeekBar.setMax(200);
-        mSeekBar.setProgress((int)(balance * 100.f) + 100);
+        // Rescale balance to range 0-BALANCE_MAX_VALUE centered at BALANCE_MAX_VALUE / 2.
+        mSeekBar.setMax(BALANCE_MAX_VALUE);
+        mSeekBar.setProgress((int) (balance * 100.f) + BALANCE_CENTER_VALUE);
         mSeekBar.setEnabled(isEnabled());
     }
 }
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 39a7a80..1b41240 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -41,19 +41,19 @@
         super.onCreate(savedInstanceState);
 
         final PackageManager pm = getApplicationContext().getPackageManager();
-        Intent intent;
+        Intent intent = null;
 
         // This logic may have to be modified on devices with multiple biometrics.
         if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
             intent = getFingerprintEnrollIntent();
         } else if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
             intent = getFaceEnrollIntent();
-        } else {
-            intent = new Intent();
         }
 
-        intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
-        startActivity(intent);
+        if (intent != null) {
+            intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            startActivity(intent);
+        }
         finish();
     }
 
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index d7f2c97..097ffe2 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -21,11 +21,14 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.password.ChooseLockGeneric;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.password.SetupChooseLockGeneric;
 
@@ -202,7 +205,14 @@
 
     protected Intent getChooseLockIntent() {
         if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+            // Default to PIN lock in setup wizard
             Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+                intent.putExtra(
+                        LockPatternUtils.PASSWORD_TYPE_KEY,
+                        DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+                intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+            }
             WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
             return intent;
         } else {
@@ -212,23 +222,21 @@
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        final boolean isResultFinished = resultCode == RESULT_FINISHED;
-        final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
         if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
-            if (isResultFinished || resultCode == RESULT_SKIP) {
-                setResult(result, data);
+            if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP) {
+                setResult(resultCode, data);
                 finish();
                 return;
             }
         } else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
-            if (isResultFinished) {
+            if (resultCode == RESULT_FINISHED) {
                 updatePasswordQuality();
                 mToken = data.getByteArrayExtra(
                         ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
                 overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
                 return;
             } else {
-                setResult(result, data);
+                setResult(resultCode, data);
                 finish();
             }
         } else if (requestCode == CONFIRM_REQUEST) {
@@ -236,7 +244,7 @@
                 mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
                 overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
             } else {
-                setResult(result, data);
+                setResult(resultCode, data);
                 finish();
             }
         } else if (requestCode == LEARN_MORE_REQUEST) {
@@ -249,6 +257,11 @@
         finish();
     }
 
+    protected void onSkipButtonClick(View view) {
+        setResult(RESULT_SKIP);
+        finish();
+    }
+
     @Override
     protected void initViews() {
         super.initViews();
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 8d4c82e..5f2b675 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -60,14 +60,25 @@
         mSwitchDiversity = findViewById(R.id.toggle_diversity);
 
         mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
-        mFooterBarMixin.setSecondaryButton(
-                new FooterButton.Builder(this)
-                        .setText(R.string.security_settings_face_enroll_introduction_cancel)
-                        .setListener(this::onCancelButtonClick)
-                        .setButtonType(FooterButton.ButtonType.SKIP)
-                        .setTheme(R.style.SudGlifButton_Secondary)
-                        .build()
-        );
+        if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+            mFooterBarMixin.setSecondaryButton(
+                    new FooterButton.Builder(this)
+                            .setText(R.string.skip_label)
+                            .setListener(this::onSkipButtonClick)
+                            .setButtonType(FooterButton.ButtonType.SKIP)
+                            .setTheme(R.style.SudGlifButton_Secondary)
+                            .build()
+            );
+        } else {
+            mFooterBarMixin.setSecondaryButton(
+                    new FooterButton.Builder(this)
+                            .setText(R.string.security_settings_face_enroll_introduction_cancel)
+                            .setListener(this::onCancelButtonClick)
+                            .setButtonType(FooterButton.ButtonType.CANCEL)
+                            .setTheme(R.style.SudGlifButton_Secondary)
+                            .build()
+            );
+        }
 
         mFooterBarMixin.setPrimaryButton(
                 new FooterButton.Builder(this)
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index f2ffe22..6c2da07 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -23,7 +23,6 @@
     public static final String AUDIO_SWITCHER_SETTINGS = "settings_audio_switcher";
     public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
     public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
-    public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
     public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
     public static final String SLICE_INJECTION = "settings_slice_injection";
     public static final String MAINLINE_MODULE = "settings_mainline_module";
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 3320be0..99fe219 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -16,11 +16,14 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import android.annotation.ColorInt;
 import android.app.PendingIntent;
 import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -87,6 +90,9 @@
 
     @Override
     public Slice getSlice() {
+        // Reload theme for switching dark mode on/off
+        mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */);
+
         final IconCompat icon = IconCompat.createWithResource(mContext,
                 com.android.internal.R.drawable.ic_settings_bluetooth);
         final CharSequence title = mContext.getText(R.string.bluetooth_devices);
@@ -98,7 +104,7 @@
                 ListBuilder.ICON_IMAGE, title);
         final ListBuilder listBuilder =
                 new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
-                        .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
+                        .setAccentColor(COLOR_NOT_TINTED);
 
         // Get row builders by Bluetooth devices.
         final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder();
@@ -207,13 +213,23 @@
     IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
         final Pair<Drawable, String> pair = BluetoothUtils
                 .getBtClassDrawableWithDescription(mContext, device);
+        final Drawable drawable = pair.first;
 
-        if (pair.first != null) {
-            return Utils.createIconWithDrawable(pair.first);
-        } else {
+        // Use default bluetooth icon if can't get icon.
+        if (drawable == null) {
             return IconCompat.createWithResource(mContext,
                     com.android.internal.R.drawable.ic_settings_bluetooth);
         }
+
+        // Tint icon: Accent color for connected state; Disable color for busy state.
+        @ColorInt int color = Utils.getColorAccentDefaultColor(mContext);
+        if (device.isBusy()) {
+            color = Utils.getDisabled(mContext,
+                    Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal));
+        }
+        drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
+
+        return Utils.createIconWithDrawable(drawable);
     }
 
     private List<ListBuilder.RowBuilder> getBluetoothRowBuilder() {
@@ -227,7 +243,7 @@
                     .setSubtitle(bluetoothDevice.getConnectionSummary());
 
             if (bluetoothDevice.isConnectedA2dpDevice()) {
-                // For available media devices, the primary action is to active audio stream and
+                // For available media devices, the primary action is to activate audio stream and
                 // add setting icon to the end to link detail page.
                 rowBuilder.setPrimaryAction(buildMediaBluetoothAction(bluetoothDevice));
                 rowBuilder.addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice));
@@ -260,7 +276,7 @@
     SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
         return SliceAction.createDeeplink(
                 getBluetoothDetailIntent(bluetoothDevice),
-                IconCompat.createWithResource(mContext, R.drawable.ic_settings_24dp),
+                IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent),
                 ListBuilder.ICON_IMAGE,
                 bluetoothDevice.getName());
     }
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index dd282c6..a1fef4c 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -29,6 +29,7 @@
 import android.telephony.euicc.EuiccManager;
 
 import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.network.telephony.MobileNetworkActivity;
 import com.android.settings.widget.AddPreference;
 import com.android.settingslib.Utils;
@@ -43,7 +44,8 @@
 import androidx.preference.PreferenceScreen;
 
 public class MobileNetworkSummaryController extends AbstractPreferenceController implements
-        SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
+        SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver,
+        PreferenceControllerMixin {
     private static final String TAG = "MobileNetSummaryCtlr";
 
     private static final String KEY = "mobile_network_list";
@@ -74,8 +76,10 @@
         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
         mTelephonyMgr = mContext.getSystemService(TelephonyManager.class);
         mEuiccManager = mContext.getSystemService(EuiccManager.class);
-        mChangeListener = new SubscriptionsChangeListener(context, this);
-        lifecycle.addObserver(this);
+        if (lifecycle != null) {
+          mChangeListener = new SubscriptionsChangeListener(context, this);
+          lifecycle.addObserver(this);
+        }
     }
 
     @OnLifecycleEvent(ON_RESUME)
@@ -116,6 +120,7 @@
 
     private void startAddSimFlow() {
         final Intent intent = new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
+        intent.putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true);
         mContext.startActivity(intent);
     }
 
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index d120062..8d40175 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -143,6 +143,8 @@
     @Override
     public void onStart() {
         super.onStart();
+        initComponents();
+        updateUiForArguments();
         updateEmptyView();
         updateUiForServiceState();
     }
@@ -158,20 +160,9 @@
     @Override
     public void onStop() {
         super.onStop();
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        initComponents();
-        updateUiForArguments();
-    }
-
-    @Override
-    public void onDestroyView() {
-        super.onDestroyView();
         mSwitchBar.removeOnSwitchChangeListener(this);
         mSwitchBar.hide();
+        mPrintersAdapter.unregisterAdapterDataObserver(mDataObserver);
     }
 
     private void onPreferenceToggled(String preferenceKey, boolean enabled) {
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index de2755e..07e957d 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 import android.content.DialogInterface;
+import android.net.Proxy;
+import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.security.Credentials;
@@ -67,6 +69,9 @@
     private TextView mSearchDomains;
     private TextView mDnsServers;
     private TextView mRoutes;
+    private Spinner mProxySettings;
+    private TextView mProxyHost;
+    private TextView mProxyPort;
     private CheckBox mMppe;
     private TextView mL2tpSecret;
     private TextView mIpsecIdentifier;
@@ -105,6 +110,9 @@
         mSearchDomains = (TextView) mView.findViewById(R.id.search_domains);
         mDnsServers = (TextView) mView.findViewById(R.id.dns_servers);
         mRoutes = (TextView) mView.findViewById(R.id.routes);
+        mProxySettings = (Spinner) mView.findViewById(R.id.vpn_proxy_settings);
+        mProxyHost = (TextView) mView.findViewById(R.id.vpn_proxy_host);
+        mProxyPort = (TextView) mView.findViewById(R.id.vpn_proxy_port);
         mMppe = (CheckBox) mView.findViewById(R.id.mppe);
         mL2tpSecret = (TextView) mView.findViewById(R.id.l2tp_secret);
         mIpsecIdentifier = (TextView) mView.findViewById(R.id.ipsec_identifier);
@@ -128,6 +136,11 @@
         mSearchDomains.setText(mProfile.searchDomains);
         mDnsServers.setText(mProfile.dnsServers);
         mRoutes.setText(mProfile.routes);
+        if (mProfile.proxy != null) {
+            mProxyHost.setText(mProfile.proxy.getHost());
+            int port = mProfile.proxy.getPort();
+            mProxyPort.setText(port == 0 ? "" : Integer.toString(port));
+        }
         mMppe.setChecked(mProfile.mppe);
         mL2tpSecret.setText(mProfile.l2tpSecret);
         mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
@@ -153,6 +166,9 @@
         mPassword.addTextChangedListener(this);
         mDnsServers.addTextChangedListener(this);
         mRoutes.addTextChangedListener(this);
+        mProxySettings.setOnItemSelectedListener(this);
+        mProxyHost.addTextChangedListener(this);
+        mProxyPort.addTextChangedListener(this);
         mIpsecSecret.addTextChangedListener(this);
         mIpsecUserCert.setOnItemSelectedListener(this);
         mShowOptions.setOnClickListener(this);
@@ -175,7 +191,8 @@
 
             // Switch to advanced view immediately if any advanced options are on
             if (!mProfile.searchDomains.isEmpty() || !mProfile.dnsServers.isEmpty() ||
-                    !mProfile.routes.isEmpty()) {
+                    !mProfile.routes.isEmpty() || (mProfile.proxy != null &&
+                    (!mProfile.proxy.getHost().isEmpty() || mProfile.proxy.getPort() != 0))) {
                 showAdvancedOptions();
             }
 
@@ -246,6 +263,8 @@
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
         if (parent == mType) {
             changeType(position);
+        } else if (parent == mProxySettings) {
+            updateProxyFieldsVisibility(position);
         }
         updateUiControls();
     }
@@ -271,6 +290,7 @@
      * These include:
      * "Always-on VPN" checkbox
      * Reason for "Always-on VPN" being disabled, when necessary
+     * Proxy info if manually configured
      * "Save account information" checkbox
      * "Save" and "Connect" buttons
      */
@@ -298,6 +318,13 @@
             mAlwaysOnInvalidReason.setVisibility(View.VISIBLE);
         }
 
+        // Show proxy fields if any proxy field is filled.
+        if (mProfile.proxy != null && (!mProfile.proxy.getHost().isEmpty() ||
+                mProfile.proxy.getPort() != 0)) {
+            mProxySettings.setSelection(VpnProfile.PROXY_MANUAL);
+            updateProxyFieldsVisibility(VpnProfile.PROXY_MANUAL);
+        }
+
         // Save account information
         if (mAlwaysOnVpn.isChecked()) {
             mSaveLogin.setChecked(true);
@@ -311,6 +338,11 @@
         getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validate(mEditing));
     }
 
+    private void updateProxyFieldsVisibility(int position) {
+        final int visible = position == VpnProfile.PROXY_MANUAL ? View.VISIBLE : View.GONE;
+        mView.findViewById(R.id.vpn_proxy_fields).setVisibility(visible);
+    }
+
     private void showAdvancedOptions() {
         mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
         mShowOptions.setVisibility(View.GONE);
@@ -361,6 +393,11 @@
                 !validateAddresses(mRoutes.getText().toString(), true)) {
             return false;
         }
+
+        if (!validateProxy()) {
+            return false;
+        }
+
         switch (mType.getSelectedItemPosition()) {
             case VpnProfile.TYPE_PPTP:
             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
@@ -435,6 +472,10 @@
         return mEditing;
     }
 
+    boolean hasProxy() {
+        return mProxySettings.getSelectedItemPosition() == VpnProfile.PROXY_MANUAL;
+    }
+
     VpnProfile getProfile() {
         // First, save common fields.
         VpnProfile profile = new VpnProfile(mProfile.key);
@@ -446,7 +487,16 @@
         profile.searchDomains = mSearchDomains.getText().toString().trim();
         profile.dnsServers = mDnsServers.getText().toString().trim();
         profile.routes = mRoutes.getText().toString().trim();
-
+        if (hasProxy()) {
+            String proxyHost = mProxyHost.getText().toString().trim();
+            String proxyPort = mProxyPort.getText().toString().trim();
+            // 0 is a last resort default, but the interface validates that the proxy port is
+            // present and non-zero.
+            int port = proxyPort.isEmpty() ? 0 : Integer.parseInt(proxyPort);
+            profile.proxy = new ProxyInfo(proxyHost, port, null);
+        } else {
+            profile.proxy = null;
+        }
         // Then, save type-specific fields.
         switch (profile.type) {
             case VpnProfile.TYPE_PPTP:
@@ -483,4 +533,15 @@
         profile.saveLogin = mSaveLogin.isChecked() || (mEditing && hasLogin);
         return profile;
     }
+
+    private boolean validateProxy() {
+        if (!hasProxy()) {
+            return true;
+        }
+
+        final String host = mProxyHost.getText().toString().trim();
+        final String port = mProxyPort.getText().toString().trim();
+        return Proxy.validate(host, port, "") == Proxy.PROXY_VALID;
+    }
+
 }
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index e7db5db..916d330 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -248,8 +248,8 @@
         mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings);
         mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
         mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
-        if (FeatureFlagUtils.isEnabled(mContext,
-                com.android.settings.core.FeatureFlags.WIFI_MAC_RANDOMIZATION)) {
+        if (mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported)) {
             View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
             privacySettingsLayout.setVisibility(View.VISIBLE);
         }
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index b79f2d4..97ddc53 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -58,8 +58,9 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_MAC_RANDOMIZATION)
-                ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported) ?
+                AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java
new file mode 100644
index 0000000..ba7bd2c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.preference.PreferenceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BalanceSeekBarPreferenceTest {
+    private static final int BALANCE_CENTER_VALUE = 100;
+    private static final int BALANCE_MAX_VALUE = 200;
+
+    private Context mContext;
+    private AttributeSet mAttrs;
+    private PreferenceViewHolder mHolder;
+    private BalanceSeekBar mSeekBar;
+    private BalanceSeekBarPreference mSeekBarPreference;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mSeekBarPreference = new BalanceSeekBarPreference(mContext, mAttrs);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        final View view =
+                inflater.inflate(mSeekBarPreference.getLayoutResource(),
+                        new LinearLayout(mContext), false);
+        mHolder = PreferenceViewHolder.createInstanceForTests(view);
+        mSeekBar = (BalanceSeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+    }
+
+    @Test
+    public void seekBarPreferenceOnBindViewHolder_shouldInitSeekBarValue() {
+        mSeekBarPreference.onBindViewHolder(mHolder);
+
+        assertThat(mSeekBar.getMax()).isEqualTo(BALANCE_MAX_VALUE);
+        assertThat(mSeekBar.getProgress()).isEqualTo(BALANCE_CENTER_VALUE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java
new file mode 100644
index 0000000..e0dc681
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BalanceSeekBarTest {
+    // Fix the maximum process value to 200 for testing the BalanceSeekBar.
+    // It affects the SeekBar value of center(100) and snapThreshold(200 * SNAP_TO_PERCENTAGE).
+    private static final int MAX_PROGRESS_VALUE = 200;
+
+    private Context mContext;
+    private AttributeSet mAttrs;
+    private BalanceSeekBar mSeekBar;
+    private BalanceSeekBar.OnSeekBarChangeListener mProxySeekBarListener;
+    private SeekBar.OnSeekBarChangeListener mockSeekBarChangeListener;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mSeekBar = new BalanceSeekBar(mContext, mAttrs);
+        mProxySeekBarListener = mSeekBar.getProxySeekBarListener();
+        mockSeekBarChangeListener = mock(SeekBar.OnSeekBarChangeListener.class);
+        mSeekBar.setOnSeekBarChangeListener(mockSeekBarChangeListener);
+    }
+
+    @Test
+    public void onStartTrackingTouch_shouldInvokeMethod() {
+        mProxySeekBarListener.onStartTrackingTouch(mSeekBar);
+
+        verify(mockSeekBarChangeListener, times(1)).onStartTrackingTouch(mSeekBar);
+    }
+
+    @Test
+    public void onStopTrackingTouch_shouldInvokeMethod() {
+        mProxySeekBarListener.onStopTrackingTouch(mSeekBar);
+
+        verify(mockSeekBarChangeListener, times(1)).onStopTrackingTouch(mSeekBar);
+    }
+
+    @Test
+    public void onProgressChanged_shouldInvokeMethod() {
+        // Assign the test value of SeekBar progress
+        mProxySeekBarListener.onProgressChanged(mSeekBar, MAX_PROGRESS_VALUE, true);
+
+        verify(mockSeekBarChangeListener, times(1)).onProgressChanged(eq(mSeekBar),
+                eq(MAX_PROGRESS_VALUE), eq(true));
+    }
+
+    @Test
+    public void setMaxTest_shouldSetValue() {
+        mSeekBar.setMax(MAX_PROGRESS_VALUE);
+
+        assertThat(getBalanceSeekBarCenter(mSeekBar)).isEqualTo(MAX_PROGRESS_VALUE / 2);
+        assertThat(getBalanceSeekBarSnapThreshold(mSeekBar)).isEqualTo(
+                MAX_PROGRESS_VALUE * BalanceSeekBar.SNAP_TO_PERCENTAGE);
+    }
+
+    @Test
+    public void setProgressTest_shouldSnapToCenter() {
+        // Assign the test value of SeekBar progress within the threshold (94-106 in this case).
+        final int progressWithinThreshold = 102;
+        mSeekBar.setMax(MAX_PROGRESS_VALUE);
+        mSeekBar.setProgress(progressWithinThreshold + 10); //set progress which is over threshold.
+        mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithinThreshold, true);
+
+        assertThat(mSeekBar.getProgress()).isEqualTo(getBalanceSeekBarCenter(mSeekBar));
+    }
+
+    @Test
+    public void setProgressTest_shouldMaintainInputValue() {
+        // Assign the test value of SeekBar progress without the threshold.
+        final int progressWithoutThreshold = 107;
+        mSeekBar.setMax(MAX_PROGRESS_VALUE);
+        mSeekBar.setProgress(progressWithoutThreshold);
+        mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithoutThreshold, true);
+
+        assertThat(mSeekBar.getProgress()).isEqualTo(progressWithoutThreshold);
+    }
+
+    // method to get the center from BalanceSeekBar for testing setMax().
+    private int getBalanceSeekBarCenter(BalanceSeekBar seekBar) {
+        return seekBar.getMax() / 2;
+    }
+
+    // method to get the snapThreshold from BalanceSeekBar for testing setMax().
+    private float getBalanceSeekBarSnapThreshold(BalanceSeekBar seekBar) {
+        return seekBar.getMax() * BalanceSeekBar.SNAP_TO_PERCENTAGE;
+    }
+}