Merge "IPC StrictMode"
diff --git a/api/current.txt b/api/current.txt
index e3caa79..81ecceb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3690,11 +3690,11 @@
     method public <T extends android.view.View> T findViewById(@IdRes int);
     method public void finish();
     method public void finishActivity(int);
-    method public void finishActivityFromChild(@NonNull android.app.Activity, int);
+    method @Deprecated public void finishActivityFromChild(@NonNull android.app.Activity, int);
     method public void finishAffinity();
     method public void finishAfterTransition();
     method public void finishAndRemoveTask();
-    method public void finishFromChild(android.app.Activity);
+    method @Deprecated public void finishFromChild(android.app.Activity);
     method @Nullable public android.app.ActionBar getActionBar();
     method public final android.app.Application getApplication();
     method @Nullable public android.content.ComponentName getCallingActivity();
@@ -3743,7 +3743,7 @@
     method @Deprecated public final android.database.Cursor managedQuery(android.net.Uri, String[], String, String[], String);
     method public boolean moveTaskToBack(boolean);
     method public boolean navigateUpTo(android.content.Intent);
-    method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
+    method @Deprecated public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
     method @CallSuper public void onActionModeFinished(android.view.ActionMode);
     method @CallSuper public void onActionModeStarted(android.view.ActionMode);
     method public void onActivityReenter(int, android.content.Intent);
@@ -3787,7 +3787,7 @@
     method public void onMultiWindowModeChanged(boolean, android.content.res.Configuration);
     method @Deprecated public void onMultiWindowModeChanged(boolean);
     method public boolean onNavigateUp();
-    method public boolean onNavigateUpFromChild(android.app.Activity);
+    method @Deprecated public boolean onNavigateUpFromChild(android.app.Activity);
     method protected void onNewIntent(android.content.Intent);
     method public boolean onOptionsItemSelected(@NonNull android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
@@ -3894,16 +3894,16 @@
     method @Nullable public android.view.ActionMode startActionMode(android.view.ActionMode.Callback, int);
     method public void startActivityForResult(@RequiresPermission android.content.Intent, int);
     method public void startActivityForResult(@RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
-    method public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int);
-    method public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
+    method @Deprecated public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int);
+    method @Deprecated public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
     method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int);
     method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
     method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int);
     method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int, @Nullable android.os.Bundle);
     method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
-    method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
-    method public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int, @Nullable android.os.Bundle) throws android.content.IntentSender.SendIntentException;
+    method @Deprecated public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
+    method @Deprecated public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int, @Nullable android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public void startLocalVoiceInteraction(android.os.Bundle);
     method public void startLockTask();
     method @Deprecated public void startManagingCursor(android.database.Cursor);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f4df6b7..15c6425 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4341,7 +4341,9 @@
      * The default implementation simply calls onNavigateUp() on this activity (the parent).
      *
      * @param child The activity making the call.
+     * @deprecated Use {@link #onNavigateUp()} instead.
      */
+    @Deprecated
     public boolean onNavigateUpFromChild(Activity child) {
         return onNavigateUp();
     }
@@ -5768,7 +5770,10 @@
      *
      * @see #startActivity
      * @see #startActivityForResult
+     * @deprecated Use {@code androidx.fragment.app.FragmentActivity#startActivityFromFragment(
+     * androidx.fragment.app.Fragment,Intent,int)}
      */
+    @Deprecated
     public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
             int requestCode) {
         startActivityFromChild(child, intent, requestCode, null);
@@ -5792,7 +5797,10 @@
      *
      * @see #startActivity
      * @see #startActivityForResult
+     * @deprecated Use {@code androidx.fragment.app.FragmentActivity#startActivityFromFragment(
+     * androidx.fragment.app.Fragment,Intent,int,Bundle)}
      */
+    @Deprecated
     public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
             int requestCode, @Nullable Bundle options) {
         options = transferSpringboardActivityOptions(options);
@@ -5821,8 +5829,8 @@
      * @see Fragment#startActivity
      * @see Fragment#startActivityForResult
      *
-     * @deprecated Use {@link android.support.v4.app.FragmentActivity#startActivityFromFragment(
-     * android.support.v4.app.Fragment,Intent,int)}
+     * @deprecated Use {@code androidx.fragment.app.FragmentActivity#startActivityFromFragment(
+     * androidx.fragment.app.Fragment,Intent,int)}
      */
     @Deprecated
     public void startActivityFromFragment(@NonNull Fragment fragment,
@@ -5850,8 +5858,8 @@
      * @see Fragment#startActivity
      * @see Fragment#startActivityForResult
      *
-     * @deprecated Use {@link android.support.v4.app.FragmentActivity#startActivityFromFragment(
-     * android.support.v4.app.Fragment,Intent,int,Bundle)}
+     * @deprecated Use {@code androidx.fragment.app.FragmentActivity#startActivityFromFragment(
+     * androidx.fragment.app.Fragment,Intent,int,Bundle)}
      */
     @Deprecated
     public void startActivityFromFragment(@NonNull Fragment fragment,
@@ -5859,10 +5867,7 @@
         startActivityForResult(fragment.mWho, intent, requestCode, options);
     }
 
-    /**
-     * @hide
-     */
-    public void startActivityAsUserFromFragment(@NonNull Fragment fragment,
+    private void startActivityAsUserFromFragment(@NonNull Fragment fragment,
             @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options,
             UserHandle user) {
         startActivityForResultAsUser(intent, fragment.mWho, requestCode, options, user);
@@ -5903,7 +5908,10 @@
     /**
      * Same as calling {@link #startIntentSenderFromChild(Activity, IntentSender,
      * int, Intent, int, int, int, Bundle)} with no options.
+     * @deprecated Use {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
+     * instead.
      */
+    @Deprecated
     public void startIntentSenderFromChild(Activity child, IntentSender intent,
             int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
             int extraFlags)
@@ -5917,7 +5925,11 @@
      * taking a IntentSender; see
      * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
      * for more information.
+     * @deprecated Use
+     * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int, Bundle)}
+     * instead.
      */
+    @Deprecated
     public void startIntentSenderFromChild(Activity child, IntentSender intent,
             int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
             int extraFlags, @Nullable Bundle options)
@@ -5927,17 +5939,15 @@
     }
 
     /**
-     * Like {@link #startIntentSenderFromChild}, but taking a Fragment; see
+     * Like {@link #startIntentSender}, but taking a Fragment; see
      * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
      * for more information.
-     *
-     * @hide
      */
-    public void startIntentSenderFromChildFragment(Fragment child, IntentSender intent,
+    private void startIntentSenderFromFragment(Fragment fragment, IntentSender intent,
             int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
-            int extraFlags, @Nullable Bundle options)
+            @Nullable Bundle options)
             throws IntentSender.SendIntentException {
-        startIntentSenderForResultInner(intent, child.mWho, requestCode, fillInIntent,
+        startIntentSenderForResultInner(intent, fragment.mWho, requestCode, fillInIntent,
                 flagsMask, flagsValues, options);
     }
 
@@ -6279,7 +6289,9 @@
      * @param child The activity making the call.
      *
      * @see #finish
+     * @deprecated Use {@link #finish()} instead.
      */
+    @Deprecated
     public void finishFromChild(Activity child) {
         finish();
     }
@@ -6326,7 +6338,9 @@
      * @param child The activity making the call.
      * @param requestCode Request code that had been used to start the
      *                    activity.
+     * @deprecated Use {@link #finishActivity(int)} instead.
      */
+    @Deprecated
     public void finishActivityFromChild(@NonNull Activity child, int requestCode) {
         try {
             ActivityTaskManager.getService()
@@ -7569,7 +7583,9 @@
      * @return true if up navigation successfully reached the activity indicated by upIntent and
      *         upIntent was delivered to it. false if an instance of the indicated activity could
      *         not be found and this activity was simply finished normally.
+     * @deprecated Use {@link #navigateUpTo(Intent)} instead.
      */
+    @Deprecated
     public boolean navigateUpToFromChild(Activity child, Intent upIntent) {
         return navigateUpTo(upIntent);
     }
@@ -8623,8 +8639,8 @@
                 startIntentSenderForResultInner(intent, fragment.mWho, requestCode, fillInIntent,
                         flagsMask, flagsValues, options);
             } else if (options != null) {
-                mParent.startIntentSenderFromChildFragment(fragment, intent, requestCode,
-                        fillInIntent, flagsMask, flagsValues, extraFlags, options);
+                mParent.startIntentSenderFromFragment(fragment, intent, requestCode,
+                        fillInIntent, flagsMask, flagsValues, options);
             }
         }
 
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 9720e9f..588acee 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1670,7 +1670,6 @@
      *
      * @see Activity#startActivity(Intent)
      * @see Activity#startActivityForResult(Intent, int)
-     * @see Activity#startActivityFromChild
      *
      * {@hide}
      */
@@ -1815,7 +1814,6 @@
      * 
      * @see Activity#startActivity(Intent)
      * @see Activity#startActivityForResult(Intent, int)
-     * @see Activity#startActivityFromChild
      * 
      * {@hide}
      */
@@ -1883,7 +1881,6 @@
      *
      * @see Activity#startActivity(Intent)
      * @see Activity#startActivityForResult(Intent, int)
-     * @see Activity#startActivityFromChild
      *
      * {@hide}
      */
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index f297c06..9dbfbc7 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1033,12 +1033,13 @@
 
     /** @hide */
     public final void setTransportLoggingEnabled(boolean enabled) {
-        if (mTransport != null) {
-            if (enabled) {
-                mTransport.mInterface = new LoggingContentInterface(getClass().getSimpleName(), this);
-            } else {
-                mTransport.mInterface = this;
-            }
+        if (mTransport == null) {
+            return;
+        }
+        if (enabled) {
+            mTransport.mInterface = new LoggingContentInterface(getClass().getSimpleName(), this);
+        } else {
+            mTransport.mInterface = this;
         }
     }
 
diff --git a/core/java/android/content/pm/PackageList.java b/core/java/android/content/pm/PackageList.java
index f781758..e3eb2c5 100644
--- a/core/java/android/content/pm/PackageList.java
+++ b/core/java/android/content/pm/PackageList.java
@@ -52,6 +52,13 @@
     }
 
     @Override
+    public void onPackageChanged(String packageName, int uid) {
+        if (mWrappedObserver != null) {
+            mWrappedObserver.onPackageChanged(packageName, uid);
+        }
+    }
+
+    @Override
     public void onPackageRemoved(String packageName, int uid) {
         if (mWrappedObserver != null) {
             mWrappedObserver.onPackageRemoved(packageName, uid);
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 3e130c5..c28cf8f 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -129,7 +129,7 @@
         public CameraLooper(int cameraId) {
             mCameraId = cameraId;
 
-            mThread = new Thread(this);
+            mThread = new Thread(this, "LegacyCameraLooper");
             mThread.start();
         }
 
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 4675600..d9000e4 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -114,7 +114,7 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public ApduServiceInfo(ResolveInfo info, String description,
+    public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
             ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
             boolean requiresUnlock, int bannerResource, int uid,
             String settingsActivityName, String offHost, String staticOffHost) {
@@ -124,7 +124,7 @@
         this.mDynamicAidGroups = new HashMap<String, AidGroup>();
         this.mOffHostName = offHost;
         this.mStaticOffHostName = staticOffHost;
-        this.mOnHost = (offHost == null);
+        this.mOnHost = onHost;
         this.mRequiresDeviceUnlock = requiresUnlock;
         for (AidGroup aidGroup : staticAidGroups) {
             this.mStaticAidGroups.put(aidGroup.category, aidGroup);
@@ -570,7 +570,7 @@
             int bannerResource = source.readInt();
             int uid = source.readInt();
             String settingsActivityName = source.readString();
-            return new ApduServiceInfo(info, description, staticAidGroups,
+            return new ApduServiceInfo(info, onHost, description, staticAidGroups,
                     dynamicAidGroups, requiresUnlock, bannerResource, uid,
                     settingsActivityName, offHostName, staticOffHostName);
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e486235..f573d87 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3495,6 +3495,14 @@
         };
 
         /**
+         * The user selected min refresh rate in frames per second.
+         *
+         * If this isn't set, 0 will be used.
+         * @hide
+         */
+        public static final String MIN_REFRESH_RATE = "min_refresh_rate";
+
+        /**
          * The user selected peak refresh rate in frames per second.
          *
          * If this isn't set, the system falls back to a device specific default.
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index be5d221..d62b979 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -62,8 +62,9 @@
 /**
  * Displays image resources, for example {@link android.graphics.Bitmap}
  * or {@link android.graphics.drawable.Drawable} resources.
- * ImageView is also commonly used to {@link #setImageTintMode(PorterDuff.Mode)
- * apply tints to an image} and handle {@link #setScaleType(ScaleType) image scaling}.
+ * ImageView is also commonly used to
+ * <a href="#setImageTintMode(android.graphics.PorterDuff.Mode)">apply tints to an image</a> and
+ * handle <a href="#setScaleType(android.widget.ImageView.ScaleType)">image scaling</a>.
  *
  * <p>
  * The following XML snippet is a common example of using an ImageView to display an image resource:
@@ -76,7 +77,8 @@
  *     &lt;ImageView
  *         android:layout_width="wrap_content"
  *         android:layout_height="wrap_content"
- *         android:src="@mipmap/ic_launcher"
+ *         android:src="@drawable/my_image"
+ *         android:contentDescription="@string/my_image_description"
  *         /&gt;
  * &lt;/LinearLayout&gt;
  * </pre>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 97b7ae9..eef780a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -94,6 +94,7 @@
                     Settings.System.VOLUME_VOICE, // deprecated since API 2?
                     Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
                     Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
+                    Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
                     Settings.System.PEAK_REFRESH_RATE // depends on hardware capabilities
                     );
 
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 90f7d48..2989676 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -20,6 +20,8 @@
 #include <SkRefCnt.h>
 #include <cutils/compiler.h>
 #include <minikin/MinikinFont.h>
+#include <string>
+#include <string_view>
 
 class SkFont;
 class SkTypeface;
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 6197c70..9e671b1 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -179,6 +179,10 @@
  *         <td>TV content rating system for Canada (French)</td>
  *     </tr>
  *     <tr>
+ *         <td>DTMB</td>
+ *         <td>DTMB content rating system</td>
+ *     </tr>
+ *     <tr>
  *         <td>DVB</td>
  *         <td>DVB content rating system</td>
  *     </tr>
@@ -199,10 +203,18 @@
  *         <td>TV content rating system for South Korea</td>
  *     </tr>
  *     <tr>
+ *         <td>NZ_TV</td>
+ *         <td>TV content rating system for New Zealand</td>
+ *     </tr>
+ *     <tr>
  *         <td>SG_TV</td>
  *         <td>TV content rating system for Singapore</td>
  *     </tr>
  *     <tr>
+ *         <td>TH_TV</td>
+ *         <td>TV content rating system for Thailand</td>
+ *     </tr>
+ *     <tr>
  *         <td>US_MV</td>
  *         <td>Movie content rating system for the United States</td>
  *     </tr>
@@ -356,6 +368,67 @@
  *         <td>Only to be viewed by adults</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="15">DTMB</td>
+ *         <td>DTMB_4</td>
+ *         <td>Recommended for ages 4 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_5</td>
+ *         <td>Recommended for ages 5 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_6</td>
+ *         <td>Recommended for ages 6 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_7</td>
+ *         <td>Recommended for ages 7 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_8</td>
+ *         <td>Recommended for ages 8 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_9</td>
+ *         <td>Recommended for ages 9 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_10</td>
+ *         <td>Recommended for ages 10 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_11</td>
+ *         <td>Recommended for ages 11 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_12</td>
+ *         <td>Recommended for ages 12 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_13</td>
+ *         <td>Recommended for ages 13 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_14</td>
+ *         <td>Recommended for ages 14 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_15</td>
+ *         <td>Recommended for ages 15 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_16</td>
+ *         <td>Recommended for ages 16 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_17</td>
+ *         <td>Recommended for ages 17 and over</td>
+ *     </tr>
+ *     <tr>
+ *         <td>DTMB_18</td>
+ *         <td>Recommended for ages 18 and over</td>
+ *     </tr>
+ *     <tr>
  *         <td valign="top" rowspan="15">DVB</td>
  *         <td>DVB_4</td>
  *         <td>Recommended for ages 4 and over</td>
@@ -648,6 +721,22 @@
  *         <td>For adults only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">NZ_TV</td>
+ *         <td>NZ_TV_G</td>
+ *         <td>Programmes which exclude material likely to be unsuitable for children. Programmes
+ *         may not necessarily be designed for child viewers but should not contain material likely
+ *         to alarm or distress them.</td>
+ *     </tr>
+ *     <tr>
+ *         <td>NZ_TV_PGR</td>
+ *         <td>Programmes containing material more suited for mature audiences but not necessarily
+ *         unsuitable for child viewers when subject to the guidance of a parent or an adult.</td>
+ *     </tr>
+ *     <tr>
+ *         <td>NZ_TV_AO</td>
+ *         <td>Programmes containing adult themes and directed primarily at mature audiences.</td>
+ *     </tr>
+ *     <tr>
  *         <td valign="top" rowspan="6">SG_TV</td>
  *         <td>SG_TV_G</td>
  *         <td>Suitable for all ages</td>
@@ -674,6 +763,31 @@
  *         <td>Suitable for adults aged 21 and above</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">TH_TV</td>
+ *         <td>TH_TV_4</td>
+ *         <td>Suitable for audiences 3 to 5 years of age</td>
+ *     </tr>
+ *     <tr>
+ *         <td>TH_TV_6</td>
+ *         <td>Suitable for audiences 6 to 12 years of age</td>
+ *     </tr>
+ *     <tr>
+ *         <td>TH_TV_10</td>
+ *         <td>Suitable for all audiences</td>
+ *     </tr>
+ *     <tr>
+ *         <td>TH_TV_13</td>
+ *         <td>Parental guidance suggested for viewers age below 13</td>
+ *     </tr>
+ *     <tr>
+ *         <td>TH_TV_18</td>
+ *         <td>Parental guidance suggested for viewers age below 18</td>
+ *     </tr>
+ *     <tr>
+ *         <td>TH_TV_19</td>
+ *         <td>Not suitable for children and teenagers</td>
+ *     </tr>
+ *     <tr>
  *         <td valign="top" rowspan="5">US_MV</td>
  *         <td>US_MV_G</td>
  *         <td>General audiences</td>
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 8fe4fec..53c0122 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -100,7 +100,11 @@
             return getWideColorSupport(surfaceControl);
         // These data space need HDR support.
         case HAL_DATASPACE_BT2020_PQ:
-            return getHdrSupport(surfaceControl);
+            if (!getHdrSupport(surfaceControl)) {
+                ALOGE("Invalid dataspace - device does not support hdr");
+                return false;
+            }
+            return true;
         default:
             return false;
     }
@@ -458,10 +462,11 @@
     CHECK_NOT_NULL(aSurfaceControl);
 
     sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
-    LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, aDataSpace), "invalid dataspace");
-
+    if (!isDataSpaceValid(surfaceControl, aDataSpace)) {
+        ALOGE("Failed to set buffer dataspace - invalid dataspace");
+        return;
+    }
     Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
-
     transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace));
 }
 
@@ -527,7 +532,10 @@
     CHECK_NOT_NULL(aSurfaceControl);
 
     sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
-    LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, dataspace), "invalid dataspace");
+    if (!isDataSpaceValid(surfaceControl, dataspace)) {
+        ALOGE("Failed to set buffer dataspace - invalid dataspace");
+        return;
+    }
     Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
 
     half3 color;
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index eb6160a..75344c4 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -376,7 +376,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ ఫీచ‌ర్‌ ప్రయోగాత్మకమైనది, పనితీరుపై ప్రభావం చూపవచ్చు."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
     <string name="power_remaining_settings_home_page" msgid="4845022416859002011">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="6123167166221295462">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 59270a0..f9452e2 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -41,6 +41,7 @@
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
@@ -304,6 +305,7 @@
     @Inject Lazy<ChannelEditorDialogController> mChannelEditorDialogController;
     @Inject Lazy<INotificationManager> mINotificationManager;
     @Inject Lazy<FalsingManager> mFalsingManager;
+    @Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
 
     @Inject
     public Dependency() {
@@ -482,6 +484,7 @@
         mProviders.put(ChannelEditorDialogController.class, mChannelEditorDialogController::get);
         mProviders.put(INotificationManager.class, mINotificationManager::get);
         mProviders.put(FalsingManager.class, mFalsingManager::get);
+        mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
         //                    per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 3ce8a4b..b67d7df 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -30,6 +30,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.KeyguardIndicationController;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
index edd2463..5d103eb 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardLiftController;
 import com.android.systemui.util.AsyncSensorManager;
@@ -47,4 +48,11 @@
         }
         return new KeyguardLiftController(context, statusBarStateController, asyncSensorManager);
     }
+
+
+    @Singleton
+    @Provides
+    static SysUiState provideSysUiState() {
+        return new SysUiState();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
index 6cf2034..763315d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
@@ -22,8 +22,8 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import java.io.PrintWriter;
@@ -41,15 +41,11 @@
                     handleDozingChanged(isDozing);
                 }
             };
-    private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
-            new OverviewProxyService.OverviewProxyListener() {
-        @Override
-        public void onSystemUiStateChanged(int sysuiStateFlags) {
-            handleSystemUiStateChange(sysuiStateFlags);
-        }
-    };
+
+    private final SysUiState.SysUiStateCallback mSysUiStateCallback =
+            this::handleSystemUiStateChange;
     private final StatusBarStateController mStatusBarStateController;
-    private final OverviewProxyService mOverviewProxyService;
+    private final SysUiState mSysUiFlagContainer;
 
     private boolean mIsDozing;
     private boolean mIsHomeHandleHiding;
@@ -58,7 +54,7 @@
 
     AssistHandleLikeHomeBehavior() {
         mStatusBarStateController = Dependency.get(StatusBarStateController.class);
-        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+        mSysUiFlagContainer = Dependency.get(SysUiState.class);
     }
 
     @Override
@@ -66,14 +62,14 @@
         mAssistHandleCallbacks = callbacks;
         mIsDozing = mStatusBarStateController.isDozing();
         mStatusBarStateController.addCallback(mStatusBarStateListener);
-        mOverviewProxyService.addCallback(mOverviewProxyListener);
+        mSysUiFlagContainer.addCallback(mSysUiStateCallback);
         callbackForCurrentState();
     }
 
     @Override
     public void onModeDeactivated() {
         mAssistHandleCallbacks = null;
-        mOverviewProxyService.removeCallback(mOverviewProxyListener);
+        mSysUiFlagContainer.removeCallback(mSysUiStateCallback);
     }
 
     private static boolean isHomeHandleHiding(int sysuiStateFlags) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 28fae63..7a9feb7 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -34,6 +34,7 @@
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.Dependency;
 import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -109,12 +110,10 @@
                 public void onOverviewShown(boolean fromHome) {
                     handleOverviewShown();
                 }
-
-                @Override
-                public void onSystemUiStateChanged(int sysuiStateFlags) {
-                    handleSystemUiStateChanged(sysuiStateFlags);
-                }
             };
+
+    private final SysUiState.SysUiStateCallback mSysUiStateCallback =
+            this::handleSystemUiStateChanged;
     private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -129,6 +128,7 @@
     private final StatusBarStateController mStatusBarStateController;
     private final ActivityManagerWrapper mActivityManagerWrapper;
     private final OverviewProxyService mOverviewProxyService;
+    private final SysUiState mSysUiFlagContainer;
 
     private boolean mOnLockscreen;
     private boolean mIsDozing;
@@ -156,6 +156,7 @@
         mStatusBarStateController = Dependency.get(StatusBarStateController.class);
         mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
         mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+        mSysUiFlagContainer = Dependency.get(SysUiState.class);
         mDefaultHomeIntentFilter = new IntentFilter();
         for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
             mDefaultHomeIntentFilter.addAction(action);
@@ -176,6 +177,7 @@
         mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
         mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
         mOverviewProxyService.addCallback(mOverviewProxyListener);
+        mSysUiFlagContainer.addCallback(mSysUiStateCallback);
 
         mLearningTimeElapsed = Settings.Secure.getLong(
                 context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
@@ -201,6 +203,7 @@
         mStatusBarStateController.removeCallback(mStatusBarStateListener);
         mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
         mOverviewProxyService.removeCallback(mOverviewProxyListener);
+        mSysUiFlagContainer.removeCallback(mSysUiStateCallback);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
new file mode 100644
index 0000000..029ab43
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
@@ -0,0 +1,114 @@
+/*
+ * 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.systemui.model;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.shared.system.QuickStepContract;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Singleton;
+
+/**
+ * Contains sysUi state flags and notifies registered
+ * listeners whenever changes happen.
+ */
+@Singleton
+public class SysUiState implements Dumpable {
+
+    private @QuickStepContract.SystemUiStateFlags int mFlags;
+    private final List<SysUiStateCallback> mCallbacks = new ArrayList<>();
+    private int mFlagsToSet = 0;
+    private int mFlagsToClear = 0;
+
+    /**
+     * Add listener to be notified of changes made to SysUI state.
+     * The callback will also be called as part of this function.
+     */
+    public void addCallback(@NonNull SysUiStateCallback callback) {
+        mCallbacks.add(callback);
+        callback.onSystemUiStateChanged(mFlags);
+    }
+
+    /** Callback will no longer receive events on state change */
+    public void removeCallback(@NonNull SysUiStateCallback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    /** Methods to this call can be chained together before calling {@link #commitUpdate(int)}. */
+    public SysUiState setFlag(int flag, boolean enabled) {
+        if (enabled) {
+            mFlagsToSet |= flag;
+        } else {
+            mFlagsToClear |= flag;
+        }
+        return this;
+    }
+
+    /** Call to save all the flags updated from {@link #setFlag(int, boolean)}. */
+    public void commitUpdate(int displayId) {
+        updateFlags(displayId);
+        mFlagsToSet = 0;
+        mFlagsToClear = 0;
+    }
+
+    private void updateFlags(int displayId) {
+        if (displayId != DEFAULT_DISPLAY) {
+            // Ignore non-default displays for now
+            return;
+        }
+
+        int newState = mFlags;
+        newState |= mFlagsToSet;
+        newState &= ~mFlagsToClear;
+        notifyAndSetSystemUiStateChanged(newState, mFlags);
+    }
+
+    /** Notify all those who are registered that the state has changed. */
+    private void notifyAndSetSystemUiStateChanged(int newFlags, int oldFlags) {
+        if (newFlags != oldFlags) {
+            mCallbacks.forEach(callback -> callback.onSystemUiStateChanged(newFlags));
+            mFlags = newFlags;
+        }
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("SysUiState state:");
+        pw.print("  mSysUiStateFlags="); pw.println(mFlags);
+        pw.println("    " + QuickStepContract.getSystemUiStateString(mFlags));
+        pw.print("    backGestureDisabled=");
+        pw.println(QuickStepContract.isBackGestureDisabled(mFlags));
+        pw.print("    assistantGestureDisabled=");
+        pw.println(QuickStepContract.isAssistantGestureDisabled(mFlags));
+    }
+
+    /** Callback to be notified whenever system UI state flags are changed. */
+    public interface SysUiStateCallback{
+        /** To be called when any SysUiStateFlag gets updated */
+        void onSystemUiStateChanged(@QuickStepContract.SystemUiStateFlags int sysUiFlags);
+    }
+}
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 16f0b15..9268ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -17,7 +17,6 @@
 package com.android.systemui.recents;
 
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
@@ -58,12 +57,12 @@
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.phone.NavigationBarFragment;
@@ -101,6 +100,7 @@
     private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000;
 
     private final Context mContext;
+    private SysUiState mSysUiState;
     private final Handler mHandler;
     private final NavigationBarController mNavBarController;
     private final StatusBarWindowController mStatusBarWinController;
@@ -114,7 +114,6 @@
 
     private IOverviewProxy mOverviewProxy;
     private int mConnectionBackoffAttempts;
-    private @SystemUiStateFlags int mSysUiStateFlags;
     private boolean mBound;
     private boolean mIsEnabled;
     private int mCurrentBoundedUserId = -1;
@@ -464,7 +463,8 @@
     @Inject
     public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
             NavigationBarController navBarController, NavigationModeController navModeController,
-            StatusBarWindowController statusBarWinController) {
+            StatusBarWindowController statusBarWinController,
+            SysUiState sysUiState) {
         mContext = context;
         mHandler = new Handler();
         mNavBarController = navBarController;
@@ -478,6 +478,8 @@
         mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources());
         mSupportsRoundedCornersOnWindows = ScreenDecorationsUtils
                 .supportsRoundedCornersOnWindows(mContext.getResources());
+        mSysUiState = sysUiState;
+        mSysUiState.addCallback(this::notifySystemUiStateFlags);
 
         // Assumes device always starts with back button until launcher tells it that it does not
         mNavBarButtonAlpha = 1.0f;
@@ -512,36 +514,12 @@
         }
     }
 
-    public void setSystemUiStateFlag(int flag, boolean enabled, int displayId) {
-        if (displayId != DEFAULT_DISPLAY) {
-            // Ignore non-default displays for now
-            return;
-        }
-
-        int newState = mSysUiStateFlags;
-        if (enabled) {
-            newState |= flag;
-        } else {
-            newState &= ~flag;
-        }
-        if (mSysUiStateFlags != newState) {
-            mSysUiStateFlags = newState;
-            notifySystemUiStateChanged(mSysUiStateFlags);
-            notifySystemUiStateFlags(mSysUiStateFlags);
-        }
-    }
-
-    public int getSystemUiStateFlags() {
-        return mSysUiStateFlags;
-    }
-
     private void updateSystemUiStateFlags() {
         final NavigationBarFragment navBarFragment =
                 mNavBarController.getDefaultNavigationBarFragment();
         final NavigationBarView navBarView =
                 mNavBarController.getNavigationBarView(mContext.getDisplayId());
 
-        mSysUiStateFlags = 0;
         if (navBarFragment != null) {
             navBarFragment.updateSystemUiStateFlags(-1);
         }
@@ -552,7 +530,6 @@
         if (mStatusBarWinController != null) {
             mStatusBarWinController.notifyStateChangedCallbacks();
         }
-        notifySystemUiStateFlags(mSysUiStateFlags);
     }
 
     private void notifySystemUiStateFlags(int flags) {
@@ -568,11 +545,13 @@
     private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
             boolean bouncerShowing) {
         int displayId = mContext.getDisplayId();
-        setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
-                keyguardShowing && !keyguardOccluded, displayId);
-        setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
-                keyguardShowing && keyguardOccluded, displayId);
-        setSystemUiStateFlag(SYSUI_STATE_BOUNCER_SHOWING, bouncerShowing, displayId);
+
+        mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
+                        keyguardShowing && !keyguardOccluded)
+                .setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
+                        keyguardShowing && keyguardOccluded)
+                .setFlag(SYSUI_STATE_BOUNCER_SHOWING, bouncerShowing)
+                .commitUpdate(displayId);
     }
 
     /**
@@ -665,7 +644,6 @@
         mConnectionCallbacks.add(listener);
         listener.onConnectionChanged(mOverviewProxy != null);
         listener.onNavBarButtonAlphaChanged(mNavBarButtonAlpha, false);
-        listener.onSystemUiStateChanged(mSysUiStateFlags);
     }
 
     @Override
@@ -736,12 +714,6 @@
         }
     }
 
-    private void notifySystemUiStateChanged(int sysuiStateFlags) {
-        for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
-            mConnectionCallbacks.get(i).onSystemUiStateChanged(sysuiStateFlags);
-        }
-    }
-
     private void notifyStartAssistant(Bundle bundle) {
         for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
             mConnectionCallbacks.get(i).startAssistant(bundle);
@@ -782,12 +754,7 @@
 
         pw.print("  quickStepIntent="); pw.println(mQuickStepIntent);
         pw.print("  quickStepIntentResolved="); pw.println(isEnabled());
-        pw.print("  mSysUiStateFlags="); pw.println(mSysUiStateFlags);
-        pw.println("    " + QuickStepContract.getSystemUiStateString(mSysUiStateFlags));
-        pw.print("    backGestureDisabled=");
-        pw.println(QuickStepContract.isBackGestureDisabled(mSysUiStateFlags));
-        pw.print("    assistantGestureDisabled=");
-        pw.println(QuickStepContract.isAssistantGestureDisabled(mSysUiStateFlags));
+        mSysUiState.dump(fd, pw, args);
         pw.print(" mInputFocusTransferStarted="); pw.println(mInputFocusTransferStarted);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 3314e67..575b559 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -55,6 +55,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -166,8 +167,10 @@
     private RegionSamplingHelper mRegionSamplingHelper;
     private int mLeftInset;
     private int mRightInset;
+    private int mSysUiFlags;
 
-    public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService) {
+    public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
+            SysUiState sysUiFlagContainer) {
         final Resources res = context.getResources();
         mContext = context;
         mDisplayId = context.getDisplayId();
@@ -186,6 +189,7 @@
         mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
         mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
         updateCurrentUserResources(res);
+        sysUiFlagContainer.addCallback(sysUiFlags -> mSysUiFlags = sysUiFlags);
     }
 
     public void updateCurrentUserResources(Resources res) {
@@ -352,10 +356,9 @@
         if (action == MotionEvent.ACTION_DOWN) {
             // Verify if this is in within the touch region and we aren't in immersive mode, and
             // either the bouncer is showing or the notification panel is hidden
-            int stateFlags = mOverviewProxyService.getSystemUiStateFlags();
             mIsOnLeftEdge = ev.getX() <= mEdgeWidth + mLeftInset;
             mInRejectedExclusion = false;
-            mAllowGesture = !QuickStepContract.isBackGestureDisabled(stateFlags)
+            mAllowGesture = !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
                     && isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
             if (mAllowGesture) {
                 mEdgePanelLp.gravity = mIsOnLeftEdge
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 5d3f3ac..2b8c86b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -91,6 +91,7 @@
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
@@ -134,6 +135,7 @@
 
     private final AccessibilityManagerWrapper mAccessibilityManagerWrapper;
     protected final AssistManager mAssistManager;
+    private SysUiState mSysUiFlagsContainer;
     private final MetricsLogger mMetricsLogger;
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final StatusBarStateController mStatusBarStateController;
@@ -245,12 +247,14 @@
             DeviceProvisionedController deviceProvisionedController, MetricsLogger metricsLogger,
             AssistManager assistManager, OverviewProxyService overviewProxyService,
             NavigationModeController navigationModeController,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            SysUiState sysUiFlagsContainer) {
         mAccessibilityManagerWrapper = accessibilityManagerWrapper;
         mDeviceProvisionedController = deviceProvisionedController;
         mStatusBarStateController = statusBarStateController;
         mMetricsLogger = metricsLogger;
         mAssistManager = assistManager;
+        mSysUiFlagsContainer = sysUiFlagsContainer;
         mAssistantAvailable = mAssistManager.getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
         mOverviewProxyService = overviewProxyService;
         mNavBarMode = navigationModeController.addListener(this);
@@ -884,12 +888,11 @@
         }
         boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
         boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE,
-                clickable, mDisplayId);
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE,
-                longClickable, mDisplayId);
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NAV_BAR_HIDDEN,
-                !isNavBarWindowVisible(), mDisplayId);
+
+        mSysUiFlagsContainer.setFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable)
+                .setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
+                .setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isNavBarWindowVisible())
+                .commitUpdate(mDisplayId);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 3485f23..fa4812d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -68,6 +68,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsOnboarding;
@@ -92,6 +93,7 @@
     final static boolean ALTERNATE_CAR_MODE_UI = false;
     private final RegionSamplingHelper mRegionSamplingHelper;
     private final int mNavColorSampleMargin;
+    private final SysUiState mSysUiFlagContainer;
 
     View mCurrentView = null;
     private View mVertical;
@@ -266,6 +268,7 @@
         mNavBarMode = Dependency.get(NavigationModeController.class).addListener(this);
         boolean isGesturalMode = isGesturalMode(mNavBarMode);
 
+        mSysUiFlagContainer = Dependency.get(SysUiState.class);
         // Set up the context group of buttons
         mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
         final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
@@ -307,11 +310,10 @@
         mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
         mDeadZone = new DeadZone(this);
 
-        mNavColorSampleMargin =
-                getResources()
+        mNavColorSampleMargin = getResources()
                         .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
-
-        mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService);
+        mEdgeBackGestureHandler =
+                new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiFlagContainer);
         mRegionSamplingHelper = new RegionSamplingHelper(this,
                 new RegionSamplingHelper.SamplingCallback() {
                     @Override
@@ -745,23 +747,26 @@
 
     public void updateDisabledSystemUiStateFlags() {
         int displayId = mContext.getDisplayId();
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_SCREEN_PINNING,
-                ActivityManagerWrapper.getInstance().isScreenPinningActive(), displayId);
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_OVERVIEW_DISABLED,
-                (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0, displayId);
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_HOME_DISABLED,
-                (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0, displayId);
-        mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_SEARCH_DISABLED,
-                (mDisabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0, displayId);
+
+        mSysUiFlagContainer.setFlag(SYSUI_STATE_SCREEN_PINNING,
+                        ActivityManagerWrapper.getInstance().isScreenPinningActive())
+                .setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
+                        (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
+                .setFlag(SYSUI_STATE_HOME_DISABLED,
+                        (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0)
+                .setFlag(SYSUI_STATE_SEARCH_DISABLED,
+                        (mDisabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0)
+                .commitUpdate(displayId);
     }
 
     public void updatePanelSystemUiStateFlags() {
         int displayId = mContext.getDisplayId();
         if (mPanelView != null) {
-            mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
-                    mPanelView.isFullyExpanded() && !mPanelView.isInSettings(), displayId);
-            mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
-                    mPanelView.isInSettings(), displayId);
+            mSysUiFlagContainer.setFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
+                    mPanelView.isFullyExpanded() && !mPanelView.isInSettings())
+                    .setFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
+                            mPanelView.isInSettings())
+                    .commitUpdate(displayId);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java
new file mode 100644
index 0000000..9bcfd5b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.systemui.model;
+
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@SmallTest
+@RunWith(MockitoJUnitRunner.class)
+public class SysUiStateTest extends SysuiTestCase {
+    private static final int FLAG_1 = 1;
+    private static final int FLAG_2 = 1 << 1;
+    private static final int FLAG_3 = 1 << 2;
+    private static final int FLAG_4 = 1 << 3;
+    private static final int DISPLAY_ID = DEFAULT_DISPLAY;
+
+    private SysUiState.SysUiStateCallback mCallback;
+    private SysUiState mFlagsContainer;
+
+    @Before
+    public void setup() {
+        mFlagsContainer = new SysUiState();
+        mCallback = mock(SysUiState.SysUiStateCallback.class);
+        mFlagsContainer.addCallback(mCallback);
+    }
+
+    @Test
+    public void addSingle_setFlag() {
+        setFlags(FLAG_1);
+
+        verify(mCallback, times(1)).onSystemUiStateChanged(FLAG_1);
+    }
+
+    @Test
+    public void addMultiple_setFlag() {
+        setFlags(FLAG_1);
+        setFlags(FLAG_2);
+
+        verify(mCallback, times(1)).onSystemUiStateChanged(FLAG_1);
+        verify(mCallback, times(1))
+                .onSystemUiStateChanged(FLAG_1 | FLAG_2);
+    }
+
+    @Test
+    public void addMultipleRemoveOne_setFlag() {
+        setFlags(FLAG_1);
+        setFlags(FLAG_2);
+        mFlagsContainer.setFlag(FLAG_1, false)
+                .commitUpdate(DISPLAY_ID);
+
+        verify(mCallback, times(1)).onSystemUiStateChanged(FLAG_1);
+        verify(mCallback, times(1))
+                .onSystemUiStateChanged(FLAG_1 | FLAG_2);
+        verify(mCallback, times(1)).onSystemUiStateChanged(FLAG_2);
+    }
+
+    @Test
+    public void addMultiple_setFlags() {
+        setFlags(FLAG_1, FLAG_2, FLAG_3, FLAG_4);
+
+        int expected = FLAG_1 | FLAG_2 | FLAG_3 | FLAG_4;
+        verify(mCallback, times(1)).onSystemUiStateChanged(expected);
+    }
+
+    @Test
+    public void addMultipleRemoveOne_setFlags() {
+        setFlags(FLAG_1, FLAG_2, FLAG_3, FLAG_4);
+        mFlagsContainer.setFlag(FLAG_2, false)
+                .commitUpdate(DISPLAY_ID);
+
+        int expected1 = FLAG_1 | FLAG_2 | FLAG_3 | FLAG_4;
+        verify(mCallback, times(1)).onSystemUiStateChanged(expected1);
+        int expected2 = FLAG_1 | FLAG_3 | FLAG_4;
+        verify(mCallback, times(1)).onSystemUiStateChanged(expected2);
+    }
+
+    @Test
+    public void removeCallback() {
+        mFlagsContainer.removeCallback(mCallback);
+        setFlags(FLAG_1, FLAG_2, FLAG_3, FLAG_4);
+
+        int expected = FLAG_1 | FLAG_2 | FLAG_3 | FLAG_4;
+        verify(mCallback, times(0)).onSystemUiStateChanged(expected);
+    }
+
+    private void setFlags(int... flags) {
+        for (int i = 0; i < flags.length; i++) {
+            mFlagsContainer.setFlag(flags[i], true);
+        }
+        mFlagsContainer.commitUpdate(DISPLAY_ID);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index db8af39..75aae01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -24,6 +24,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -56,6 +58,7 @@
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.SysuiTestableContext;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
@@ -82,6 +85,8 @@
     private OverviewProxyService mOverviewProxyService =
             mDependency.injectMockDependency(OverviewProxyService.class);
     private CommandQueue mCommandQueue;
+    private SysUiState mMockSysUiState;
+
     private AccessibilityManagerWrapper mAccessibilityWrapper =
             new AccessibilityManagerWrapper(mContext) {
                 Tracker mTracker = mLeakCheck.getTracker("accessibility_manager");
@@ -156,6 +161,9 @@
 
         mDependency.injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
         mDependency.injectTestDependency(AccessibilityManagerWrapper.class, mAccessibilityWrapper);
+
+        mMockSysUiState = mock(SysUiState.class);
+        when(mMockSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mMockSysUiState);
     }
 
     @Test
@@ -217,7 +225,8 @@
                 mock(AssistManager.class),
                 mOverviewProxyService,
                 mock(NavigationModeController.class),
-                mock(StatusBarStateController.class));
+                mock(StatusBarStateController.class),
+                mMockSysUiState);
     }
 
     private class HostCallbacksForExternalDisplay extends
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index fbe2589..29c4bad 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -130,6 +130,11 @@
         }
 
         @Override
+        public void onPackageChanged(@NonNull String packageName, int uid) {
+            sendPackagePermissionsForUid(uid, getPermissionForUid(uid));
+        }
+
+        @Override
         public void onPackageRemoved(String packageName, int uid) {
             sendPackagePermissionsForUid(uid, getPermissionForUid(uid));
         }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index fb94907..faf01f9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -58,7 +58,6 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
-import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.VpnService;
@@ -114,7 +113,6 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -902,38 +900,6 @@
     }
 
     /**
-     * Analyzes the passed LinkedProperties to figure out whether it routes to most of the IP space.
-     *
-     * This returns true if the passed LinkedProperties contains routes to either most of the IPv4
-     * space or to most of the IPv6 address space, where "most" is defined by the value of the
-     * MOST_IPV{4,6}_ADDRESSES_COUNT constants : if more than this number of addresses are matched
-     * by any of the routes, then it's decided that most of the space is routed.
-     * @hide
-     */
-    @VisibleForTesting
-    static boolean providesRoutesToMostDestinations(LinkProperties lp) {
-        final List<RouteInfo> routes = lp.getAllRoutes();
-        if (routes.size() > MAX_ROUTES_TO_EVALUATE) return true;
-        final Comparator<IpPrefix> prefixLengthComparator = IpPrefix.lengthComparator();
-        TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator);
-        TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator);
-        for (final RouteInfo route : routes) {
-            if (route.getType() == RouteInfo.RTN_UNREACHABLE) continue;
-            IpPrefix destination = route.getDestination();
-            if (destination.isIPv4()) {
-                ipv4Prefixes.add(destination);
-            } else {
-                ipv6Prefixes.add(destination);
-            }
-        }
-        if (NetworkUtils.routedIPv4AddressCount(ipv4Prefixes) > MOST_IPV4_ADDRESSES_COUNT) {
-            return true;
-        }
-        return NetworkUtils.routedIPv6AddressCount(ipv6Prefixes)
-                .compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
-    }
-
-    /**
      * Attempt to perform a seamless handover of VPNs by only updating LinkProperties without
      * registering a new NetworkAgent. This is not always possible if the new VPN configuration
      * has certain changes, in which case this method would just return {@code false}.
@@ -1079,7 +1045,8 @@
             // TEMP use the old jni calls until there is support for netd address setting
             StringBuilder builder = new StringBuilder();
             for (LinkAddress address : config.addresses) {
-                builder.append(" " + address);
+                builder.append(" ");
+                builder.append(address);
             }
             if (jniSetAddresses(interfaze, builder.toString()) < 1) {
                 throw new IllegalArgumentException("At least one address must be specified");
@@ -1163,7 +1130,7 @@
 
     // Note: Return type guarantees results are deduped and sorted, which callers require.
     private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) {
-        SortedSet<Integer> uids = new TreeSet<Integer>();
+        SortedSet<Integer> uids = new TreeSet<>();
         for (String app : packageNames) {
             int uid = getAppUid(app, userHandle);
             if (uid != -1) uids.add(uid);
@@ -1266,7 +1233,7 @@
         // UidRange#createForUser returns the entire range of UIDs available to a macro-user.
         // This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE}
         final UidRange userRange = UidRange.createForUser(userHandle);
-        final List<UidRange> ranges = new ArrayList<UidRange>();
+        final List<UidRange> ranges = new ArrayList<>();
         for (UidRange range : existingRanges) {
             if (userRange.containsRange(range)) {
                 ranges.add(range);
@@ -1765,7 +1732,7 @@
             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
             serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
         }
-        if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
+        if (userCert == null || caCert == null || serverCert == null) {
             throw new IllegalStateException("Cannot load credentials");
         }
 
@@ -1884,7 +1851,7 @@
      * Return the information of the current ongoing legacy VPN.
      * Callers are responsible for checking permissions if needed.
      */
-    public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
+    private synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
         if (mLegacyVpnRunner == null) return null;
 
         final LegacyVpnInfo info = new LegacyVpnInfo();
@@ -2038,7 +2005,6 @@
 
         private void bringup() {
             // Catch all exceptions so we can clean up a few things.
-            boolean initFinished = false;
             try {
                 // Initialize the timer.
                 mBringupStartTime = SystemClock.elapsedRealtime();
@@ -2057,7 +2023,6 @@
                     throw new IllegalStateException("Cannot delete the state");
                 }
                 new File("/data/misc/vpn/abort").delete();
-                initFinished = true;
 
                 // Check if we need to restart any of the daemons.
                 boolean restart = false;
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 7648636..58aadd1 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -38,13 +38,16 @@
 import android.os.UserHandle;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.R;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
 import com.android.server.display.whitebalance.AmbientFilter;
@@ -64,6 +67,8 @@
     private static final boolean DEBUG = false;
 
     private static final int MSG_ALLOWED_MODES_CHANGED = 1;
+    private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
+    private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
 
     // Special ID used to indicate that given vote is to be applied globally, rather than to a
     // specific display.
@@ -91,6 +96,7 @@
     private final DisplayObserver mDisplayObserver;
     private final BrightnessObserver mBrightnessObserver;
 
+    private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
     private Listener mListener;
 
     public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
@@ -103,7 +109,7 @@
         mSettingsObserver = new SettingsObserver(context, handler);
         mDisplayObserver = new DisplayObserver(context, handler);
         mBrightnessObserver = new BrightnessObserver(context, handler);
-
+        mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
     }
 
     /**
@@ -405,7 +411,7 @@
         void onAllowedDisplayModesChanged();
     }
 
-    private static final class DisplayModeDirectorHandler extends Handler {
+    private final class DisplayModeDirectorHandler extends Handler {
         DisplayModeDirectorHandler(Looper looper) {
             super(looper, null, true /*async*/);
         }
@@ -417,6 +423,23 @@
                     Listener listener = (Listener) msg.obj;
                     listener.onAllowedDisplayModesChanged();
                     break;
+
+                case MSG_BRIGHTNESS_THRESHOLDS_CHANGED:
+                    Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
+
+                    if (thresholds != null) {
+                        mBrightnessObserver.onDeviceConfigThresholdsChanged(
+                                thresholds.first, thresholds.second);
+                    } else {
+                        mBrightnessObserver.onDeviceConfigThresholdsChanged(null, null);
+                    }
+                    break;
+
+                case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED:
+                    Float defaultPeakRefreshRate = (Float) msg.obj;
+                    mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
+                            defaultPeakRefreshRate);
+                    break;
             }
         }
     }
@@ -502,13 +525,15 @@
     }
 
     private final class SettingsObserver extends ContentObserver {
-        private final Uri mRefreshRateSetting =
+        private final Uri mPeakRefreshRateSetting =
                 Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
+        private final Uri mMinRefreshRateSetting =
+                Settings.System.getUriFor(Settings.System.MIN_REFRESH_RATE);
         private final Uri mLowPowerModeSetting =
                 Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE);
 
         private final Context mContext;
-        private final float mDefaultPeakRefreshRate;
+        private float mDefaultPeakRefreshRate;
 
         SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
             super(handler);
@@ -519,20 +544,44 @@
 
         public void observe() {
             final ContentResolver cr = mContext.getContentResolver();
-            cr.registerContentObserver(mRefreshRateSetting, false /*notifyDescendants*/, this,
+            cr.registerContentObserver(mPeakRefreshRateSetting, false /*notifyDescendants*/, this,
+                    UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(mMinRefreshRateSetting, false /*notifyDescendants*/, this,
                     UserHandle.USER_SYSTEM);
             cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
                     UserHandle.USER_SYSTEM);
+
+            Float deviceConfigDefaultPeakRefresh =
+                    mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
+            if (deviceConfigDefaultPeakRefresh != null) {
+                mDefaultPeakRefreshRate = deviceConfigDefaultPeakRefresh;
+            }
+
             synchronized (mLock) {
                 updateRefreshRateSettingLocked();
                 updateLowPowerModeSettingLocked();
             }
         }
 
+        public void onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate) {
+            if (defaultPeakRefreshRate == null) {
+                defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
+                        R.integer.config_defaultPeakRefreshRate);
+            }
+
+            if (mDefaultPeakRefreshRate != defaultPeakRefreshRate) {
+                synchronized (mLock) {
+                    mDefaultPeakRefreshRate = defaultPeakRefreshRate;
+                    updateRefreshRateSettingLocked();
+                }
+            }
+        }
+
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
             synchronized (mLock) {
-                if (mRefreshRateSetting.equals(uri)) {
+                if (mPeakRefreshRateSetting.equals(uri)
+                        || mMinRefreshRateSetting.equals(uri)) {
                     updateRefreshRateSettingLocked();
                 } else if (mLowPowerModeSetting.equals(uri)) {
                     updateLowPowerModeSettingLocked();
@@ -550,15 +599,22 @@
                 vote = null;
             }
             updateVoteLocked(Vote.PRIORITY_LOW_POWER_MODE, vote);
-            mBrightnessObserver.onLowPowerModeEnabled(inLowPowerMode);
+            mBrightnessObserver.onLowPowerModeEnabledLocked(inLowPowerMode);
         }
 
         private void updateRefreshRateSettingLocked() {
+            float minRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
+                    Settings.System.MIN_REFRESH_RATE, 0f);
             float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
                     Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
-            Vote vote = Vote.forRefreshRates(0f, peakRefreshRate);
+
+            if (peakRefreshRate < minRefreshRate) {
+                peakRefreshRate = minRefreshRate;
+            }
+
+            Vote vote = Vote.forRefreshRates(minRefreshRate, peakRefreshRate);
             updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote);
-            mBrightnessObserver.onPeakRefreshRateEnabled(peakRefreshRate > 60f);
+            mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate);
         }
 
         public void dumpLocked(PrintWriter pw) {
@@ -721,8 +777,8 @@
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
 
         private final static int LIGHT_SENSOR_RATE_MS = 250;
-        private final int[] mDisplayBrightnessThresholds;
-        private final int[] mAmbientBrightnessThresholds;
+        private int[] mDisplayBrightnessThresholds;
+        private int[] mAmbientBrightnessThresholds;
         // valid threshold if any item from the array >= 0
         private boolean mShouldObserveDisplayChange;
         private boolean mShouldObserveAmbientChange;
@@ -735,10 +791,12 @@
         private AmbientFilter mAmbientFilter;
 
         private final Context mContext;
-        // Enable light sensor only when screen is on, peak refresh rate enabled and low power mode
-        // off. After initialization, these states will be updated from the same handler thread.
+
+        // Enable light sensor only when mShouldObserveAmbientChange is true, screen is on, peak
+        // refresh rate changeable and low power mode off. After initialization, these states will
+        // be updated from the same handler thread.
         private boolean mScreenOn = false;
-        private boolean mPeakRefreshRateEnabled = false;
+        private boolean mRefreshRateChangeable = false;
         private boolean mLowPowerModeEnabled = false;
 
         BrightnessObserver(Context context, Handler handler) {
@@ -748,79 +806,61 @@
                     R.array.config_brightnessThresholdsOfPeakRefreshRate);
             mAmbientBrightnessThresholds = context.getResources().getIntArray(
                     R.array.config_ambientThresholdsOfPeakRefreshRate);
+
             if (mDisplayBrightnessThresholds.length != mAmbientBrightnessThresholds.length) {
                 throw new RuntimeException("display brightness threshold array and ambient "
                         + "brightness threshold array have different length");
             }
-
-            mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds);
-            mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds);
         }
 
         public void observe(SensorManager sensorManager) {
-            if (mShouldObserveDisplayChange) {
-                final ContentResolver cr = mContext.getContentResolver();
-                cr.registerContentObserver(mDisplayBrightnessSetting,
-                        false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM);
+            mSensorManager = sensorManager;
+            // DeviceConfig is accessible after system ready.
+            int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
+            int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
+
+            if (brightnessThresholds != null && ambientThresholds != null
+                    && brightnessThresholds.length == ambientThresholds.length) {
+                mDisplayBrightnessThresholds = brightnessThresholds;
+                mAmbientBrightnessThresholds = ambientThresholds;
             }
-
-            if (mShouldObserveAmbientChange) {
-                Resources resources = mContext.getResources();
-                String lightSensorType = resources.getString(
-                        com.android.internal.R.string.config_displayLightSensorType);
-
-                Sensor lightSensor = null;
-                if (!TextUtils.isEmpty(lightSensorType)) {
-                    List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
-                    for (int i = 0; i < sensors.size(); i++) {
-                        Sensor sensor = sensors.get(i);
-                        if (lightSensorType.equals(sensor.getStringType())) {
-                            lightSensor = sensor;
-                            break;
-                        }
-                    }
-                }
-
-                if (lightSensor == null) {
-                    lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
-                }
-
-                if (lightSensor != null) {
-                    final Resources res = mContext.getResources();
-
-                    mAmbientFilter = DisplayWhiteBalanceFactory.createBrightnessFilter(res);
-                    mSensorManager = sensorManager;
-                    mLightSensor = lightSensor;
-
-                    onScreenOn(isDefaultDisplayOn());
-                }
-            }
-
-            if (mShouldObserveDisplayChange || mShouldObserveAmbientChange) {
-                synchronized (mLock) {
-                    onBrightnessChangedLocked();
-                }
-            }
+            restartObserver();
+            mDeviceConfigDisplaySettings.startListening();
         }
 
-        public void onPeakRefreshRateEnabled(boolean b) {
-            if (mShouldObserveAmbientChange && mPeakRefreshRateEnabled != b) {
-                mPeakRefreshRateEnabled = b;
+        public void onRefreshRateSettingChangedLocked(float min, float max) {
+            boolean changeable = (max - min > 1f && max > 60f);
+            if (mRefreshRateChangeable != changeable) {
+                mRefreshRateChangeable = changeable;
                 updateSensorStatus();
+                if (!changeable) {
+                    // Revoke previous vote from BrightnessObserver
+                    updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, null);
+                }
             }
         }
 
-        public void onLowPowerModeEnabled(boolean b) {
-            if (mShouldObserveAmbientChange && mLowPowerModeEnabled != b) {
+        public void onLowPowerModeEnabledLocked(boolean b) {
+            if (mLowPowerModeEnabled != b) {
                 mLowPowerModeEnabled = b;
                 updateSensorStatus();
             }
         }
 
-        public void onDisplayChanged(int displayId) {
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                onScreenOn(isDefaultDisplayOn());
+        public void onDeviceConfigThresholdsChanged(int[] brightnessThresholds,
+                int[] ambientThresholds) {
+            if (brightnessThresholds != null && ambientThresholds != null
+                    && brightnessThresholds.length == ambientThresholds.length) {
+                mDisplayBrightnessThresholds = brightnessThresholds;
+                mAmbientBrightnessThresholds = ambientThresholds;
+            } else {
+                // Invalid or empty. Use device default.
+                mDisplayBrightnessThresholds = mContext.getResources().getIntArray(
+                        R.array.config_brightnessThresholdsOfPeakRefreshRate);
+                mAmbientBrightnessThresholds = mContext.getResources().getIntArray(
+                        R.array.config_ambientThresholdsOfPeakRefreshRate);
             }
+            restartObserver();
         }
 
         public void dumpLocked(PrintWriter pw) {
@@ -835,6 +875,12 @@
             }
         }
 
+        public void onDisplayChanged(int displayId) {
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                onScreenOn(isDefaultDisplayOn());
+            }
+        }
+
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
             synchronized (mLock) {
@@ -842,6 +888,63 @@
             }
         }
 
+        private void restartObserver() {
+            mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds);
+            mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds);
+
+            final ContentResolver cr = mContext.getContentResolver();
+            if (mShouldObserveDisplayChange) {
+                // Content Service does not check if an listener has already been registered.
+                // To ensure only one listener is registered, force an unregistration first.
+                cr.unregisterContentObserver(this);
+                cr.registerContentObserver(mDisplayBrightnessSetting,
+                        false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM);
+            } else {
+                cr.unregisterContentObserver(this);
+            }
+
+            if (mShouldObserveAmbientChange) {
+                Resources resources = mContext.getResources();
+                String lightSensorType = resources.getString(
+                        com.android.internal.R.string.config_displayLightSensorType);
+
+                Sensor lightSensor = null;
+                if (!TextUtils.isEmpty(lightSensorType)) {
+                    List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+                    for (int i = 0; i < sensors.size(); i++) {
+                        Sensor sensor = sensors.get(i);
+                        if (lightSensorType.equals(sensor.getStringType())) {
+                            lightSensor = sensor;
+                            break;
+                        }
+                    }
+                }
+
+                if (lightSensor == null) {
+                    lightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+                }
+
+                if (lightSensor != null) {
+                    final Resources res = mContext.getResources();
+
+                    mAmbientFilter = DisplayWhiteBalanceFactory.createBrightnessFilter(res);
+                    mLightSensor = lightSensor;
+
+                    onScreenOn(isDefaultDisplayOn());
+                }
+            } else {
+                mAmbientFilter = null;
+                mLightSensor = null;
+            }
+
+            if (mRefreshRateChangeable) {
+                updateSensorStatus();
+                synchronized (mLock) {
+                    onBrightnessChangedLocked();
+                }
+            }
+        }
+
         /**
          * Checks to see if at least one value is positive, in which case it is necessary to listen
          * to value changes.
@@ -903,7 +1006,8 @@
                 return;
             }
 
-            if (mScreenOn && !mLowPowerModeEnabled && mPeakRefreshRateEnabled) {
+            if (mShouldObserveAmbientChange && mScreenOn && !mLowPowerModeEnabled
+                    && mRefreshRateChangeable) {
                 mSensorManager.registerListener(mLightSensorListener,
                         mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
             } else {
@@ -996,6 +1100,88 @@
                     }
                 }
             };
-        };
+        }
     }
+
+    private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
+
+        public DeviceConfigDisplaySettings() {
+        }
+
+        public void startListening() {
+            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                    BackgroundThread.getExecutor(), this);
+        }
+
+        /*
+         * Return null if no such property or wrong format (not comma separated integers).
+         */
+        public int[] getBrightnessThresholds() {
+            return getIntArrayProperty(
+                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS);
+        }
+
+        /*
+         * Return null if no such property or wrong format (not comma separated integers).
+         */
+        public int[] getAmbientThresholds() {
+            return getIntArrayProperty(
+                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS);
+        }
+
+        /*
+         * Return null if no such property
+         */
+        public Float getDefaultPeakRefreshRate() {
+            float defaultPeakRefreshRate = DeviceConfig.getFloat(
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);
+
+            if (defaultPeakRefreshRate == -1) {
+                return null;
+            }
+            return defaultPeakRefreshRate;
+        }
+
+        @Override
+        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+            int[] brightnessThresholds = getBrightnessThresholds();
+            int[] ambientThresholds = getAmbientThresholds();
+            Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
+
+            mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
+                    new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
+                    .sendToTarget();
+            mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
+                    defaultPeakRefreshRate).sendToTarget();
+        }
+
+        private int[] getIntArrayProperty(String prop) {
+            String strArray = DeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
+                    null);
+
+            if (strArray != null) {
+                return parseIntArray(strArray);
+            }
+
+            return null;
+        }
+
+        private int[] parseIntArray(@NonNull String strArray) {
+            String[] items = strArray.split(",");
+            int[] array = new int[items.length];
+
+            try {
+                for (int i = 0; i < array.length; i++) {
+                    array[i] = Integer.parseInt(items[i]);
+                }
+            } catch (NumberFormatException e) {
+                Slog.e(TAG, "Incorrect format for array: '" + strArray + "'", e);
+                array = null;
+            }
+
+            return array;
+        }
+    }
+
 }
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 1da5bc6..dc00cb4 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -261,11 +261,12 @@
             mContext.registerReceiver(new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
-                    populateAllPackagesCacheIfNeeded();
+                    // Post populateAllPackagesCacheIfNeeded to a background thread, since it's
+                    // expensive to run it in broadcast handler thread.
+                    BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded());
                     mContext.unregisterReceiver(this);
                 }
-            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED), /* broadcastPermission */ null,
-                    BackgroundThread.getHandler());
+            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
         }
 
         private void populateAllPackagesCacheIfNeeded() {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 3aeb2b1..b632d18f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -505,6 +505,11 @@
             params.installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
         }
 
+        if (callingUid != Process.SYSTEM_UID) {
+            // Only system_server can use INSTALL_DISABLE_VERIFICATION.
+            params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
+        }
+
         boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
         if (params.isStaged || isApex) {
             mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 85bc9f3..e8090e3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3097,7 +3097,7 @@
         pw.println("       [--user USER_ID] INTENT");
         pw.println("    Prints all broadcast receivers that can handle the given INTENT.");
         pw.println("");
-        pw.println("  install [-lrtsfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
+        pw.println("  install [-rtsfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
         pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
@@ -3108,7 +3108,6 @@
         pw.println("       [PATH|-]");
         pw.println("    Install an application.  Must provide the apk data to install, either as a");
         pw.println("    file path or '-' to read from stdin.  Options are:");
-        pw.println("      -l: forward lock application");
         pw.println("      -R: disallow replacement of existing application");
         pw.println("      -t: allow test packages");
         pw.println("      -i: specify package name of installer owning the app");
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index a1bc406..7448e00 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -401,10 +401,14 @@
 
             // Restore z-layering, position and stack crop until client has a chance to modify it.
             t.setLayer(animationLeash, mRecord.mAppWindowToken.getPrefixOrderIndex());
-            t.setPosition(animationLeash, mPosition.x, mPosition.y);
-            mTmpRect.set(mStackBounds);
-            mTmpRect.offsetTo(0, 0);
-            t.setWindowCrop(animationLeash, mTmpRect);
+            if (mRecord.mStartBounds != null) {
+                t.setPosition(animationLeash, mRecord.mStartBounds.left, mRecord.mStartBounds.top);
+                t.setWindowCrop(animationLeash, mRecord.mStartBounds.width(),
+                        mRecord.mStartBounds.height());
+            } else {
+                t.setPosition(animationLeash, mPosition.x, mPosition.y);
+                t.setWindowCrop(animationLeash, mStackBounds.width(), mStackBounds.height());
+            }
             mCapturedLeash = animationLeash;
             mCapturedFinishCallback = finishCallback;
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3874fdc..b25677a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7719,11 +7719,6 @@
 
         mInputManager.registerInputChannel(inputChannel, null /* generate new token */);
 
-        // Prevent the java finalizer from breaking the input channel. But we won't
-        // do any further management so we just release the java ref and let the
-        // InputDispatcher hold the last ref.
-        inputChannel.release();
-
         InputWindowHandle h = new InputWindowHandle(null, null, displayId);
         h.token = inputChannel.getToken();
         h.name = name;
@@ -7746,5 +7741,10 @@
         SurfaceControl.Transaction t = new SurfaceControl.Transaction();
         t.setInputWindowInfo(surface, h);
         t.apply();
+
+        // Prevent the java finalizer from breaking the input channel. But we won't
+        // do any further management so we just release the java ref and let the
+        // InputDispatcher hold the last ref.
+        inputChannel.release();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 74791e2..3e05dcc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -110,7 +110,7 @@
             assertEquals(false, app.isTranslucent);
             verify(mMockTransaction).setLayer(mMockLeash, app.prefixOrderIndex);
             verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
-            verify(mMockTransaction).setWindowCrop(mMockLeash, new Rect(0, 0, 100, 50));
+            verify(mMockTransaction).setWindowCrop(mMockLeash, 100, 50);
 
             finishedCaptor.getValue().onAnimationFinished();
             verify(mFinishedCallback).onAnimationFinished(eq(adapter));
@@ -251,8 +251,9 @@
             assertEquals(win.mWinAnimator.mLastClipRect, app.clipRect);
             assertEquals(false, app.isTranslucent);
             verify(mMockTransaction).setLayer(mMockLeash, app.prefixOrderIndex);
-            verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
-            verify(mMockTransaction).setWindowCrop(mMockLeash, new Rect(0, 0, 200, 200));
+            verify(mMockTransaction).setPosition(
+                    mMockLeash, app.startBounds.left, app.startBounds.top);
+            verify(mMockTransaction).setWindowCrop(mMockLeash, 200, 200);
             verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
 
             finishedCaptor.getValue().onAnimationFinished();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e9c24cd..6bf7bfb9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -634,10 +634,19 @@
      */
     public static final int SAP_START_FAILURE_NO_CHANNEL = 1;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"IFACE_IP_MODE_"}, value = {
+            IFACE_IP_MODE_UNSPECIFIED,
+            IFACE_IP_MODE_CONFIGURATION_ERROR,
+            IFACE_IP_MODE_TETHERED,
+            IFACE_IP_MODE_LOCAL_ONLY})
+    public @interface IfaceIpMode {}
+
     /**
      * Interface IP mode unspecified.
      *
-     * @see updateInterfaceIpState(String, int)
+     * @see #updateInterfaceIpState(String, int)
      *
      * @hide
      */
@@ -646,7 +655,7 @@
     /**
      * Interface IP mode for configuration error.
      *
-     * @see updateInterfaceIpState(String, int)
+     * @see #updateInterfaceIpState(String, int)
      *
      * @hide
      */
@@ -655,7 +664,7 @@
     /**
      * Interface IP mode for tethering.
      *
-     * @see updateInterfaceIpState(String, int)
+     * @see #updateInterfaceIpState(String, int)
      *
      * @hide
      */
@@ -664,7 +673,7 @@
     /**
      * Interface IP mode for Local Only Hotspot.
      *
-     * @see updateInterfaceIpState(String, int)
+     * @see #updateInterfaceIpState(String, int)
      *
      * @hide
      */
@@ -2670,9 +2679,9 @@
     /**
      * Call allowing ConnectivityService to update WifiService with interface mode changes.
      *
-     * The possible modes include: {@link IFACE_IP_MODE_TETHERED},
-     *                             {@link IFACE_IP_MODE_LOCAL_ONLY},
-     *                             {@link IFACE_IP_MODE_CONFIGURATION_ERROR}
+     * The possible modes include: {@link #IFACE_IP_MODE_TETHERED},
+     *                             {@link #IFACE_IP_MODE_LOCAL_ONLY},
+     *                             {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}
      *
      * @param ifaceName String name of the updated interface
      * @param mode int representing the new mode
@@ -3397,6 +3406,7 @@
 
         private final CloseGuard mCloseGuard = CloseGuard.get();
         private final WifiConfiguration mConfig;
+        private boolean mClosed = false;
 
         /** @hide */
         @VisibleForTesting
@@ -3412,8 +3422,13 @@
         @Override
         public void close() {
             try {
-                stopLocalOnlyHotspot();
-                mCloseGuard.close();
+                synchronized (mLock) {
+                    if (!mClosed) {
+                        mClosed = true;
+                        stopLocalOnlyHotspot();
+                        mCloseGuard.close();
+                    }
+                }
             } catch (Exception e) {
                 Log.e(TAG, "Failed to stop Local Only Hotspot.");
             }