Merge "Ambient wallpaper API feedback"
diff --git a/api/current.txt b/api/current.txt
index 7c32ef0..1b5b3ee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -480,6 +480,10 @@
     field public static final int dashGap = 16843175; // 0x10101a7
     field public static final int dashWidth = 16843174; // 0x10101a6
     field public static final int data = 16842798; // 0x101002e
+    field public static final int dataRetentionTime = 16844189; // 0x101059d
+    field public static final int dataSentOffDevice = 16844186; // 0x101059a
+    field public static final int dataSharedWithThirdParty = 16844187; // 0x101059b
+    field public static final int dataUsedForMonetization = 16844188; // 0x101059c
     field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
     field public static final int datePickerMode = 16843955; // 0x10104b3
     field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -1495,6 +1499,7 @@
     field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
+    field public static final int usageInfoRequired = 16844185; // 0x1010599
     field public static final int use32bitAbi = 16844053; // 0x1010515
     field public static final int useAppZygote = 16844184; // 0x1010598
     field public static final int useDefaultMargins = 16843641; // 0x1010379
@@ -3802,6 +3807,7 @@
     method public void overridePendingTransition(int, int);
     method public void postponeEnterTransition();
     method public void recreate();
+    method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
     method public void registerForContextMenu(android.view.View);
     method public boolean releaseInstance();
     method public final deprecated void removeDialog(int);
@@ -3879,6 +3885,7 @@
     method public deprecated void stopManagingCursor(android.database.Cursor);
     method public void takeKeyEvents(boolean);
     method public void triggerSearch(java.lang.String, android.os.Bundle);
+    method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
     method public void unregisterForContextMenu(android.view.View);
     field public static final int DEFAULT_KEYS_DIALER = 1; // 0x1
     field public static final int DEFAULT_KEYS_DISABLE = 0; // 0x0
@@ -11169,8 +11176,8 @@
     field public android.content.pm.ProviderInfo[] providers;
     field public android.content.pm.ActivityInfo[] receivers;
     field public android.content.pm.FeatureInfo[] reqFeatures;
-    field public java.lang.String[] requestedPermissions;
-    field public int[] requestedPermissionsFlags;
+    field public deprecated java.lang.String[] requestedPermissions;
+    field public deprecated int[] requestedPermissionsFlags;
     field public android.content.pm.ServiceInfo[] services;
     field public java.lang.String sharedUserId;
     field public int sharedUserLabel;
@@ -11178,6 +11185,7 @@
     field public android.content.pm.SigningInfo signingInfo;
     field public java.lang.String[] splitNames;
     field public int[] splitRevisionCodes;
+    field public android.content.pm.UsesPermissionInfo[] usesPermissions;
     field public deprecated int versionCode;
     field public java.lang.String versionName;
   }
@@ -11653,6 +11661,7 @@
     field public java.lang.String group;
     field public java.lang.CharSequence nonLocalizedDescription;
     field public deprecated int protectionLevel;
+    field public boolean usageInfoRequired;
   }
 
   public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
@@ -11832,6 +11841,28 @@
     field public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR;
   }
 
+  public final class UsesPermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDataRetention();
+    method public int getDataRetentionWeeks();
+    method public int getDataSentOffDevice();
+    method public int getDataSharedWithThirdParty();
+    method public int getDataUsedForMonetization();
+    method public int getFlags();
+    method public java.lang.String getPermission();
+    field public static final android.os.Parcelable.Creator<android.content.pm.UsesPermissionInfo> CREATOR;
+    field public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+    field public static final int RETENTION_NOT_RETAINED = 1; // 0x1
+    field public static final int RETENTION_SPECIFIED = 4; // 0x4
+    field public static final int RETENTION_UNDEFINED = 0; // 0x0
+    field public static final int RETENTION_UNLIMITED = 3; // 0x3
+    field public static final int RETENTION_USER_SELECTED = 2; // 0x2
+    field public static final int USAGE_NO = 3; // 0x3
+    field public static final int USAGE_UNDEFINED = 0; // 0x0
+    field public static final int USAGE_USER_TRIGGERED = 2; // 0x2
+    field public static final int USAGE_YES = 1; // 0x1
+  }
+
   public final class VersionedPackage implements android.os.Parcelable {
     ctor public VersionedPackage(java.lang.String, int);
     ctor public VersionedPackage(java.lang.String, long);
@@ -13941,6 +13972,7 @@
   }
 
   public final class Insets {
+    method public static android.graphics.Insets add(android.graphics.Insets, android.graphics.Insets);
     method public static android.graphics.Insets of(int, int, int, int);
     method public static android.graphics.Insets of(android.graphics.Rect);
     field public static final android.graphics.Insets NONE;
@@ -14693,6 +14725,7 @@
     method public float getTranslationX();
     method public float getTranslationY();
     method public float getTranslationZ();
+    method public long getUniqueId();
     method public int getWidth();
     method public boolean hasDisplayList();
     method public boolean hasIdentityMatrix();
@@ -15046,6 +15079,7 @@
     method public void invalidateSelf();
     method public boolean isAutoMirrored();
     method public boolean isFilterBitmap();
+    method public boolean isProjected();
     method public boolean isStateful();
     method public final boolean isVisible();
     method public void jumpToCurrentState();
diff --git a/api/system-current.txt b/api/system-current.txt
index b43f6c6..b4c7336 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3685,6 +3685,10 @@
 
   public class WifiManager {
     method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+    method public void connect(int, android.net.wifi.WifiManager.ActionListener);
+    method public void disable(int, android.net.wifi.WifiManager.ActionListener);
+    method public void disableEphemeralNetwork(java.lang.String);
+    method public void forget(int, android.net.wifi.WifiManager.ActionListener);
     method public java.util.List<android.net.wifi.WifiConfiguration> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
     method public java.util.List<android.net.wifi.hotspot2.OsuProvider> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
     method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
@@ -3696,6 +3700,7 @@
     method public boolean isWifiApEnabled();
     method public boolean isWifiScannerSupported();
     method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
+    method public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
     method public boolean startScan(android.os.WorkSource);
     method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
diff --git a/api/test-current.txt b/api/test-current.txt
index 8c710c1..c0f7ab6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -61,6 +61,7 @@
   }
 
   public class ActivityTaskManager {
+    method public void clearLaunchParamsForPackages(java.util.List<java.lang.String>);
     method public java.lang.String listAllStacks();
     method public void moveTaskToStack(int, int, boolean);
     method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 0277b7e..25bd033 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1461,7 +1461,6 @@
 Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
 Landroid/view/IWindowManager;->showStrictModeViolation(Z)V
 Landroid/view/IWindowManager;->thawRotation()V
-Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
 Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowSession;
 Landroid/view/IWindowSession;->finishDrawing(Landroid/view/IWindow;)V
 Landroid/view/IWindowSession;->getInTouchMode()Z
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 5940c45..3095925 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -4117,6 +4117,10 @@
 com.android.internal.util.VirtualRefBasePtr
 com.android.internal.util.XmlUtils
 com.android.internal.util.XmlUtils$WriteMapCallback
+com.android.internal.util.function.NonaConsumer
+com.android.internal.util.function.NonaFunction
+com.android.internal.util.function.OctConsumer
+com.android.internal.util.function.OctFunction
 com.android.internal.util.function.HeptConsumer
 com.android.internal.util.function.HeptFunction
 com.android.internal.util.function.HexConsumer
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 83fab7e..05bb9a1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -827,6 +827,8 @@
     /** The screen observation manager. Always access via {@link #getIntelligenceManager()}. */
     @Nullable private IntelligenceManager mIntelligenceManager;
 
+    private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
+            new ArrayList<Application.ActivityLifecycleCallbacks>();
 
     static final class NonConfigurationInstances {
         Object activity;
@@ -1065,6 +1067,288 @@
     }
 
     /**
+     * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
+     * lifecycle callbacks for only this Activity.
+     * <p>
+     * In relation to any
+     * {@link Application#registerActivityLifecycleCallbacks Application registered callbacks},
+     * the callbacks registered here will always occur nested within those callbacks. This means:
+     * <ul>
+     *     <li>Pre events will first be sent to Application registered callbacks, then to callbacks
+     *     registered here.</li>
+     *     <li>{@link Application.ActivityLifecycleCallbacks#onActivityCreated(Activity, Bundle)},
+     *     {@link Application.ActivityLifecycleCallbacks#onActivityStarted(Activity)}, and
+     *     {@link Application.ActivityLifecycleCallbacks#onActivityResumed(Activity)} will
+     *     be sent first to Application registered callbacks, then to callbacks registered here.
+     *     For all other events, callbacks registered here will be sent first.</li>
+     *     <li>Post events will first be sent to callbacks registered here, then to
+     *     Application registered callbacks.</li>
+     * </ul>
+     * <p>
+     * If multiple callbacks are registered here, they receive events in a first in (up through
+     * {@link Application.ActivityLifecycleCallbacks#onActivityPostResumed}, last out
+     * ordering.
+     * <p>
+     * It is strongly recommended to register this in the constructor of your Activity to ensure
+     * you get all available callbacks. As this callback is associated with only this Activity,
+     * it is not usually necessary to {@link #unregisterActivityLifecycleCallbacks unregister} it
+     * unless you specifically do not want to receive further lifecycle callbacks.
+     *
+     * @param callback The callback instance to register
+     */
+    public void registerActivityLifecycleCallbacks(
+            @NonNull Application.ActivityLifecycleCallbacks callback) {
+        synchronized (mActivityLifecycleCallbacks) {
+            mActivityLifecycleCallbacks.add(callback);
+        }
+    }
+
+    /**
+     * Unregister an {@link Application.ActivityLifecycleCallbacks} previously registered
+     * with {@link #registerActivityLifecycleCallbacks}. It will not receive any further
+     * callbacks.
+     *
+     * @param callback The callback instance to unregister
+     * @see #registerActivityLifecycleCallbacks
+     */
+    public void unregisterActivityLifecycleCallbacks(
+            @NonNull Application.ActivityLifecycleCallbacks callback) {
+        synchronized (mActivityLifecycleCallbacks) {
+            mActivityLifecycleCallbacks.remove(callback);
+        }
+    }
+
+    private void dispatchActivityPreCreated(@Nullable Bundle savedInstanceState) {
+        getApplication().dispatchActivityPreCreated(this, savedInstanceState);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(this,
+                        savedInstanceState);
+            }
+        }
+    }
+
+    private void dispatchActivityCreated(@Nullable Bundle savedInstanceState) {
+        getApplication().dispatchActivityCreated(this, savedInstanceState);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(this,
+                        savedInstanceState);
+            }
+        }
+    }
+
+    private void dispatchActivityPostCreated(@Nullable Bundle savedInstanceState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(this,
+                        savedInstanceState);
+            }
+        }
+        getApplication().dispatchActivityPostCreated(this, savedInstanceState);
+    }
+
+    private void dispatchActivityPreStarted() {
+        getApplication().dispatchActivityPreStarted(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(this);
+            }
+        }
+    }
+
+    private void dispatchActivityStarted() {
+        getApplication().dispatchActivityStarted(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(this);
+            }
+        }
+    }
+
+    private void dispatchActivityPostStarted() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivityPostStarted(this);
+            }
+        }
+        getApplication().dispatchActivityPostStarted(this);
+    }
+
+    private void dispatchActivityPreResumed() {
+        getApplication().dispatchActivityPreResumed(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(this);
+            }
+        }
+    }
+
+    private void dispatchActivityResumed() {
+        getApplication().dispatchActivityResumed(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityResumed(this);
+            }
+        }
+    }
+
+    private void dispatchActivityPostResumed() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = 0; i < callbacks.length; i++) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(this);
+            }
+        }
+        getApplication().dispatchActivityPostResumed(this);
+    }
+
+    private void dispatchActivityPrePaused() {
+        getApplication().dispatchActivityPrePaused(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(this);
+            }
+        }
+    }
+
+    private void dispatchActivityPaused() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPaused(this);
+            }
+        }
+        getApplication().dispatchActivityPaused(this);
+    }
+
+    private void dispatchActivityPostPaused() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(this);
+            }
+        }
+        getApplication().dispatchActivityPostPaused(this);
+    }
+
+    private void dispatchActivityPreStopped() {
+        getApplication().dispatchActivityPreStopped(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(this);
+            }
+        }
+    }
+
+    private void dispatchActivityStopped() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStopped(this);
+            }
+        }
+        getApplication().dispatchActivityStopped(this);
+    }
+
+    private void dispatchActivityPostStopped() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivityPostStopped(this);
+            }
+        }
+        getApplication().dispatchActivityPostStopped(this);
+    }
+
+    private void dispatchActivityPreSaveInstanceState(@NonNull Bundle outState) {
+        getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivityPreSaveInstanceState(this, outState);
+            }
+        }
+    }
+
+    private void dispatchActivitySaveInstanceState(@NonNull Bundle outState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivitySaveInstanceState(this, outState);
+            }
+        }
+        getApplication().dispatchActivitySaveInstanceState(this, outState);
+    }
+
+    private void dispatchActivityPostSaveInstanceState(@NonNull Bundle outState) {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivityPostSaveInstanceState(this, outState);
+            }
+        }
+        getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+    }
+
+    private void dispatchActivityPreDestroyed() {
+        getApplication().dispatchActivityPreDestroyed(this);
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivityPreDestroyed(this);
+            }
+        }
+    }
+
+    private void dispatchActivityDestroyed() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityDestroyed(this);
+            }
+        }
+        getApplication().dispatchActivityDestroyed(this);
+    }
+
+    private void dispatchActivityPostDestroyed() {
+        Object[] callbacks = collectActivityLifecycleCallbacks();
+        if (callbacks != null) {
+            for (int i = callbacks.length - 1; i >= 0; i--) {
+                ((Application.ActivityLifecycleCallbacks) callbacks[i])
+                        .onActivityPostDestroyed(this);
+            }
+        }
+        getApplication().dispatchActivityPostDestroyed(this);
+    }
+
+    private Object[] collectActivityLifecycleCallbacks() {
+        Object[] callbacks = null;
+        synchronized (mActivityLifecycleCallbacks) {
+            if (mActivityLifecycleCallbacks.size() > 0) {
+                callbacks = mActivityLifecycleCallbacks.toArray();
+            }
+        }
+        return callbacks;
+    }
+
+    /**
      * Called when the activity is starting.  This is where most initialization
      * should go: calling {@link #setContentView(int)} to inflate the
      * activity's UI, using {@link #findViewById} to programmatically interact
@@ -1119,7 +1403,7 @@
                     ? mLastNonConfigurationInstances.fragments : null);
         }
         mFragments.dispatchCreate();
-        getApplication().dispatchActivityCreated(this, savedInstanceState);
+        dispatchActivityCreated(savedInstanceState);
         if (mVoiceInteractor != null) {
             mVoiceInteractor.attachActivity(this);
         }
@@ -1355,7 +1639,7 @@
 
         mFragments.doLoaderStart();
 
-        getApplication().dispatchActivityStarted(this);
+        dispatchActivityStarted();
 
         if (mAutoFillResetNeeded) {
             getAutofillManager().onVisibleForAutofill();
@@ -1426,7 +1710,7 @@
     @CallSuper
     protected void onResume() {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
-        getApplication().dispatchActivityResumed(this);
+        dispatchActivityResumed();
         mActivityTransitionState.onResume(this, isTopOfTask());
         enableAutofillCompatibilityIfNeeded();
         if (mAutoFillResetNeeded) {
@@ -1642,13 +1926,13 @@
      * @param outState The bundle to save the state to.
      */
     final void performSaveInstanceState(@NonNull Bundle outState) {
-        getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+        dispatchActivityPreSaveInstanceState(outState);
         onSaveInstanceState(outState);
         saveManagedDialogs(outState);
         mActivityTransitionState.saveState(outState);
         storeHasCurrentPermissionRequest(outState);
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
-        getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+        dispatchActivityPostSaveInstanceState(outState);
     }
 
     /**
@@ -1662,13 +1946,13 @@
      */
     final void performSaveInstanceState(@NonNull Bundle outState,
             @NonNull PersistableBundle outPersistentState) {
-        getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+        dispatchActivityPreSaveInstanceState(outState);
         onSaveInstanceState(outState, outPersistentState);
         saveManagedDialogs(outState);
         storeHasCurrentPermissionRequest(outState);
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
                 ", " + outPersistentState);
-        getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+        dispatchActivityPostSaveInstanceState(outState);
     }
 
     /**
@@ -1731,7 +2015,7 @@
             outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
             getAutofillManager().onSaveInstanceState(outState);
         }
-        getApplication().dispatchActivitySaveInstanceState(this, outState);
+        dispatchActivitySaveInstanceState(outState);
     }
 
     /**
@@ -1831,7 +2115,7 @@
     @CallSuper
     protected void onPause() {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
-        getApplication().dispatchActivityPaused(this);
+        dispatchActivityPaused();
         if (mAutoFillResetNeeded) {
             if (!mAutoFillIgnoreFirstResumePause) {
                 if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill notifyViewExited " + this);
@@ -2015,7 +2299,7 @@
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
         if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
         mActivityTransitionState.onStop();
-        getApplication().dispatchActivityStopped(this);
+        dispatchActivityStopped();
         mTranslucentCallback = null;
         mCalled = true;
 
@@ -2104,7 +2388,7 @@
             mActionBar.onDestroy();
         }
 
-        getApplication().dispatchActivityDestroyed(this);
+        dispatchActivityDestroyed();
 
         notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);
 
@@ -7284,7 +7568,7 @@
 
     @UnsupportedAppUsage
     final void performCreate(Bundle icicle, PersistableBundle persistentState) {
-        getApplication().dispatchActivityPreCreated(this, icicle);
+        dispatchActivityPreCreated(icicle);
         mCanEnterPictureInPicture = true;
         restoreHasCurrentPermissionRequest(icicle);
         if (persistentState != null) {
@@ -7299,7 +7583,7 @@
                 com.android.internal.R.styleable.Window_windowNoDisplay, false);
         mFragments.dispatchActivityCreated();
         mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
-        getApplication().dispatchActivityPostCreated(this, icicle);
+        dispatchActivityPostCreated(icicle);
     }
 
     final void performNewIntent(@NonNull Intent intent) {
@@ -7308,7 +7592,7 @@
     }
 
     final void performStart(String reason) {
-        getApplication().dispatchActivityPreStarted(this);
+        dispatchActivityPreStarted();
         mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
         mFragments.noteStateNotSaved();
         mCalled = false;
@@ -7351,7 +7635,7 @@
         }
 
         mActivityTransitionState.enterReady(this);
-        getApplication().dispatchActivityPostStarted(this);
+        dispatchActivityPostStarted();
     }
 
     /**
@@ -7406,7 +7690,7 @@
     }
 
     final void performResume(boolean followedByPause, String reason) {
-        getApplication().dispatchActivityPreResumed(this);
+        dispatchActivityPreResumed();
         performRestart(true /* start */, reason);
 
         mFragments.execPendingActions();
@@ -7456,11 +7740,11 @@
                 "Activity " + mComponent.toShortString() +
                 " did not call through to super.onPostResume()");
         }
-        getApplication().dispatchActivityPostResumed(this);
+        dispatchActivityPostResumed();
     }
 
     final void performPause() {
-        getApplication().dispatchActivityPrePaused(this);
+        dispatchActivityPrePaused();
         mDoReportFullyDrawn = false;
         mFragments.dispatchPause();
         mCalled = false;
@@ -7473,7 +7757,7 @@
                     "Activity " + mComponent.toShortString() +
                     " did not call through to super.onPause()");
         }
-        getApplication().dispatchActivityPostPaused(this);
+        dispatchActivityPostPaused();
     }
 
     final void performUserLeaving() {
@@ -7489,7 +7773,7 @@
         mCanEnterPictureInPicture = false;
 
         if (!mStopped) {
-            getApplication().dispatchActivityPreStopped(this);
+            dispatchActivityPreStopped();
             if (mWindow != null) {
                 mWindow.closeAllPanels();
             }
@@ -7524,13 +7808,13 @@
             }
 
             mStopped = true;
-            getApplication().dispatchActivityPostStopped(this);
+            dispatchActivityPostStopped();
         }
         mResumed = false;
     }
 
     final void performDestroy() {
-        getApplication().dispatchActivityPreDestroyed(this);
+        dispatchActivityPreDestroyed();
         mDestroyed = true;
         mWindow.destroy();
         mFragments.dispatchDestroy();
@@ -7540,7 +7824,7 @@
         if (mVoiceInteractor != null) {
             mVoiceInteractor.detachActivity();
         }
-        getApplication().dispatchActivityPostDestroyed(this);
+        dispatchActivityPostDestroyed();
     }
 
     final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 56ccf6f..6fdf7c8 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -433,4 +433,18 @@
         }
         return sb.toString();
     }
+
+    /**
+     * Clears launch params for the given package.
+     * @param packageNames the names of the packages of which the launch params are to be cleared
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void clearLaunchParamsForPackages(List<String> packageNames) {
+        try {
+            getService().clearLaunchParamsForPackages(packageNames);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 09b77d5..777a494 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -445,4 +445,9 @@
     void setPackageScreenCompatMode(in String packageName, int mode);
     boolean getPackageAskScreenCompat(in String packageName);
     void setPackageAskScreenCompat(in String packageName, boolean ask);
+
+    /**
+     * Clears launch params for given packages.
+     */
+    void clearLaunchParamsForPackages(in List<String> packageNames);
 }
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 1c9a43a..673d85f 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,7 +1,6 @@
-artikz@google.com
+anniemeng@google.com
 brufino@google.com
 bryanmawhinney@google.com
 ctate@google.com
 jorlow@google.com
-mkarpinski@google.com
 
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index ecdd810..099d15a 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -22,6 +22,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Overall information about the contents of a package.  This corresponds
  * to all of the information collected from AndroidManifest.xml.
@@ -204,7 +207,10 @@
      * {@link PackageManager#GET_PERMISSIONS} was set.  This list includes
      * all permissions requested, even those that were not granted or known
      * by the system at install time.
+     *
+     * @deprecated Use {@link #usesPermissions}
      */
+    @Deprecated
     public String[] requestedPermissions;
 
     /**
@@ -214,10 +220,23 @@
      * {@link PackageManager#GET_PERMISSIONS} was set.  Each value matches
      * the corresponding entry in {@link #requestedPermissions}, and will have
      * the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
+     *
+     * @deprecated Use {@link #usesPermissions}
      */
+    @Deprecated
     public int[] requestedPermissionsFlags;
 
     /**
+     * Array of all {@link android.R.styleable#AndroidManifestUsesPermission
+     * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
+     * or null if there were none.  This is only filled in if the flag
+     * {@link PackageManager#GET_PERMISSIONS} was set.  This list includes
+     * all permissions requested, even those that were not granted or known
+     * by the system at install time.
+     */
+    public UsesPermissionInfo[] usesPermissions;
+
+    /**
      * Flag for {@link #requestedPermissionsFlags}: the requested permission
      * is required for the application to run; the user can not optionally
      * disable it.  Currently all permissions are required.
@@ -456,6 +475,7 @@
         dest.writeTypedArray(permissions, parcelableFlags);
         dest.writeStringArray(requestedPermissions);
         dest.writeIntArray(requestedPermissionsFlags);
+        dest.writeTypedArray(usesPermissions, parcelableFlags);
         dest.writeTypedArray(signatures, parcelableFlags);
         dest.writeTypedArray(configPreferences, parcelableFlags);
         dest.writeTypedArray(reqFeatures, parcelableFlags);
@@ -520,6 +540,7 @@
         permissions = source.createTypedArray(PermissionInfo.CREATOR);
         requestedPermissions = source.createStringArray();
         requestedPermissionsFlags = source.createIntArray();
+        usesPermissions = source.createTypedArray(UsesPermissionInfo.CREATOR);
         signatures = source.createTypedArray(Signature.CREATOR);
         configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
         reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d00c9a0..49189e5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -785,18 +785,23 @@
                     pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
                 }
             }
-            N = p.requestedPermissions.size();
+            N = p.usesPermissionInfos.size();
             if (N > 0) {
                 pi.requestedPermissions = new String[N];
                 pi.requestedPermissionsFlags = new int[N];
+                pi.usesPermissions = new UsesPermissionInfo[N];
                 for (int i=0; i<N; i++) {
-                    final String perm = p.requestedPermissions.get(i);
+                    UsesPermissionInfo info = p.usesPermissionInfos.get(i);
+                    final String perm = info.getPermission();
                     pi.requestedPermissions[i] = perm;
+                    int permissionFlags = 0;
                     // The notion of required permissions is deprecated but for compatibility.
-                    pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+                    permissionFlags |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
                     if (grantedPermissions != null && grantedPermissions.contains(perm)) {
-                        pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+                        permissionFlags |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
                     }
+                    pi.requestedPermissionsFlags[i] = permissionFlags;
+                    pi.usesPermissions[i] = new UsesPermissionInfo(info, permissionFlags);
                 }
             }
         }
@@ -2114,12 +2119,12 @@
                     return null;
                 }
             } else if (tagName.equals(TAG_USES_PERMISSION)) {
-                if (!parseUsesPermission(pkg, res, parser)) {
+                if (!parseUsesPermission(pkg, res, parser, outError)) {
                     return null;
                 }
             } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
                     || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
-                if (!parseUsesPermission(pkg, res, parser)) {
+                if (!parseUsesPermission(pkg, res, parser, outError)) {
                     return null;
                 }
             } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
@@ -2442,7 +2447,7 @@
                     newPermsMsg.append(' ');
                 }
                 newPermsMsg.append(npi.name);
-                pkg.requestedPermissions.add(npi.name);
+                addRequestedPermission(pkg, npi.name);
                 pkg.implicitPermissions.add(npi.name);
             }
         }
@@ -2463,7 +2468,7 @@
             for (int in = 0; in < newPerms.size(); in++) {
                 final String perm = newPerms.get(in);
                 if (!pkg.requestedPermissions.contains(perm)) {
-                    pkg.requestedPermissions.add(perm);
+                    addRequestedPermission(pkg, perm);
                     pkg.implicitPermissions.add(perm);
                 }
             }
@@ -2543,13 +2548,13 @@
             }
         } else {
             if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
-                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
+                addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_AUDIO);
             }
             if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
-                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
+                addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_VIDEO);
             }
             if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
-                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
+                addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_IMAGES);
             }
         }
 
@@ -2589,6 +2594,14 @@
     }
 
     /**
+     * Helper method for adding a requested permission to a package outside of a uses-permission.
+     */
+    private void addRequestedPermission(Package pkg, String permission) {
+        pkg.requestedPermissions.add(permission);
+        pkg.usesPermissionInfos.add(new UsesPermissionInfo(permission));
+    }
+
+    /**
      * Computes the targetSdkVersion to use at runtime. If the package is not
      * compatible with this platform, populates {@code outError[0]} with an
      * error message.
@@ -2845,8 +2858,8 @@
         return certSha256Digests;
     }
 
-    private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
-            throws XmlPullParserException, IOException {
+    private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
+            String[] outError) throws XmlPullParserException, IOException {
         TypedArray sa = res.obtainAttributes(parser,
                 com.android.internal.R.styleable.AndroidManifestUsesPermission);
 
@@ -2870,6 +2883,44 @@
         final String requiredNotfeature = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
 
+        int dataSentOffDevice = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSentOffDevice, 0);
+
+        int dataSharedWithThirdParty = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSharedWithThirdParty, 0);
+
+        int dataUsedForMonetization = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataUsedForMonetization, 0);
+
+        int retentionWeeks = -1;
+        int retention;
+
+        String rawRetention = sa.getString(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime);
+
+        if (rawRetention == null) {
+            retention = UsesPermissionInfo.RETENTION_UNDEFINED;
+        } else if ("notRetained".equals(rawRetention)) {
+            retention = UsesPermissionInfo.RETENTION_NOT_RETAINED;
+        } else if ("userSelected".equals(rawRetention)) {
+            retention = UsesPermissionInfo.RETENTION_USER_SELECTED;
+        } else if ("unlimited".equals(rawRetention)) {
+            retention = UsesPermissionInfo.RETENTION_UNLIMITED;
+        } else {
+            // A number of weeks was specified
+            retention = UsesPermissionInfo.RETENTION_SPECIFIED;
+            retentionWeeks = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime,
+                -1);
+
+            if (retentionWeeks < 0) {
+                outError[0] = "Bad value provided for dataRetentionTime.";
+                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+                XmlUtils.skipCurrentTag(parser);
+                sa.recycle();
+                return false;
+            }
+        }
         sa.recycle();
 
         XmlUtils.skipCurrentTag(parser);
@@ -2902,6 +2953,10 @@
                     + parser.getPositionDescription());
         }
 
+        UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice,
+                dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks);
+        pkg.usesPermissionInfos.add(info);
+
         return true;
     }
 
@@ -3236,6 +3291,10 @@
         perm.info.flags = sa.getInt(
                 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
 
+        perm.info.usageInfoRequired = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestPermission_usageInfoRequired, 0)
+                != 0;
+
         sa.recycle();
 
         if (perm.info.protectionLevel == -1) {
@@ -6370,6 +6429,9 @@
         @UnsupportedAppUsage
         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
 
+        public final ArrayList<UsesPermissionInfo> usesPermissionInfos =
+                new ArrayList<>();
+
         /** Permissions requested but not in the manifest. */
         public final ArrayList<String> implicitPermissions = new ArrayList<>();
 
@@ -6900,6 +6962,7 @@
 
             dest.readStringList(requestedPermissions);
             internStringArrayList(requestedPermissions);
+            dest.readParcelableList(usesPermissionInfos, boot);
             dest.readStringList(implicitPermissions);
             internStringArrayList(implicitPermissions);
             protectedBroadcasts = dest.createStringArrayList();
@@ -7066,6 +7129,7 @@
             dest.writeParcelableList(instrumentation, flags);
 
             dest.writeStringList(requestedPermissions);
+            dest.writeParcelableList(usesPermissionInfos, flags);
             dest.writeStringList(implicitPermissions);
             dest.writeStringList(protectedBroadcasts);
 
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 60c06a1..7523949 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -20,6 +20,7 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -308,6 +309,12 @@
      */
     public CharSequence nonLocalizedDescription;
 
+    /**
+     * If {@code true} an application targeting {@link Build.VERSION_CODES.Q} <em>must</em>
+     * include permission data usage information in order to be able to be granted this permission.
+     */
+    public boolean usageInfoRequired;
+
     /** @hide */
     public static int fixProtectionLevel(int level) {
         if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -394,6 +401,7 @@
         descriptionRes = orig.descriptionRes;
         requestRes = orig.requestRes;
         nonLocalizedDescription = orig.nonLocalizedDescription;
+        usageInfoRequired = orig.usageInfoRequired;
     }
 
     /**
@@ -458,6 +466,7 @@
         dest.writeInt(descriptionRes);
         dest.writeInt(requestRes);
         TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
+        dest.writeInt(usageInfoRequired ? 1 : 0);
     }
 
     /** @hide */
@@ -498,5 +507,6 @@
         descriptionRes = source.readInt();
         requestRes = source.readInt();
         nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+        usageInfoRequired = source.readInt() != 0;
     }
 }
diff --git a/core/java/android/content/pm/UsesPermissionInfo.java b/core/java/android/content/pm/UsesPermissionInfo.java
new file mode 100644
index 0000000..997552b
--- /dev/null
+++ b/core/java/android/content/pm/UsesPermissionInfo.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.RetentionPolicy;
+/**
+ * Information you can retrive about a particular application requested permission. This
+ * corresponds to information collected from the AndroidManifest.xml's &lt;uses-permission&gt;
+ * tags.
+ */
+public final class UsesPermissionInfo extends PackageItemInfo implements Parcelable {
+
+    /**
+     * Flag for {@link #flags}: the requested permission is currently granted to the application.
+     */
+    public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 1 << 1;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"FLAG_"}, value = {FLAG_REQUESTED_PERMISSION_GRANTED})
+    @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+    public @interface Flags {}
+
+    /** An unset value for {@link #getDataSentOffDevice()},
+     * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()}
+     */
+    public static final int USAGE_UNDEFINED = 0;
+
+    /**
+     * A yes value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()},
+     * and {@link #getDataUsedForMonetization()} corresponding to the <code>yes</code> value of
+     * {@link android.R.attrs#dataSentOffDevice}, {@link android.R.attrs#dataSharedWithThirdParty},
+     * and {@link android.R.attrs#dataUsedForMonetization} attributes.
+     */
+    public static final int USAGE_YES = 1;
+
+    /**
+     * A user triggered only value for {@link #getDataSentOffDevice()},
+     * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()}
+     * corresponding to the <code>userTriggered</code> value of
+     * {@link android.R.attrs#dataSentOffDevice}, {@link android.R.attrs#dataSharedWithThirdParty},
+     * and {@link android.R.attrs#dataUsedForMonetization} attributes.
+     */
+    public static final int USAGE_USER_TRIGGERED = 2;
+
+    /**
+     * A no value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()},
+     * and {@link #getDataUsedForMonetization()} corresponding to the <code>no</code> value of
+     * {@link android.R.attrs#dataSentOffDevice}, {@link android.R.attrs#dataSharedWithThirdParty},
+     * and {@link android.R.attrs#dataUsedForMonetization} attributes.
+     */
+    public static final int USAGE_NO = 3;
+
+    /** @hide */
+    @IntDef(prefix = {"USAGE_"}, value = {
+        USAGE_UNDEFINED,
+        USAGE_YES,
+        USAGE_USER_TRIGGERED,
+        USAGE_NO})
+    @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+    public @interface Usage {}
+
+    /**
+     * An unset value for {@link #getDataRetention}.
+     */
+    public static final int RETENTION_UNDEFINED = 0;
+
+    /**
+     * A data not retained value for {@link #getDataRetention()} corresponding to the
+     * <code>notRetained</code> value of {@link android.R.attrs#dataRetentionTime}.
+     */
+    public static final int RETENTION_NOT_RETAINED = 1;
+
+    /**
+     * A user selected value for {@link #getDataRetention()} corresponding to the
+     * <code>userSelected</code> value of {@link android.R.attrs#dataRetentionTime}.
+     */
+    public static final int RETENTION_USER_SELECTED = 2;
+
+    /**
+     * An unlimited value for {@link #getDataRetention()} corresponding to the
+     * <code>unlimited</code> value of {@link android.R.attrs#dataRetentionTime}.
+     */
+    public static final int RETENTION_UNLIMITED = 3;
+
+    /**
+     * A specified value for {@link #getDataRetention()} corresponding to providing the number of
+     * weeks data is retained in {@link android.R.attrs#dataRetentionTime}. The number of weeks
+     * is available in {@link #getDataRetentionWeeks()}.
+     */
+    public static final int RETENTION_SPECIFIED = 4;
+
+    /** @hide */
+    @IntDef(prefix = {"RETENTION_"}, value = {
+        RETENTION_UNDEFINED,
+        RETENTION_NOT_RETAINED,
+        RETENTION_USER_SELECTED,
+        RETENTION_UNLIMITED,
+        RETENTION_SPECIFIED})
+    @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+    public @interface Retention {}
+
+    private final String mPermission;
+    private final @Flags int mFlags;
+    private final @Usage int mDataSentOffDevice;
+    private final @Usage int mDataSharedWithThirdParty;
+    private final @Usage int mDataUsedForMonetization;
+    private final @Retention int mDataRetention;
+    private final int mDataRetentionWeeks;
+
+    /** @hide */
+    public UsesPermissionInfo(String permission) {
+        mPermission = permission;
+        mDataSentOffDevice = USAGE_UNDEFINED;
+        mDataSharedWithThirdParty = USAGE_UNDEFINED;
+        mDataUsedForMonetization = USAGE_UNDEFINED;
+        mDataRetention = RETENTION_UNDEFINED;
+        mDataRetentionWeeks = -1;
+        mFlags = 0;
+    }
+
+    /** @hide */
+    public UsesPermissionInfo(String permission,
+            @Usage int dataSentOffDevice, @Usage int dataSharedWithThirdParty,
+            @Usage int dataUsedForMonetization, @Retention int dataRetention,
+            int dataRetentionWeeks) {
+        mPermission = permission;
+        mDataSentOffDevice = dataSentOffDevice;
+        mDataSharedWithThirdParty = dataSharedWithThirdParty;
+        mDataUsedForMonetization = dataUsedForMonetization;
+        mDataRetention = dataRetention;
+        mDataRetentionWeeks = dataRetentionWeeks;
+        mFlags = 0;
+    }
+
+    /** @hide */
+    public UsesPermissionInfo(UsesPermissionInfo orig) {
+        this(orig, orig.mFlags);
+    }
+
+    /** @hide */
+    public UsesPermissionInfo(UsesPermissionInfo orig, int flags) {
+        super(orig);
+        mPermission = orig.mPermission;
+        mFlags = flags;
+        mDataSentOffDevice = orig.mDataSentOffDevice;
+        mDataSharedWithThirdParty = orig.mDataSharedWithThirdParty;
+        mDataUsedForMonetization = orig.mDataUsedForMonetization;
+        mDataRetention = orig.mDataRetention;
+        mDataRetentionWeeks = orig.mDataRetentionWeeks;
+    }
+
+    /**
+     * The name of the requested permission.
+     */
+    public String getPermission() {
+        return mPermission;
+    }
+
+    public @Flags int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * If the application sends the data guarded by this permission off the device.
+     *
+     * See {@link android.R.attrs#dataSentOffDevice}
+     */
+    public @Usage int getDataSentOffDevice() {
+        return mDataSentOffDevice;
+    }
+
+    /**
+     * If the application or its services shares the data guarded by this permission with third
+     * parties.
+     *
+     * See {@link android.R.attrs#dataSharedWithThirdParty}
+     */
+    public @Usage int getDataSharedWithThirdParty() {
+        return mDataSharedWithThirdParty;
+    }
+
+    /**
+     * If the application or its services use the data guarded by this permission for monetization
+     * purposes.
+     *
+     * See {@link android.R.attrs#dataUsedForMonetization}
+     */
+    public @Usage int getDataUsedForMonetization() {
+        return mDataUsedForMonetization;
+    }
+
+    /**
+     * How long the application or its services store the data guarded by this permission.
+     * If set to {@link #RETENTION_SPECIFIED} {@link #getDataRetentionWeeks()} will contain the
+     * number of weeks the data is stored.
+     *
+     * See {@link android.R.attrs#dataRetentionTime}
+     */
+    public @Retention int getDataRetention() {
+        return mDataRetention;
+    }
+
+    /**
+     * If {@link #getDataRetention()} is {@link #RETENTION_SPECIFIED} the number of weeks the
+     * application or its services store data guarded by this permission.
+     *
+     * @throws IllegalStateException if {@link #getDataRetention} is not
+     * {@link #RETENTION_SPECIFIED}.
+     */
+    public int getDataRetentionWeeks() {
+        if (mDataRetention != RETENTION_SPECIFIED) {
+            throw new IllegalStateException("Data retention weeks not specified");
+        }
+        return mDataRetentionWeeks;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeString(mPermission);
+        dest.writeInt(mFlags);
+        dest.writeInt(mDataSentOffDevice);
+        dest.writeInt(mDataSharedWithThirdParty);
+        dest.writeInt(mDataUsedForMonetization);
+        dest.writeInt(mDataRetention);
+        dest.writeInt(mDataRetentionWeeks);
+    }
+
+    private UsesPermissionInfo(Parcel source) {
+        super(source);
+        mPermission = source.readString();
+        mFlags = source.readInt();
+        mDataSentOffDevice = source.readInt();
+        mDataSharedWithThirdParty = source.readInt();
+        mDataUsedForMonetization = source.readInt();
+        mDataRetention = source.readInt();
+        mDataRetentionWeeks = source.readInt();
+    }
+
+    public static final Creator<UsesPermissionInfo> CREATOR =
+            new Creator<UsesPermissionInfo>() {
+                @Override
+                public UsesPermissionInfo createFromParcel(Parcel source) {
+                    return new UsesPermissionInfo(source);
+                }
+                @Override
+                public UsesPermissionInfo[] newArray(int size) {
+                    return new UsesPermissionInfo[size];
+                }
+            };
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 979bcae..a095b0d 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -57,6 +57,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
+import android.view.InsetsState;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -185,6 +186,7 @@
         final DisplayCutout.ParcelableWrapper mDisplayCutout =
                 new DisplayCutout.ParcelableWrapper();
         DisplayCutout mDispatchedDisplayCutout = DisplayCutout.NO_CUTOUT;
+        final InsetsState mInsetsState = new InsetsState();
         final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
 
         final WindowManager.LayoutParams mLayout
@@ -808,9 +810,11 @@
                         mLayout.windowAnimations =
                                 com.android.internal.R.style.Animation_Wallpaper;
                         mInputChannel = new InputChannel();
+
                         if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
                                 mDisplay.getDisplayId(), mWinFrame, mContentInsets, mStableInsets,
-                                mOutsets, mDisplayCutout, mInputChannel) < 0) {
+                                mOutsets, mDisplayCutout, mInputChannel,
+                                mInsetsState) < 0) {
                             Log.w(TAG, "Failed to add window while updating wallpaper surface.");
                             return;
                         }
@@ -836,7 +840,8 @@
                         mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
                             View.VISIBLE, 0, -1, mWinFrame, mOverscanInsets, mContentInsets,
                             mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
-                            mDisplayCutout, mMergedConfiguration, mSurfaceHolder.mSurface);
+                            mDisplayCutout, mMergedConfiguration, mSurfaceHolder.mSurface,
+                            mInsetsState);
 
                     if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
                             + ", frame=" + mWinFrame);
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 4b8b7f3..af41b69 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -24,6 +24,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.DisplayCutout;
+import android.view.InsetsState;
 
 import com.android.internal.os.IResultReceiver;
 import android.util.MergedConfiguration;
@@ -53,6 +54,12 @@
             in MergedConfiguration newMergedConfiguration, in Rect backDropFrame,
             boolean forceLayout, boolean alwaysConsumeNavBar, int displayId,
             in DisplayCutout.ParcelableWrapper displayCutout);
+
+    /**
+     * Called when the window insets configuration has changed.
+     */
+    void insetsChanged(in InsetsState insetsState);
+
     void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index bedfa9f..9762586 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -28,6 +28,7 @@
 import android.view.IWindowId;
 import android.view.MotionEvent;
 import android.view.WindowManager;
+import android.view.InsetsState;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
@@ -40,10 +41,11 @@
     int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, in int layerStackId, out Rect outFrame,
             out Rect outContentInsets, out Rect outStableInsets, out Rect outOutsets,
-            out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel);
+            out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
+            out InsetsState insetsState);
     int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
             in int viewVisibility, in int layerStackId, out Rect outContentInsets,
-            out Rect outStableInsets);
+            out Rect outStableInsets, out InsetsState insetsState);
     void remove(IWindow window);
 
     /**
@@ -86,6 +88,7 @@
      * config for window, if it is now becoming visible and the merged configuration has changed
      * since it was last displayed.
      * @param outSurface Object in which is placed the new display surface.
+     * @param insetsState The current insets state in the system.
      *
      * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
      * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
@@ -96,7 +99,8 @@
             out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
             out Rect outOutsets, out Rect outBackdropFrame,
             out DisplayCutout.ParcelableWrapper displayCutout,
-            out MergedConfiguration outMergedConfiguration, out Surface outSurface);
+            out MergedConfiguration outMergedConfiguration, out Surface outSurface,
+            out InsetsState insetsState);
 
     /*
      * Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
new file mode 100644
index 0000000..7841d04
--- /dev/null
+++ b/core/java/android/view/InsetsController.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Rect;
+
+import java.io.PrintWriter;
+
+/**
+ * Implements {@link WindowInsetsController} on the client.
+ */
+class InsetsController {
+
+    private final InsetsState mState = new InsetsState();
+    private final Rect mFrame = new Rect();
+
+    void onFrameChanged(Rect frame) {
+        mFrame.set(frame);
+    }
+
+    public InsetsState getState() {
+        return mState;
+    }
+
+    public void setState(InsetsState state) {
+        mState.set(state);
+    }
+
+    /**
+     * @see InsetsState#calculateInsets
+     */
+    WindowInsets calculateInsets(boolean isScreenRound,
+            boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+        return mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout);
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix); pw.println("InsetsController:");
+        mState.dump(prefix + "  ", pw);
+    }
+}
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
new file mode 100644
index 0000000..0cb8ad7
--- /dev/null
+++ b/core/java/android/view/InsetsSource.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.InsetsState.InternalInsetType;
+
+import java.io.PrintWriter;
+
+/**
+ * Represents the state of a single window generating insets for clients.
+ * @hide
+ */
+public class InsetsSource implements Parcelable {
+
+    private final @InternalInsetType int mType;
+
+    /** Frame of the source in screen coordinate space */
+    private final Rect mFrame;
+    private boolean mVisible;
+
+    private final Rect mTmpFrame = new Rect();
+
+    public InsetsSource(@InternalInsetType int type) {
+        mType = type;
+        mFrame = new Rect();
+    }
+
+    public InsetsSource(InsetsSource other) {
+        mType = other.mType;
+        mFrame = new Rect(other.mFrame);
+        mVisible = other.mVisible;
+    }
+
+    public void setFrame(Rect frame) {
+        mFrame.set(frame);
+    }
+
+    public void setVisible(boolean visible) {
+        mVisible = visible;
+    }
+
+    public @InternalInsetType int getType() {
+        return mType;
+    }
+
+    public Rect getFrame() {
+        return mFrame;
+    }
+
+    /**
+     * Calculates the insets this source will cause to a client window.
+     *
+     * @param relativeFrame The frame to calculate the insets relative to.
+     * @param ignoreVisibility If true, always reports back insets even if source isn't visible.
+     * @return The resulting insets.
+     */
+    public Insets calculateInsets(Rect relativeFrame, boolean ignoreVisibility) {
+        if (!ignoreVisibility && !mVisible) {
+            return Insets.NONE;
+        }
+        if (!mTmpFrame.setIntersect(mFrame, relativeFrame)) {
+            return Insets.NONE;
+        }
+
+        // Intersecting at top/bottom
+        if (mTmpFrame.width() == relativeFrame.width()) {
+            if (mTmpFrame.top == relativeFrame.top) {
+                return Insets.of(0, mTmpFrame.height(), 0, 0);
+            } else {
+                return Insets.of(0, 0, 0, mTmpFrame.height());
+            }
+        }
+        // Intersecting at left/right
+        else if (mTmpFrame.height() == relativeFrame.height()) {
+            if (mTmpFrame.left == relativeFrame.left) {
+                return Insets.of(mTmpFrame.width(), 0, 0, 0);
+            } else {
+                return Insets.of(0, 0, mTmpFrame.width(), 0);
+            }
+        } else {
+            return Insets.NONE;
+        }
+    }
+
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix);
+        pw.print("InsetsSource type="); pw.print(InsetsState.typeToString(mType));
+        pw.print(" frame="); pw.print(mFrame.toShortString());
+        pw.print(" visible="); pw.print(mVisible);
+        pw.println();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        InsetsSource that = (InsetsSource) o;
+
+        if (mType != that.mType) return false;
+        if (mVisible != that.mVisible) return false;
+        return mFrame.equals(that.mFrame);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mType;
+        result = 31 * result + mFrame.hashCode();
+        result = 31 * result + (mVisible ? 1 : 0);
+        return result;
+    }
+
+    public InsetsSource(Parcel in) {
+        mType = in.readInt();
+        mFrame = in.readParcelable(null /* loader */);
+        mVisible = in.readBoolean();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mType);
+        dest.writeParcelable(mFrame, 0 /* flags*/);
+        dest.writeBoolean(mVisible);
+    }
+
+    public static final Creator<InsetsSource> CREATOR = new Creator<InsetsSource>() {
+
+        public InsetsSource createFromParcel(Parcel in) {
+            return new InsetsSource(in);
+        }
+
+        public InsetsSource[] newArray(int size) {
+            return new InsetsSource[size];
+        }
+    };
+}
diff --git a/core/java/android/view/InsetsState.aidl b/core/java/android/view/InsetsState.aidl
new file mode 100644
index 0000000..d02ddd1
--- /dev/null
+++ b/core/java/android/view/InsetsState.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable InsetsState;
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
new file mode 100644
index 0000000..9895adc
--- /dev/null
+++ b/core/java/android/view/InsetsState.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.IntDef;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Holder for state of system windows that cause window insets for all other windows in the system.
+ * @hide
+ */
+public class InsetsState implements Parcelable {
+
+    /**
+     * Internal representation of inset source types. This is different from the public API in
+     * {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
+     * at the same time.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "TYPE", value = {
+            TYPE_TOP_BAR,
+            TYPE_SIDE_BAR_1,
+            TYPE_SIDE_BAR_2,
+            TYPE_SIDE_BAR_3,
+            TYPE_IME
+    })
+    public @interface InternalInsetType {}
+
+    static final int FIRST_TYPE = 0;
+
+    /** Top bar. Can be status bar or caption in freeform windowing mode. */
+    public static final int TYPE_TOP_BAR = FIRST_TYPE;
+
+    /**
+     * Up to 3 side bars that appear on left/right/bottom. On phones there is only one side bar
+     * (the navigation bar, see {@link #TYPE_NAVIGATION_BAR}), but other form factors might have
+     * multiple, like Android Auto.
+     */
+    public static final int TYPE_SIDE_BAR_1 = 1;
+    public static final int TYPE_SIDE_BAR_2 = 2;
+    public static final int TYPE_SIDE_BAR_3 = 3;
+
+    /** Input method window. */
+    public static final int TYPE_IME = 4;
+    static final int LAST_TYPE = TYPE_IME;
+
+    // Derived types
+
+    /** First side bar is navigation bar. */
+    public static final int TYPE_NAVIGATION_BAR = TYPE_SIDE_BAR_1;
+
+    /** A shelf is the same as the navigation bar. */
+    public static final int TYPE_SHELF = TYPE_NAVIGATION_BAR;
+
+    private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
+
+    public InsetsState() {
+    }
+
+    /**
+     * Calculates {@link WindowInsets} based on the current source configuration.
+     *
+     * @param frame The frame to calculate the insets relative to.
+     * @return The calculated insets.
+     */
+    public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
+            boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+        Insets systemInsets = Insets.NONE;
+        Insets maxInsets = Insets.NONE;
+        final Rect relativeFrame = new Rect(frame);
+        final Rect relativeFrameMax = new Rect(frame);
+        for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
+            InsetsSource source = mSources.get(type);
+            if (source == null) {
+                continue;
+            }
+            systemInsets = processSource(source, systemInsets, relativeFrame,
+                    false /* ignoreVisibility */);
+
+            // IME won't be reported in max insets as the size depends on the EditorInfo of the IME
+            // target.
+            if (source.getType() != TYPE_IME) {
+                maxInsets = processSource(source, maxInsets, relativeFrameMax,
+                        true /* ignoreVisibility */);
+            }
+        }
+        return new WindowInsets(new Rect(systemInsets), null, new Rect(maxInsets), isScreenRound,
+                alwaysConsumeNavBar, cutout);
+    }
+
+    private Insets processSource(InsetsSource source, Insets insets, Rect relativeFrame,
+            boolean ignoreVisibility) {
+        Insets currentInsets = source.calculateInsets(relativeFrame, ignoreVisibility);
+        insets = Insets.add(currentInsets, insets);
+        relativeFrame.inset(insets);
+        return insets;
+    }
+
+    public InsetsSource getSource(@InternalInsetType int type) {
+        return mSources.computeIfAbsent(type, InsetsSource::new);
+    }
+
+    /**
+     * Modifies the state of this class to exclude a certain type to make it ready for dispatching
+     * to the client.
+     *
+     * @param type The {@link InternalInsetType} of the source to remove
+     */
+    public void removeSource(int type) {
+        mSources.remove(type);
+    }
+
+    public void set(InsetsState other) {
+        set(other, false /* copySources */);
+    }
+
+    public void set(InsetsState other, boolean copySources) {
+        mSources.clear();
+        if (copySources) {
+            for (int i = 0; i < other.mSources.size(); i++) {
+                InsetsSource source = other.mSources.valueAt(i);
+                mSources.put(source.getType(), new InsetsSource(source));
+            }
+        } else {
+            mSources.putAll(other.mSources);
+        }
+    }
+
+    public void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix + "InsetsState");
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            mSources.valueAt(i).dump(prefix + "  ", pw);
+        }
+    }
+
+    static String typeToString(int type) {
+        switch (type) {
+            case TYPE_TOP_BAR:
+                return "TYPE_TOP_BAR";
+            case TYPE_SIDE_BAR_1:
+                return "TYPE_SIDE_BAR_1";
+            case TYPE_SIDE_BAR_2:
+                return "TYPE_SIDE_BAR_2";
+            case TYPE_SIDE_BAR_3:
+                return "TYPE_SIDE_BAR_3";
+            case TYPE_IME:
+                return "TYPE_IME";
+            default:
+                return "TYPE_UNKNOWN";
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) { return true; }
+        if (o == null || getClass() != o.getClass()) { return false; }
+
+        InsetsState state = (InsetsState) o;
+
+        if (mSources.size() != state.mSources.size()) {
+            return false;
+        }
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            InsetsSource source = mSources.valueAt(i);
+            InsetsSource otherSource = state.mSources.get(source.getType());
+            if (otherSource == null) {
+                return false;
+            }
+            if (!otherSource.equals(source)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return mSources.hashCode();
+    }
+
+    public InsetsState(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSources.size());
+        for (int i = 0; i < mSources.size(); i++) {
+            dest.writeParcelable(mSources.valueAt(i), 0 /* flags */);
+        }
+    }
+
+    public static final Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
+
+        public InsetsState createFromParcel(Parcel in) {
+            return new InsetsState(in);
+        }
+
+        public InsetsState[] newArray(int size) {
+            return new InsetsState[size];
+        }
+    };
+
+    public void readFromParcel(Parcel in) {
+        mSources.clear();
+        final int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            final InsetsSource source = in.readParcelable(null /* loader */);
+            mSources.put(source.getType(), source);
+        }
+    }
+}
+
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8e9f2d7..d9d52c0 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -161,6 +161,19 @@
     private static final boolean MT_RENDERER_AVAILABLE = true;
 
     /**
+     * If set to true, the view system will switch from using rectangles retrieved from window to
+     * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets
+     * directly from the full configuration, enabling richer information about the insets state, as
+     * well as new APIs to control it frame-by-frame, and synchronize animations with it.
+     * <p>
+     * Only switch this to true once the new insets system is productionized and the old APIs are
+     * fully migrated over.
+     */
+    private static final String USE_NEW_INSETS_PROPERTY = "persist.wm.new_insets";
+    private static final boolean USE_NEW_INSETS =
+            SystemProperties.getBoolean(USE_NEW_INSETS_PROPERTY, false);
+
+    /**
      * Set this system property to true to force the view hierarchy to render
      * at 60 Hz. This can be used to measure the potential framerate.
      */
@@ -432,6 +445,8 @@
     boolean mAdded;
     boolean mAddedTouchMode;
 
+    final Rect mTmpFrame = new Rect();
+
     // These are accessed by multiple threads.
     final Rect mWinFrame; // frame given by window manager.
 
@@ -444,6 +459,7 @@
     final DisplayCutout.ParcelableWrapper mPendingDisplayCutout =
             new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
     boolean mPendingAlwaysConsumeNavBar;
+    private InsetsState mPendingInsets;
     final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
             = new ViewTreeObserver.InternalInsetsInfo();
 
@@ -531,6 +547,8 @@
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                     new InputEventConsistencyVerifier(this, 0) : null;
 
+    private final InsetsController mInsetsController = new InsetsController();
+
     static final class SystemUiVisibilityInfo {
         int seq;
         int globalVisibility;
@@ -797,9 +815,11 @@
                     mAttachInfo.mRecomputeGlobalAttributes = true;
                     collectViewAttributes();
                     res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
-                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
+                            getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
                             mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
-                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
+                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
+                            mInsetsController.getState());
+                    setFrame(mTmpFrame);
                 } catch (RemoteException e) {
                     mAdded = false;
                     mView = null;
@@ -826,6 +846,7 @@
                 mAttachInfo.mAlwaysConsumeNavBar =
                         (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
                 mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
+                mPendingInsets = mInsetsController.getState();
                 if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
                 if (res < WindowManagerGlobal.ADD_OKAY) {
                     mAttachInfo.mRootView = null;
@@ -1771,7 +1792,8 @@
             Rect stableInsets = mDispatchStableInsets;
             DisplayCutout displayCutout = mDispatchDisplayCutout;
             // For dispatch we preserve old logic, but for direct requests from Views we allow to
-            // immediately use pending insets.
+            // immediately use pending insets. This is such that getRootWindowInsets returns the
+            // result from the layout hint before we ran a traversal shortly after adding a window.
             if (!forceConstruct
                     && (!mPendingContentInsets.equals(contentInsets) ||
                         !mPendingStableInsets.equals(stableInsets) ||
@@ -1788,10 +1810,16 @@
             }
             contentInsets = ensureInsetsNonNegative(contentInsets, "content");
             stableInsets = ensureInsetsNonNegative(stableInsets, "stable");
-            mLastWindowInsets = new WindowInsets(contentInsets,
-                    null /* windowDecorInsets */, stableInsets,
-                    mContext.getResources().getConfiguration().isScreenRound(),
-                    mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+            if (USE_NEW_INSETS) {
+                mLastWindowInsets = mInsetsController.calculateInsets(
+                        mContext.getResources().getConfiguration().isScreenRound(),
+                        mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+            } else {
+                mLastWindowInsets = new WindowInsets(contentInsets,
+                        null /* windowDecorInsets */, stableInsets,
+                        mContext.getResources().getConfiguration().isScreenRound(),
+                        mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+            }
         }
         return mLastWindowInsets;
     }
@@ -1991,6 +2019,9 @@
                 if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
                     insetsChanged = true;
                 }
+                if (!mPendingInsets.equals(mInsetsController.getState())) {
+                    insetsChanged = true;
+                }
                 if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
                         || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                     windowSizeMayChange = true;
@@ -2184,6 +2215,8 @@
                         mAttachInfo.mStableInsets);
                 final boolean cutoutChanged = !mPendingDisplayCutout.equals(
                         mAttachInfo.mDisplayCutout);
+                final boolean insetsStateChanged = !mPendingInsets.equals(
+                        mInsetsController.getState());
                 final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
                 final boolean surfaceSizeChanged = (relayoutResult
                         & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
@@ -2221,6 +2254,10 @@
                     mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar;
                     contentInsetsChanged = true;
                 }
+                if (insetsStateChanged) {
+                    mInsetsController.setState(mPendingInsets);
+                    contentInsetsChanged = true;
+                }
                 if (contentInsetsChanged || mLastSystemUiVisibility !=
                         mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
                         || mLastOverscanRequested != mAttachInfo.mOverscanRequested
@@ -2666,7 +2703,6 @@
     }
 
     private void maybeHandleWindowMove(Rect frame) {
-
         // TODO: Well, we are checking whether the frame has changed similarly
         // to how this is done for the insets. This is however incorrect since
         // the insets and the frame are translated. For example, the old frame
@@ -4171,6 +4207,7 @@
     private final static int MSG_UPDATE_POINTER_ICON = 27;
     private final static int MSG_POINTER_CAPTURE_CHANGED = 28;
     private final static int MSG_DRAW_FINISHED = 29;
+    private final static int MSG_INSETS_CHANGED = 30;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -4226,6 +4263,8 @@
                     return "MSG_POINTER_CAPTURE_CHANGED";
                 case MSG_DRAW_FINISHED:
                     return "MSG_DRAW_FINISHED";
+                case MSG_INSETS_CHANGED:
+                    return "MSG_INSETS_CHANGED";
             }
             return super.getMessageName(message);
         }
@@ -4306,7 +4345,7 @@
                                 || !mPendingVisibleInsets.equals(args.arg3)
                                 || !mPendingOutsets.equals(args.arg7);
 
-                        mWinFrame.set((Rect) args.arg1);
+                        setFrame((Rect) args.arg1);
                         mPendingOverscanInsets.set((Rect) args.arg5);
                         mPendingContentInsets.set((Rect) args.arg2);
                         mPendingStableInsets.set((Rect) args.arg6);
@@ -4329,16 +4368,25 @@
                         requestLayout();
                     }
                     break;
+                case MSG_INSETS_CHANGED:
+                    mPendingInsets = (InsetsState) msg.obj;
+
+                    // TODO: Full traversal not needed here
+                    if (USE_NEW_INSETS) {
+                        requestLayout();
+                    }
+                    break;
                 case MSG_WINDOW_MOVED:
                     if (mAdded) {
                         final int w = mWinFrame.width();
                         final int h = mWinFrame.height();
                         final int l = msg.arg1;
                         final int t = msg.arg2;
-                        mWinFrame.left = l;
-                        mWinFrame.right = l + w;
-                        mWinFrame.top = t;
-                        mWinFrame.bottom = t + h;
+                        mTmpFrame.left = l;
+                        mTmpFrame.right = l + w;
+                        mTmpFrame.top = t;
+                        mTmpFrame.bottom = t + h;
+                        setFrame(mTmpFrame);
 
                         mPendingBackDropFrame.set(mWinFrame);
                         maybeHandleWindowMove(mWinFrame);
@@ -6724,9 +6772,9 @@
                 (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                 (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
                 insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
-                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
+                mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                 mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
-                mPendingMergedConfiguration, mSurface);
+                mPendingMergedConfiguration, mSurface, mPendingInsets);
 
         mPendingAlwaysConsumeNavBar =
                 (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
@@ -6736,15 +6784,22 @@
         }
 
         if (mTranslator != null) {
-            mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
+            mTranslator.translateRectInScreenToAppWinFrame(mTmpFrame);
             mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
             mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
             mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
             mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
         }
+        setFrame(mTmpFrame);
+
         return relayoutResult;
     }
 
+    private void setFrame(Rect frame) {
+        mWinFrame.set(frame);
+        mInsetsController.onFrameChanged(frame);
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -6847,6 +6902,8 @@
 
         mChoreographer.dump(prefix, writer);
 
+        mInsetsController.dump(prefix, writer);
+
         writer.print(prefix); writer.println("View Hierarchy:");
         dumpViewHierarchy(innerPrefix, writer, mView);
     }
@@ -7055,6 +7112,10 @@
         mHandler.sendMessage(msg);
     }
 
+    private void dispatchInsetsChanged(InsetsState insetsState) {
+        mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget();
+    }
+
     public void dispatchMoved(int newX, int newY) {
         if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
         if (mTranslator != null) {
@@ -8118,6 +8179,14 @@
         }
 
         @Override
+        public void insetsChanged(InsetsState insetsState) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.dispatchInsetsChanged(insetsState);
+            }
+        }
+
+        @Override
         public void moved(int newX, int newY) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index b9d53c1..d78bfac 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -120,6 +120,8 @@
         arg5 = null;
         arg6 = null;
         arg7 = null;
+        arg8 = null;
+        arg9 = null;
         argi1 = 0;
         argi2 = 0;
         argi3 = 0;
diff --git a/core/java/com/android/internal/util/function/NonaConsumer.java b/core/java/com/android/internal/util/function/NonaConsumer.java
new file mode 100644
index 0000000..3e7ce2b
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 9-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface NonaConsumer<A, B, C, D, E, F, G, H, I> {
+    void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/NonaFunction.java b/core/java/com/android/internal/util/function/NonaFunction.java
new file mode 100644
index 0000000..560b4f1
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Function;
+
+/**
+ * A 9-argument {@link Function}
+ *
+ * @hide
+ */
+public interface NonaFunction<A, B, C, D, E, F, G, H, I, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/NonaPredicate.java b/core/java/com/android/internal/util/function/NonaPredicate.java
new file mode 100644
index 0000000..c1e6f37
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 9-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface NonaPredicate<A, B, C, D, E, F, G, H, I> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/OctConsumer.java b/core/java/com/android/internal/util/function/OctConsumer.java
new file mode 100644
index 0000000..83ee305
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 8-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface OctConsumer<A, B, C, D, E, F, G, H> {
+    void accept(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/OctFunction.java b/core/java/com/android/internal/util/function/OctFunction.java
new file mode 100644
index 0000000..cb16624
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Function;
+
+/**
+ * A 8-argument {@link Function}
+ *
+ * @hide
+ */
+public interface OctFunction<A, B, C, D, E, F, G, H, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/OctPredicate.java b/core/java/com/android/internal/util/function/OctPredicate.java
new file mode 100644
index 0000000..7f36d6a
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 8-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface OctPredicate<A, B, C, D, E, F, G, H> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index 4ffe441..d74e715 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -22,6 +22,10 @@
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
 import com.android.internal.util.function.QuadConsumer;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.QuintConsumer;
@@ -39,61 +43,62 @@
  *
  * @hide
  */
-abstract class OmniFunction<A, B, C, D, E, F, G, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, G, H, I, R> implements
         PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
         QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
         HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>,
+        OctFunction<A, B, C, D, E, F, G, H, R>, NonaFunction<A, B, C, D, E, F, G, H, I, R>,
         PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
         QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>,
-        HeptConsumer<A, B, C, D, E, F, G>,
-        PooledPredicate<A>, BiPredicate<A, B>,
+        HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>,
+        NonaConsumer<A, B, C, D, E, F, G, H, I>, PooledPredicate<A>, BiPredicate<A, B>,
         PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
         PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
 
-    abstract R invoke(A a, B b, C c, D d, E e, F f, G g);
+    abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i);
 
     @Override
     public R apply(A o, B o2) {
-        return invoke(o, o2, null, null, null, null, null);
+        return invoke(o, o2, null, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A o) {
-        return invoke(o, null, null, null, null, null, null);
+        return invoke(o, null, null, null, null, null, null, null, null);
     }
 
-    public abstract <V> OmniFunction<A, B, C, D, E, F, G, V> andThen(
+    public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, V> andThen(
             Function<? super R, ? extends V> after);
-    public abstract OmniFunction<A, B, C, D, E, F, G, R> negate();
+    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> negate();
 
     @Override
     public void accept(A o, B o2) {
-        invoke(o, o2, null, null, null, null, null);
+        invoke(o, o2, null, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A o) {
-        invoke(o, null, null, null, null, null, null);
+        invoke(o, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public void run() {
-        invoke(null, null, null, null, null, null, null);
+        invoke(null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public R get() {
-        return invoke(null, null, null, null, null, null, null);
+        return invoke(null, null, null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o, B o2) {
-        return (Boolean) invoke(o, o2, null, null, null, null, null);
+        return (Boolean) invoke(o, o2, null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o) {
-        return (Boolean) invoke(o, null, null, null, null, null, null);
+        return (Boolean) invoke(o, null, null, null, null, null, null, null, null);
     }
 
     @Override
@@ -108,52 +113,72 @@
 
     @Override
     public R apply(A a, B b, C c) {
-        return invoke(a, b, c, null, null, null, null);
+        return invoke(a, b, c, null, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c) {
-        invoke(a, b, c, null, null, null, null);
+        invoke(a, b, c, null, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d) {
-        return invoke(a, b, c, d, null, null, null);
+        return invoke(a, b, c, d, null, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e) {
-        return invoke(a, b, c, d, e, null, null);
+        return invoke(a, b, c, d, e, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f) {
-        return invoke(a, b, c, d, e, f, null);
+        return invoke(a, b, c, d, e, f, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f, G g) {
-        return invoke(a, b, c, d, e, f, g);
+        return invoke(a, b, c, d, e, f, g, null, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g, H h) {
+        return invoke(a, b, c, d, e, f, g, h, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
+        return invoke(a, b, c, d, e, f, g, h, i);
     }
 
     @Override
     public void accept(A a, B b, C c, D d) {
-        invoke(a, b, c, d, null, null, null);
+        invoke(a, b, c, d, null, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e) {
-        invoke(a, b, c, d, e, null, null);
+        invoke(a, b, c, d, e, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f) {
-        invoke(a, b, c, d, e, f, null);
+        invoke(a, b, c, d, e, f, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f, G g) {
-        invoke(a, b, c, d, e, f, g);
+        invoke(a, b, c, d, e, f, g, null, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g, H h) {
+        invoke(a, b, c, d, e, f, g, h, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
+        invoke(a, b, c, d, e, f, g, h, i);
     }
 
     @Override
@@ -167,5 +192,5 @@
     }
 
     @Override
-    public abstract OmniFunction<A, B, C, D, E, F, G, R> recycleOnUse();
+    public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> recycleOnUse();
 }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index af3c752..c00932e 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -25,6 +25,10 @@
 import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
 import com.android.internal.util.function.QuadConsumer;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.QuintConsumer;
@@ -176,7 +180,8 @@
             Consumer<? super A> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
+                function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -192,7 +197,8 @@
             Predicate<? super A> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null);
+                function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -208,7 +214,8 @@
             Function<? super A, ? extends R> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null);
+                function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -238,7 +245,8 @@
             A arg1) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
+                    function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
+                    null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -257,7 +265,8 @@
             BiConsumer<? super A, ? super B> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+                function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -274,7 +283,8 @@
             BiPredicate<? super A, ? super B> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+                function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -291,7 +301,8 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+                function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -308,7 +319,8 @@
             BiConsumer<? super A, ? super B> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -325,7 +337,8 @@
             BiPredicate<? super A, ? super B> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -342,7 +355,8 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -359,7 +373,8 @@
             BiConsumer<? super A, ? super B> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -376,7 +391,8 @@
             BiPredicate<? super A, ? super B> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -393,7 +409,8 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -424,7 +441,8 @@
             A arg1, B arg2) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+                    function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+                    null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -444,7 +462,8 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -462,7 +481,8 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -480,7 +500,8 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -498,7 +519,8 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -516,7 +538,8 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -534,7 +557,8 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -552,7 +576,8 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -570,7 +595,8 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+                null);
     }
 
     /**
@@ -602,7 +628,8 @@
             A arg1, B arg2, C arg3) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+                    function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+                    null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -623,7 +650,8 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -642,7 +670,8 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -661,7 +690,8 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -680,7 +710,8 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -699,7 +730,8 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -718,7 +750,8 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -737,7 +770,8 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -756,7 +790,8 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -775,7 +810,8 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -794,7 +830,8 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+                null);
     }
 
     /**
@@ -827,7 +864,8 @@
             A arg1, B arg2, C arg3, D arg4) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+                    function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+                    null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -849,7 +887,8 @@
             QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
             A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
+                function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
+                null);
     }
 
     /**
@@ -869,7 +908,8 @@
             QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R>
                     function, A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null);
+                function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null,
+                null);
     }
 
     /**
@@ -904,7 +944,8 @@
             A arg1, B arg2, C arg3, D arg4, E arg5) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
+                    function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
+                    null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -927,7 +968,8 @@
             HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+                function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+                null);
     }
 
     /**
@@ -948,7 +990,8 @@
             HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
                     ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null);
+                function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+                null);
     }
 
     /**
@@ -984,7 +1027,8 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+                    function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+                    null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -1008,7 +1052,8 @@
             HeptConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
                     ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+                function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+                null);
     }
 
     /**
@@ -1031,7 +1076,8 @@
                     ? super G, ? extends R> function,
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+                function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+                null);
     }
 
     /**
@@ -1068,7 +1114,195 @@
                     ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+                    function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+                    null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) }
+     */
+    static <A, B, C, D, E, F, G, H> PooledRunnable obtainRunnable(
+            OctConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, ? super G,
+                    ? super H> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7,
+            H arg8) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                null);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) }
+     */
+    static <A, B, C, D, E, F, G, H, R> PooledSupplier<R> obtainSupplier(
+            OctFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                                ? super G, ? super H, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                null);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7, arg8) } when handled
+     */
+    static <A, B, C, D, E, F, G, H> Message obtainMessage(
+            OctConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, ? super G,
+                    ? super H> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7,
+            H arg8) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                    null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) }
+     */
+    static <A, B, C, D, E, F, G, H, I> PooledRunnable obtainRunnable(
+            NonaConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I> function, A arg1, B arg2, C arg3, D arg4,
+            E arg5, F arg6, G arg7, H arg8, I arg9) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) }
+     */
+    static <A, B, C, D, E, F, G, H, I, R> PooledSupplier<R> obtainSupplier(
+            NonaFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                                ? super G, ? super H, ? super I, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @param arg8 parameter supplied to {@code function} on call
+     * @param arg9 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7, arg8, arg9) } when handled
+     */
+    static <A, B, C, D, E, F, G, H, I> Message obtainMessage(
+            NonaConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? super H, ? super I> function, A arg1, B arg2, C arg3, D arg4,
+            E arg5, F arg6, G arg7, H arg8, I arg9) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                    arg9);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index eea1e5f..6be626a 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -30,6 +30,12 @@
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
 import com.android.internal.util.function.HexPredicate;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.NonaPredicate;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
+import com.android.internal.util.function.OctPredicate;
 import com.android.internal.util.function.QuadConsumer;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.QuadPredicate;
@@ -54,12 +60,12 @@
  * @hide
  */
 final class PooledLambdaImpl<R> extends OmniFunction<Object,
-        Object, Object, Object, Object, Object, Object, R> {
+        Object, Object, Object, Object, Object, Object, Object, Object, R> {
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "PooledLambdaImpl";
 
-    private static final int MAX_ARGS = 7;
+    private static final int MAX_ARGS = 9;
 
     private static final int MAX_POOL_SIZE = 50;
 
@@ -125,7 +131,7 @@
 
     /**
      * Bit schema:
-     * AAAAAAABCDEEEEEEFFFFFF
+     * AAAAAAAAABCDEEEEEEFFFFFF
      *
      * Where:
      * A - whether {@link #mArgs arg} at corresponding index was specified at
@@ -161,17 +167,19 @@
     }
 
     @Override
-    R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
+    R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7,
+            Object a8, Object a9) {
         checkNotRecycled();
         if (DEBUG) {
             Log.i(LOG_TAG, this + ".invoke("
                     + commaSeparateFirstN(
-                            new Object[] { a1, a2, a3, a4, a5, a6, a7 },
+                            new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9 },
                             LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
                     + ")");
         }
-        final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3)
-                && fillInArg(a4) && fillInArg(a5) && fillInArg(a6) && fillInArg(a7);
+        final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4)
+                && fillInArg(a5) && fillInArg(a6) && fillInArg(a7) && fillInArg(a8)
+                && fillInArg(a9);
         int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
         if (argCount != LambdaType.MASK_ARG_COUNT) {
             for (int i = 0; i < argCount; i++) {
@@ -335,7 +343,7 @@
                                 popArg(2), popArg(3), popArg(4), popArg(5));
                     }
                 }
-            }
+            } break;
 
             case 7: {
                 switch (returnType) {
@@ -356,7 +364,49 @@
                                 popArg(5), popArg(6));
                     }
                 }
-            }
+            } break;
+
+            case 8: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((OctConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((OctPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3),
+                                popArg(4), popArg(5), popArg(6), popArg(7));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((OctFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7));
+                    }
+                }
+            } break;
+
+            case 9: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((NonaConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((NonaPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6), popArg(7), popArg(8));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((NonaFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5),
+                                popArg(6), popArg(7), popArg(8));
+                    }
+                }
+            } break;
         }
         throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
     }
@@ -419,8 +469,8 @@
      * Internal non-typesafe factory method for {@link PooledLambdaImpl}
      */
     static <E extends PooledLambda> E acquire(Pool pool, Object func,
-            int fNumArgs, int numPlaceholders, int fReturnType,
-            Object a, Object b, Object c, Object d, Object e, Object f, Object g) {
+            int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
+            Object d, Object e, Object f, Object g, Object h, Object i) {
         PooledLambdaImpl r = acquire(pool);
         if (DEBUG) {
             Log.i(LOG_TAG,
@@ -436,6 +486,8 @@
                             + ", e = " + e
                             + ", f = " + f
                             + ", g = " + g
+                            + ", h = " + h
+                            + ", i = " + i
                             + ")");
         }
         r.mFunc = func;
@@ -449,6 +501,8 @@
         setIfInBounds(r.mArgs, 4, e);
         setIfInBounds(r.mArgs, 5, f);
         setIfInBounds(r.mArgs, 6, g);
+        setIfInBounds(r.mArgs, 7, h);
+        setIfInBounds(r.mArgs, 8, i);
         return (E) r;
     }
 
@@ -474,13 +528,14 @@
     }
 
     @Override
-    public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> negate() {
+    public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+            R> negate() {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, V> andThen(
-            Function<? super R, ? extends V> after) {
+    public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+            V> andThen(Function<? super R, ? extends V> after) {
         throw new UnsupportedOperationException();
     }
 
@@ -500,7 +555,8 @@
     }
 
     @Override
-    public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> recycleOnUse() {
+    public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+            R> recycleOnUse() {
         if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
         mFlags |= FLAG_RECYCLE_ON_USE;
         return this;
@@ -584,6 +640,8 @@
                 case 5: return "Quint";
                 case 6: return "Hex";
                 case 7: return "Hept";
+                case 8: return "Oct";
+                case 9: return "Nona";
                 default: throw new IllegalArgumentException("" + argCount);
             }
         }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 137ca7f..36fe4fc 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -27,6 +27,7 @@
 import android.view.IWindow;
 import android.view.IWindowSession;
 import android.view.PointerIcon;
+import android.view.InsetsState;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -53,6 +54,10 @@
     }
 
     @Override
+    public void insetsChanged(InsetsState insetsState) {
+    }
+
+    @Override
     public void moved(int newX, int newY) {
     }
 
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index e89b593..752624b 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -468,6 +468,10 @@
     return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getAllowForceDark();
 }
 
+static jlong android_view_RenderNode_getUniqueId(jlong renderNodePtr) {
+    return reinterpret_cast<RenderNode*>(renderNodePtr)->uniqueId();
+}
+
 // ----------------------------------------------------------------------------
 // RenderProperties - Animations
 // ----------------------------------------------------------------------------
@@ -694,6 +698,7 @@
     { "nGetHeight",                "(J)I",  (void*) android_view_RenderNode_getHeight },
     { "nSetAllowForceDark",        "(JZ)Z", (void*) android_view_RenderNode_setAllowForceDark },
     { "nGetAllowForceDark",        "(J)Z",  (void*) android_view_RenderNode_getAllowForceDark },
+    { "nGetUniqueId",              "(J)J",  (void*) android_view_RenderNode_getUniqueId },
 };
 
 int register_android_view_RenderNode(JNIEnv* env) {
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 18d1d5d..d5eaa00 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1601,6 +1601,10 @@
         <attr name="request" />
         <attr name="protectionLevel" />
         <attr name="permissionFlags" />
+        <!-- If {@code true} applications that target Q <em>must</em> specify the permission usage
+             attributes in their {@code uses-permission} elements or the permission will not be
+             granted. -->
+        <attr name="usageInfoRequired" format="boolean" />
     </declare-styleable>
 
     <!-- The <code>permission-group</code> tag declares a logical grouping of
@@ -1700,6 +1704,81 @@
         requested.  If it does support the feature, it will be as if the manifest didn't
         request it at all. -->
         <attr name="requiredNotFeature" format="string" />
+
+        <!-- Specify if the app uploads data, or derived data, guarded by this permission.
+
+             If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+             {@code true} this <em>must</em> be specified by apps that target Android Q or the
+             permission will not be granted, it will be as if the manifest didn't request it at all.
+        -->
+        <attr name="dataSentOffDevice">
+          <!-- The application may send data, or derived data, guarded by this permission off of the
+               device. -->
+          <enum name="yes" value="1" />
+          <!-- The application may send data, or derived data, guarded by this permission off of the
+               device, however it will only do so when explicitly triggered by a user action. -->
+          <enum name="userTriggered" value="2" />
+          <!-- The application does not send data, or derived data, guarded by this permission off
+               of the device. -->
+          <enum name="no" value="3" />
+        </attr>
+
+        <!-- Specify if the application or its related off-device services provide data,
+             or derived data, guarded by this permission to third parties outside of the developer's
+             organization that do not qualify as data processors.
+
+             If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+             {@code true} this <em>must</em> be specified by apps that target Android Q or the
+             permission will not be granted, it will be as if the manifest didn't request it at all.
+             -->
+        <attr name="dataSharedWithThirdParty">
+          <!-- The application or its services may provide data, or derived data, guarded by this
+               permission to third party organizations. -->
+          <enum name="yes" value="1" />
+          <!-- The application or its services may provide data, or derived data, guarded by this
+               permission to third party organizations, however it will only do so when explicitly
+               triggered by a user action. -->
+          <enum name="userTriggered" value="2" />
+          <!-- The application or its services does not provide data, or derived data, guarded by
+               this permission to third party organizations. -->
+          <enum name="no" value="3" />
+        </attr>
+
+        <!-- Specify if the application or its related off-device services use data,
+             or derived data, guarded by this permission for monetization purposes.
+
+             For example, if the data is sold to another party or used for targeting advertisements
+             this must be set to {@code yes}.
+
+             If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+             {@code true} this <em>must</em> be specified by apps that target Android Q or the
+             permission will not be granted, it will be as if the manifest didn't request it at all.
+             -->
+        <attr name="dataUsedForMonetization">
+          <!-- The application or its services may use data, or derived data, guarded by this
+               permission for monetization purposes. -->
+          <enum name="yes" value="1" />
+          <!-- The application or its services may use data, or derived data, guarded by this
+               permission for monetization purposes, however it will only do so when explicity
+               triggered by a user action. -->
+          <enum name="userTriggered" value="2" />
+          <!--  The application or its services does not use data, or derived data, guarded by
+                this permission for monetization purposes. -->
+          <enum name="no" value="3" />
+        </attr>
+
+        <!-- Specify how long the application or its related off-device services store
+             data, or derived data, guarded by this permission.
+
+             This can be one of "notRetained", "userSelected", "unlimited", or a number
+             representing the number of weeks the data is retained.
+
+             If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+             {@code true} this <em>must</em> be specified by apps that target Android Q or the
+             permission will not be granted, it will be as if the manifest didn't request it at all.
+             -->
+        <attr name="dataRetentionTime" format="string" />
+
     </declare-styleable>
 
     <!-- The <code>uses-configuration</code> tag specifies
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 73e0f85..feefcad 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2923,6 +2923,11 @@
         <public name="importantForContentCapture" />
         <public name="supportsMultipleDisplays" />
         <public name="useAppZygote" />
+        <public name="usageInfoRequired" />
+        <public name="dataSentOffDevice" />
+        <public name="dataSharedWithThirdParty" />
+        <public name="dataUsedForMonetization" />
+        <public name="dataRetentionTime" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b4">
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
new file mode 100644
index 0000000..ed472d2
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static junit.framework.Assert.assertEquals;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsSourceTest {
+
+    private InsetsSource mSource = new InsetsSource(TYPE_NAVIGATION_BAR);
+
+    @Before
+    public void setUp() {
+        mSource.setVisible(true);
+    }
+
+    @Test
+    public void testCalculateInsetsTop() {
+        mSource.setFrame(new Rect(0, 0, 500, 100));
+        Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+                false /* ignoreVisibility */);
+        assertEquals(Insets.of(0, 100, 0, 0), insets);
+    }
+
+    @Test
+    public void testCalculateInsetsBottom() {
+        mSource.setFrame(new Rect(0, 400, 500, 500));
+        Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+                false /* ignoreVisibility */);
+        assertEquals(Insets.of(0, 0, 0, 100), insets);
+    }
+
+    @Test
+    public void testCalculateInsetsLeft() {
+        mSource.setFrame(new Rect(0, 0, 100, 500));
+        Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+                false /* ignoreVisibility */);
+        assertEquals(Insets.of(100, 0, 0, 0), insets);
+    }
+
+    @Test
+    public void testCalculateInsetsRight() {
+        mSource.setFrame(new Rect(400, 0, 500, 500));
+        Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+                false /* ignoreVisibility */);
+        assertEquals(Insets.of(0, 0, 100, 0), insets);
+    }
+
+    @Test
+    public void testCalculateInsets_overextend() {
+        mSource.setFrame(new Rect(0, 0, 500, 100));
+        Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+                false /* ignoreVisibility */);
+        assertEquals(Insets.of(0, 100, 0, 0), insets);
+    }
+
+    @Test
+    public void testCalculateInsets_invisible() {
+        mSource.setFrame(new Rect(0, 0, 500, 100));
+        mSource.setVisible(false);
+        Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+                false /* ignoreVisibility */);
+        assertEquals(Insets.of(0, 0, 0, 0), insets);
+    }
+
+    @Test
+    public void testCalculateInsets_ignoreVisibility() {
+        mSource.setFrame(new Rect(0, 0, 500, 100));
+        mSource.setVisible(false);
+        Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+                true /* ignoreVisibility */);
+        assertEquals(Insets.of(0, 100, 0, 0), insets);
+    }
+
+    // Parcel and equals already tested via InsetsStateTest
+}
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
new file mode 100644
index 0000000..6bb9539
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsStateTest {
+
+    private InsetsState mState = new InsetsState();
+    private InsetsState mState2 = new InsetsState();
+
+    @Test
+    public void testCalculateInsets() {
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getSource(TYPE_TOP_BAR).setVisible(true);
+        mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+        mState.getSource(TYPE_IME).setVisible(true);
+        WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                DisplayCutout.NO_CUTOUT);
+        assertEquals(new Rect(0, 100, 0, 100), insets.getSystemWindowInsets());
+    }
+
+    @Test
+    public void testCalculateInsets_imeAndNav() {
+        mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+        mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+        mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+        mState.getSource(TYPE_IME).setVisible(true);
+        WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                DisplayCutout.NO_CUTOUT);
+        assertEquals(100, insets.getStableInsetBottom());
+        assertEquals(new Rect(0, 0, 0, 200), insets.getSystemWindowInsets());
+    }
+
+    @Test
+    public void testCalculateInsets_navRightStatusTop() {
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getSource(TYPE_TOP_BAR).setVisible(true);
+        mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+        mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+        WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                DisplayCutout.NO_CUTOUT);
+        assertEquals(new Rect(0, 100, 20, 0), insets.getSystemWindowInsets());
+    }
+
+    @Test
+    public void testStripForDispatch() {
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getSource(TYPE_TOP_BAR).setVisible(true);
+        mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+        mState.getSource(TYPE_IME).setVisible(true);
+        mState.removeSource(TYPE_IME);
+        WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                DisplayCutout.NO_CUTOUT);
+        assertEquals(0, insets.getSystemWindowInsetBottom());
+    }
+
+    @Test
+    public void testEquals_differentRect() {
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 10, 10));
+        assertNotEquals(mState, mState2);
+    }
+
+    @Test
+    public void testEquals_differentSource() {
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        assertNotEquals(mState, mState2);
+    }
+
+    @Test
+    public void testEquals_sameButDifferentInsertOrder() {
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        assertEquals(mState, mState2);
+    }
+
+    @Test
+    public void testEquals_visibility() {
+        mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        mState.getSource(TYPE_IME).setVisible(true);
+        mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        assertNotEquals(mState, mState2);
+    }
+
+    @Test
+    public void testParcelUnparcel() {
+        mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        mState.getSource(TYPE_IME).setVisible(true);
+        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+        Parcel p = Parcel.obtain();
+        mState.writeToParcel(p, 0 /* flags */);
+        mState2.readFromParcel(p);
+        p.recycle();
+        assertEquals(mState, mState2);
+    }
+}
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index de110c8..d9da27c 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -82,6 +82,17 @@
     }
 
     /**
+     * Add two Insets.
+     *
+     * @param a The first Insets to add.
+     * @param b The second Insets to add.
+     * @return a + b, i. e. all insets on every side are added together.
+     */
+    public static @NonNull Insets add(@NonNull Insets a, @NonNull Insets b) {
+        return Insets.of(a.left + b.left, a.top + b.top, a.right + b.right, a.bottom + b.bottom);
+    }
+
+    /**
      * Two Insets instances are equal iff they belong to the same class and their fields are
      * pairwise equal.
      *
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index c4dc0ad..40a32f3 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -106,6 +106,20 @@
     }
 
     /**
+     * @hide
+     */
+    public Rect(@Nullable Insets r) {
+        if (r == null) {
+            left = top = right = bottom = 0;
+        } else {
+            left = r.left;
+            top = r.top;
+            right = r.right;
+            bottom = r.bottom;
+        }
+    }
+
+    /**
      * Returns a copy of {@code r} if {@code r} is not {@code null}, or {@code null} otherwise.
      *
      * @hide
@@ -418,6 +432,18 @@
     }
 
     /**
+     * Insets the rectangle on all sides specified by the dimensions of {@code insets}.
+     * @hide
+     * @param insets The insets to inset the rect by.
+     */
+    public void inset(Insets insets) {
+        left += insets.left;
+        top += insets.top;
+        right -= insets.right;
+        bottom -= insets.bottom;
+    }
+
+    /**
      * Insets the rectangle on all sides specified by the insets.
      * @hide
      * @param left The amount to add from the rectangle's left
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 45d7a21..d6f08b9 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -1173,6 +1173,22 @@
         return nGetAllowForceDark(mNativeRenderNode);
     }
 
+    /**
+     * Returns the unique ID that identifies this RenderNode. This ID is unique for the
+     * lifetime of the process. IDs are reset on process death, and are unique only within
+     * the process.
+     *
+     * This ID is intended to be used with debugging tools to associate a particular
+     * RenderNode across different debug dumping & inspection tools. For example
+     * a View layout inspector should include the unique ID for any RenderNodes that it owns
+     * to associate the drawing content with the layout content.
+     *
+     * @return the unique ID for this RenderNode
+     */
+    public long getUniqueId() {
+        return nGetUniqueId(mNativeRenderNode);
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Animations
     ///////////////////////////////////////////////////////////////////////////
@@ -1479,4 +1495,7 @@
 
     @CriticalNative
     private static native boolean nGetAllowForceDark(long renderNode);
+
+    @CriticalNative
+    private static native long nGetUniqueId(long renderNode);
 }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index caf610b..5bd59d4 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -713,11 +713,12 @@
     }
 
     /**
-     * Whether this drawable requests projection.
+     * Whether this drawable requests projection. Indicates that the
+     * {@link android.graphics.RenderNode} this Drawable will draw into should be drawn immediately
+     * after the closest ancestor RenderNode containing a projection receiver.
      *
-     * @hide magic!
+     * @see android.graphics.RenderNode#setProjectBackwards(boolean)
      */
-    @UnsupportedAppUsage
     public boolean isProjected() {
         return false;
     }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d2a8f02..4a63910 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -29,6 +29,7 @@
 
 #include <SkPathOps.h>
 #include <algorithm>
+#include <atomic>
 #include <sstream>
 #include <string>
 
@@ -47,8 +48,14 @@
     TreeInfo* mTreeInfo;
 };
 
+static int64_t generateId() {
+    static std::atomic<int64_t> sNextId{1};
+    return sNextId++;
+}
+
 RenderNode::RenderNode()
-        : mDirtyPropertyFields(0)
+        : mUniqueId(generateId())
+        , mDirtyPropertyFields(0)
         , mNeedsDisplayListSync(false)
         , mDisplayList(nullptr)
         , mStagingDisplayList(nullptr)
@@ -444,5 +451,38 @@
     return &mClippedOutlineCache.clippedOutline;
 }
 
+using StringBuffer = FatVector<char, 128>;
+
+template <typename... T>
+static void format(StringBuffer& buffer, const std::string_view& format, T... args) {
+    buffer.resize(buffer.capacity());
+    while (1) {
+        int needed = snprintf(buffer.data(), buffer.size(),
+                format.data(), std::forward<T>(args)...);
+        if (needed < 0) {
+            buffer[0] = '\0';
+            buffer.resize(1);
+            return;
+        }
+        if (needed < buffer.size()) {
+            buffer.resize(needed + 1);
+            return;
+        }
+        buffer.resize(buffer.size() * 2);
+    }
+}
+
+void RenderNode::markDrawStart(SkCanvas& canvas) {
+    StringBuffer buffer;
+    format(buffer, "RenderNode(id=%d, name='%s')", uniqueId(), getName());
+    canvas.drawAnnotation(SkRect::MakeWH(getWidth(), getHeight()), buffer.data(), nullptr);
+}
+
+void RenderNode::markDrawEnd(SkCanvas& canvas) {
+    StringBuffer buffer;
+    format(buffer, "/RenderNode(id=%d, name='%s')", uniqueId(), getName());
+    canvas.drawAnnotation(SkRect::MakeWH(getWidth(), getHeight()), buffer.data(), nullptr);
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index be0b46b..6060123 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -213,6 +213,11 @@
 
     UsageHint usageHint() const { return mUsageHint; }
 
+    int64_t uniqueId() const { return mUniqueId; }
+
+    void markDrawStart(SkCanvas& canvas);
+    void markDrawEnd(SkCanvas& canvas);
+
 private:
     void computeOrderingImpl(RenderNodeOp* opState,
                              std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
@@ -233,6 +238,7 @@
     void incParentRefCount() { mParentCount++; }
     void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);
 
+    const int64_t mUniqueId;
     String8 mName;
     sp<VirtualLightRefBase> mUserContext;
 
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index ea14d11..d80cb6d 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -115,12 +115,26 @@
     }
 }
 
+class MarkDraw {
+public:
+    explicit MarkDraw(SkCanvas& canvas, RenderNode& node) : mCanvas(canvas), mNode(node) {
+        if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+            mNode.markDrawStart(mCanvas);
+        }
+    }
+    ~MarkDraw() {
+        if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+            mNode.markDrawEnd(mCanvas);
+        }
+    }
+private:
+    SkCanvas& mCanvas;
+    RenderNode& mNode;
+};
+
 void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
     RenderNode* renderNode = mRenderNode.get();
-    if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
-        SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight());
-        canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr);
-    }
+    MarkDraw _marker{*canvas, *renderNode};
 
     // We only respect the nothingToDraw check when we are composing a layer. This
     // ensures that we paint the layer even if it is not currently visible in the
diff --git a/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml b/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
index 0678263..789d185 100644
--- a/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
+++ b/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
@@ -72,7 +72,6 @@
     </LinearLayout>
 
     <LinearLayout
-        android:id="@+id/entity_header_links"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_centerVertical="true"
@@ -85,6 +84,7 @@
             android:layout_width="wrap_content"
             android:layout_weight="1"
             android:layout_height="0dp"
+            android:visibility="gone"
             android:minWidth="24dp"
             android:src="@null"
             android:tint="?android:attr/colorAccent"/>
@@ -95,6 +95,7 @@
             android:layout_width="wrap_content"
             android:layout_weight="1"
             android:layout_height="0dp"
+            android:visibility="gone"
             android:minWidth="24dp"
             android:src="@null"
             android:tint="?android:attr/colorAccent"/>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 8b434a5..496aa0e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -323,7 +323,9 @@
             post(new Runnable() {
                 @Override
                 public void run() {
-                    handleShowingDetail(detail, x, y, false /* toggleQs */);
+                    if (isAttachedToWindow()) {
+                        handleShowingDetail(detail, x, y, false /* toggleQs */);
+                    }
                 }
             });
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 0638998..3a96595d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -198,7 +198,8 @@
         mIcon.setIcon(state, allowAnimations);
         setContentDescription(state.contentDescription);
 
-        mAccessibilityClass = state.expandedAccessibilityClassName;
+        mAccessibilityClass =
+                state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName;
         if (state instanceof QSTile.BooleanState) {
             boolean newState = ((BooleanState) state).value;
             if (mTileState != newState) {
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 645723e..d1dbbff 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,5 @@
 anniemeng@google.com
-artikz@google.com
 brufino@google.com
 bryanmawhinney@google.com
 ctate@google.com
 jorlow@google.com
-mkarpinski@google.com
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 7750c37..9ed978f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -554,7 +554,7 @@
 
     final Handler mHandler;
     @VisibleForTesting
-    public final Handler mUidEventHandler;
+    final Handler mUidEventHandler;
 
     private final ServiceThread mUidEventThread;
 
@@ -1465,7 +1465,7 @@
     }
 
     @VisibleForTesting
-    public void updateNetworks() throws InterruptedException {
+    void updateNetworks() throws InterruptedException {
         updateNetworksInternal();
         final CountDownLatch latch = new CountDownLatch(1);
         mHandler.post(() -> {
@@ -1510,7 +1510,7 @@
      * @return cycleDay to use in the mobile NetworkPolicy.
      */
     @VisibleForTesting
-    public int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
+    int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
             int fallbackCycleDay) {
         if (config == null) {
             return fallbackCycleDay;
@@ -1542,7 +1542,7 @@
      * @return warningBytes to use in the mobile NetworkPolicy.
      */
     @VisibleForTesting
-    public long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
+    long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
             long fallbackWarningBytes) {
         if (config == null) {
             return fallbackWarningBytes;
@@ -1575,7 +1575,7 @@
      * @return limitBytes to use in the mobile NetworkPolicy.
      */
     @VisibleForTesting
-    public long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
+    long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
             long fallbackLimitBytes) {
         if (config == null) {
             return fallbackLimitBytes;
@@ -2039,7 +2039,7 @@
     }
 
     @VisibleForTesting
-    public NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
+    NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
         final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
         final RecurrenceRule cycleRule = NetworkPolicy
                 .buildRule(ZonedDateTime.now().getDayOfMonth(), ZoneId.systemDefault());
@@ -3489,7 +3489,7 @@
     }
 
     @VisibleForTesting
-    public boolean isUidForeground(int uid) {
+    boolean isUidForeground(int uid) {
         synchronized (mUidRulesFirstLock) {
             return isUidStateForeground(
                     mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
@@ -3931,7 +3931,7 @@
      * power saving restrictions may still apply.
      */
     @VisibleForTesting
-    public void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
+    void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
         synchronized (mUidRulesFirstLock) {
             if (mAppIdleTempWhitelistAppIds.get(uid) == shouldWhitelist) {
                 // No change.
@@ -3956,7 +3956,7 @@
 
     /** Return the list of UIDs currently in the app idle whitelist. */
     @VisibleForTesting
-    public int[] getAppIdleWhitelist() {
+    int[] getAppIdleWhitelist() {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
         synchronized (mUidRulesFirstLock) {
@@ -3971,7 +3971,7 @@
 
     /** Returns if the UID is currently considered idle. */
     @VisibleForTesting
-    public boolean isUidIdle(int uid) {
+    boolean isUidIdle(int uid) {
         synchronized (mUidRulesFirstLock) {
             if (mAppIdleTempWhitelistAppIds.get(uid)) {
                 // UID is temporarily whitelisted.
@@ -4844,13 +4844,13 @@
     }
 
     @VisibleForTesting
-    public void addIdleHandler(IdleHandler handler) {
+    void addIdleHandler(IdleHandler handler) {
         mHandler.getLooper().getQueue().addIdleHandler(handler);
     }
 
     @GuardedBy("mUidRulesFirstLock")
     @VisibleForTesting
-    public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
+    void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
         mRestrictBackgroundPowerState = result;
 
         boolean restrictBackground = result.batterySaverEnabled;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f279af0..94d276c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -309,6 +309,7 @@
             newConfig = mConfig.copy();
             ZenRule rule = new ZenRule();
             populateZenRule(automaticZenRule, rule, true);
+            newConfig.automaticRules.put(rule.id, rule);
             if (setConfigLocked(newConfig, reason, rule.component, true)) {
                 return rule.id;
             } else {
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index e194d15..2d583ca3 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -105,6 +105,8 @@
      */
     private boolean perUser;
 
+    boolean usageInfoRequired;
+
     public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) {
         name = _name;
         sourcePackageName = _sourcePackageName;
@@ -351,6 +353,7 @@
         }
         if (bp.perm == p) {
             bp.protectionLevel = p.info.protectionLevel;
+            bp.usageInfoRequired = p.info.usageInfoRequired;
         }
         if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
             Log.d(TAG, "  Permissions: " + r);
@@ -430,6 +433,7 @@
         permissionInfo.packageName = sourcePackageName;
         permissionInfo.nonLocalizedLabel = name;
         permissionInfo.protectionLevel = protectionLevel;
+        permissionInfo.usageInfoRequired = usageInfoRequired;
         return permissionInfo;
     }
 
@@ -458,6 +462,7 @@
         bp.protectionLevel = readInt(parser, null, "protection",
                 PermissionInfo.PROTECTION_NORMAL);
         bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
+        bp.usageInfoRequired = readInt(parser, null, "usageInfoRequired", 0) != 0;
         if (dynamic) {
             final PermissionInfo pi = new PermissionInfo();
             pi.packageName = sourcePackage.intern();
@@ -465,6 +470,7 @@
             pi.icon = readInt(parser, null, "icon", 0);
             pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
             pi.protectionLevel = bp.protectionLevel;
+            pi.usageInfoRequired = bp.usageInfoRequired;
             bp.pendingPermissionInfo = pi;
         }
         out.put(bp.name, bp);
@@ -497,6 +503,7 @@
         if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
             serializer.attribute(null, "protection", Integer.toString(protectionLevel));
         }
+        serializer.attribute(null, "usageInfoRequired", usageInfoRequired ? "1" : "0");
         if (type == BasePermission.TYPE_DYNAMIC) {
             final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo;
             if (pi != null) {
@@ -533,6 +540,7 @@
         if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
         // We'll take care of setting this one.
         if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
+        if (pi1.usageInfoRequired != pi2.usageInfoRequired) return false;
         // These are not currently stored in settings.
         //if (!compareStrings(pi1.group, pi2.group)) return false;
         //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
@@ -580,6 +588,8 @@
             pw.print("    enforced=");
             pw.println(readEnforced);
         }
+        pw.print("    usageInfoRequired=");
+        pw.println(usageInfoRequired);
         return true;
     }
 }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 4124210..b390eeb 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -30,6 +30,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.text.TextUtils;
@@ -42,6 +44,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
+import java.io.FileDescriptor;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -334,5 +337,13 @@
             return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
                     false, true, name, null);
         }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out,
+                FileDescriptor err, String[] args, ShellCallback callback,
+                ResultReceiver resultReceiver) {
+            (new RoleManagerShellCommand(this)).exec(
+                    this, in, out, err, args, callback, resultReceiver);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/role/RoleManagerShellCommand.java b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
new file mode 100644
index 0000000..e1977ef
--- /dev/null
+++ b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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.server.role;
+
+import android.app.role.IRoleManager;
+import android.app.role.IRoleManagerCallback;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+class RoleManagerShellCommand extends ShellCommand {
+    private final IRoleManager mRoleManager;
+
+    RoleManagerShellCommand(IRoleManager roleManager) {
+        mRoleManager = roleManager;
+    }
+
+    private class Callback extends IRoleManagerCallback.Stub {
+        private final CompletableFuture<Void> mResult = new CompletableFuture<>();
+
+        public int waitForResult() {
+            try {
+                mResult.get(5, TimeUnit.SECONDS);
+                return 0;
+            } catch (Exception e) {
+                getErrPrintWriter().println("Error: " + e.toString());
+                return -1;
+            }
+        }
+
+        @Override
+        public void onSuccess() {
+            mResult.complete(null);
+        }
+
+        @Override
+        public void onFailure() {
+            mResult.completeExceptionally(new RuntimeException("Failed"));
+        }
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+
+        PrintWriter pw = getOutPrintWriter();
+        try {
+            switch (cmd) {
+                case "add-role-holder":
+                    return runAddRoleHolder();
+                case "remove-role-holder":
+                    return runRemoveRoleHolder();
+                case "clear-role-holders":
+                    return runClearRoleHolders();
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (RemoteException e) {
+            pw.println("Remote exception: " + e);
+        }
+        return -1;
+    }
+
+    private int getUserIdMaybe() {
+        int userId = UserHandle.USER_SYSTEM;
+        String option = getNextOption();
+        if (option != null && option.equals("--user")) {
+            userId = UserHandle.parseUserArg(getNextArgRequired());
+        }
+        return userId;
+    }
+
+    private int runAddRoleHolder() throws RemoteException {
+        int userId = getUserIdMaybe();
+        String roleName = getNextArgRequired();
+        String packageName = getNextArgRequired();
+
+        Callback callback = new Callback();
+        mRoleManager.addRoleHolderAsUser(roleName, packageName, userId, callback);
+        return callback.waitForResult();
+    }
+
+    private int runRemoveRoleHolder() throws RemoteException {
+        int userId = getUserIdMaybe();
+        String roleName = getNextArgRequired();
+        String packageName = getNextArgRequired();
+
+        Callback callback = new Callback();
+        mRoleManager.removeRoleHolderAsUser(roleName, packageName, userId, callback);
+        return callback.waitForResult();
+    }
+
+    private int runClearRoleHolders() throws RemoteException {
+        int userId = getUserIdMaybe();
+        String roleName = getNextArgRequired();
+
+        Callback callback = new Callback();
+        mRoleManager.clearRoleHoldersAsUser(roleName, userId, callback);
+        return callback.waitForResult();
+    }
+
+    @Override
+    public void onHelp() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("Role manager (role) commands:");
+        pw.println("  help");
+        pw.println("    Print this help text.");
+        pw.println();
+        pw.println("  add-role-holder [--user USER_ID] ROLE PACKAGE");
+        pw.println("  remove-role-holder [--user USER_ID] ROLE PACKAGE");
+        pw.println("  clear-role-holders [--user USER_ID] ROLE");
+        pw.println();
+    }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 33584d4..84750b3 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -181,6 +181,11 @@
         mWindowContainerController.onDisplayChanged();
     }
 
+    @Override
+    public void onInitializeOverrideConfiguration(Configuration config) {
+        getOverrideConfiguration().updateFrom(config);
+    }
+
     void addChild(ActivityStack stack, int position) {
         if (position == POSITION_BOTTOM) {
             position = 0;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8f99dae..11e998c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4511,6 +4511,21 @@
         return mKeyguardController.isKeyguardLocked();
     }
 
+    /**
+     * Clears launch params for the given package.
+     * @param packageNames the names of the packages of which the launch params are to be cleared
+     */
+    @Override
+    public void clearLaunchParamsForPackages(List<String> packageNames) {
+        mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "clearLaunchParamsForPackages");
+        synchronized (mGlobalLock) {
+            for (int i = 0; i < packageNames.size(); ++i) {
+                mStackSupervisor.mLaunchParamsPersister.removeRecordForPackage(packageNames.get(i));
+            }
+        }
+    }
+
     void dumpLastANRLocked(PrintWriter pw) {
         pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
         if (mLastANRState == null) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a834ef1..c0e9836 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -34,6 +34,7 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.GONE;
+import static android.view.InsetsState.TYPE_IME;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
@@ -123,6 +124,7 @@
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -150,6 +152,7 @@
 import android.view.Gravity;
 import android.view.InputChannel;
 import android.view.InputDevice;
+import android.view.InsetsState.InternalInsetType;
 import android.view.MagnificationSpec;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -161,6 +164,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
+import com.android.internal.util.function.TriConsumer;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.utils.DisplayRotationUtil;
 import com.android.server.wm.utils.RotationCache;
@@ -506,6 +510,8 @@
 
     private final PointerEventDispatcher mPointerEventDispatcher;
 
+    private final InsetsStateController mInsetsStateController;
+
     // Last systemUiVisibility we received from status bar.
     private int mLastStatusBarVisibility = 0;
     // Last systemUiVisibility we dispatched to windows.
@@ -902,6 +908,7 @@
 
         mService.mAnimator.addDisplayLocked(mDisplayId);
         mInputMonitor = new InputMonitor(service, mDisplayId);
+        mInsetsStateController = new InsetsStateController(this);
     }
 
     boolean isReady() {
@@ -1038,6 +1045,23 @@
         return mDisplayRotation;
     }
 
+    /**
+     * Marks a window as providing insets for the rest of the windows in the system.
+     *
+     * @param type The type of inset this window provides.
+     * @param win The window.
+     * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
+     *                      the window should be taken.
+     */
+    void setInsetProvider(@InternalInsetType int type, WindowState win,
+            @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
+        mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider);
+    }
+
+    InsetsStateController getInsetsStateController() {
+        return mInsetsStateController;
+    }
+
     @VisibleForTesting
     void setDisplayRotation(DisplayRotation displayRotation) {
         mDisplayRotation = displayRotation;
@@ -2712,6 +2736,8 @@
         mDisplayRotation.dump(prefix, pw);
         pw.println();
         mInputMonitor.dump(pw, "  ");
+        pw.println();
+        mInsetsStateController.dump(prefix, pw);
     }
 
     @Override
@@ -2994,6 +3020,8 @@
                     mInputMethodWindow.getDisplayId());
         }
         computeImeTarget(true /* updateImeTarget */);
+        mInsetsStateController.getSourceProvider(TYPE_IME).setWindow(win,
+                null /* frameProvider */);
     }
 
     /**
@@ -3449,6 +3477,7 @@
             pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
             if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
                     "after finishPostLayoutPolicyLw", pendingLayoutChanges);
+                mInsetsStateController.onPostLayout();
         } while (pendingLayoutChanges != 0);
 
         mTmpApplySurfaceChangesTransactionState.reset();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index c16f95e..0e5947a 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -25,6 +25,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.view.InsetsState.TYPE_TOP_BAR;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -128,6 +129,7 @@
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
+import android.view.InsetsState;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.Surface;
@@ -804,6 +806,11 @@
                 if (mDisplayContent.isDefaultDisplay) {
                     mService.mPolicy.setKeyguardCandidateLw(win);
                 }
+                mDisplayContent.setInsetProvider(TYPE_TOP_BAR, win,
+                        (displayFrames, windowState, rect) -> {
+                            rect.top = 0;
+                            rect.bottom = getStatusBarHeight(displayFrames);
+                        });
                 break;
             case TYPE_NAVIGATION_BAR:
                 mContext.enforceCallingOrSelfPermission(
@@ -818,6 +825,8 @@
                 mNavigationBarController.setWindow(win);
                 mNavigationBarController.setOnBarVisibilityChangedListener(
                         mNavBarVisibilityListener, true);
+                mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR,
+                        win, null /* frameProvider */);
                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                 break;
             case TYPE_NAVIGATION_BAR_PANEL:
@@ -845,9 +854,11 @@
             if (mDisplayContent.isDefaultDisplay) {
                 mService.mPolicy.setKeyguardCandidateLw(null);
             }
+            mDisplayContent.setInsetProvider(TYPE_TOP_BAR, null, null);
         } else if (mNavigationBar == win) {
             mNavigationBar = null;
             mNavigationBarController.setWindow(null);
+            mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR, null, null);
         }
         if (mLastFocusedWindow == win) {
             mLastFocusedWindow = null;
@@ -855,6 +866,11 @@
         mScreenDecorWindows.remove(win);
     }
 
+    private int getStatusBarHeight(DisplayFrames displayFrames) {
+        return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
+                displayFrames.mDisplayCutoutSafe.top);
+    }
+
     /**
      * Control the animation to run when a window's state changes.  Return a
      * non-0 number to force the animation to a specific resource ID, or 0
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index f1d1e49..7aabc15 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -30,6 +31,7 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.power.V1_0.PowerHint;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -57,6 +59,7 @@
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
     private final DisplayPolicy mDisplayPolicy;
+    private final DisplayWindowSettings mDisplayWindowSettings;
     private final Context mContext;
     private final Object mLock;
 
@@ -71,10 +74,6 @@
     private StatusBarManagerInternal mStatusBarManagerInternal;
     private SettingsObserver mSettingsObserver;
 
-    // Default display does not rotate, apps that require non-default orientation will have to
-    // have the orientation emulated.
-    private boolean mForceDefaultOrientation;
-
     private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
     @VisibleForTesting
@@ -93,6 +92,13 @@
     private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
     private int mUserRotation = Surface.ROTATION_0;
 
+    /**
+     * A flag to indicate if the display rotation should be fixed to user specified rotation
+     * regardless of all other states (including app requrested orientation). {@code true} the
+     * display rotation should be fixed to user specified rotation, {@code false} otherwise.
+     */
+    private boolean mFixedToUserRotation;
+
     private int mDemoHdmiRotation;
     private int mDemoRotation;
     private boolean mDemoHdmiRotationLock;
@@ -100,15 +106,17 @@
 
     DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
         this(service, displayContent, displayContent.getDisplayPolicy(),
-                service.mContext, service.getWindowManagerLock());
+                service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock());
     }
 
     @VisibleForTesting
     DisplayRotation(WindowManagerService service, DisplayContent displayContent,
-            DisplayPolicy displayPolicy, Context context, Object lock) {
+            DisplayPolicy displayPolicy, DisplayWindowSettings displayWindowSettings,
+            Context context, Object lock) {
         mService = service;
         mDisplayContent = displayContent;
         mDisplayPolicy = displayPolicy;
+        mDisplayWindowSettings = displayWindowSettings;
         mContext = context;
         mLock = lock;
         isDefaultDisplay = displayContent.isDefaultDisplay;
@@ -204,12 +212,19 @@
         // so if the orientation is forced, we need to respect that no matter what.
         final boolean isTv = mContext.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_LEANBACK);
-        mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
-                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
-                // For debug purposes the next line turns this feature off with:
-                // $ adb shell setprop config.override_forced_orient true
-                // $ adb shell wm size reset
-                !"true".equals(SystemProperties.get("config.override_forced_orient"));
+        final boolean forceDefaultOrientationInRes =
+                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
+        final boolean forceDefaultOrienation =
+                ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv)
+                        && forceDefaultOrientationInRes
+                        // For debug purposes the next line turns this feature off with:
+                        // $ adb shell setprop config.override_forced_orient true
+                        // $ adb shell wm size reset
+                        && !"true".equals(SystemProperties.get("config.override_forced_orient"));
+        // Configuration says we force to use the default orientation. We can fall back to fix
+        // rotation to only user rotation. As long as OEM doesn't change user rotation then the
+        // rotation of this display is effectively stuck at 0 deg.
+        setFixedToUserRotation(forceDefaultOrienation);
     }
 
     void setRotation(int rotation) {
@@ -227,7 +242,14 @@
         }
     }
 
-    void restoreUserRotation(int userRotationMode, int userRotation) {
+    void restoreSettings(int userRotationMode, int userRotation,
+            boolean fixedToUserRotation) {
+        mFixedToUserRotation = fixedToUserRotation;
+
+        // We will retrieve user rotation and user rotation mode from settings for default display.
+        if (isDefaultDisplay) {
+            return;
+        }
         if (userRotationMode != WindowManagerPolicy.USER_ROTATION_FREE
                 && userRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
             Slog.w(TAG, "Trying to restore an invalid user rotation mode " + userRotationMode
@@ -243,6 +265,18 @@
         mUserRotation = userRotation;
     }
 
+    void setFixedToUserRotation(boolean fixedToUserRotation) {
+        if (mFixedToUserRotation == fixedToUserRotation) {
+            return;
+        }
+
+        mFixedToUserRotation = fixedToUserRotation;
+        mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
+                fixedToUserRotation);
+        mService.updateRotation(true /* alwaysSendConfiguration */,
+                false /* forceRelayout */);
+    }
+
     private void setUserRotation(int userRotationMode, int userRotation) {
         if (isDefaultDisplay) {
             // We'll be notified via settings listener, so we don't need to update internal values.
@@ -265,7 +299,7 @@
             mUserRotation = userRotation;
             changed = true;
         }
-        mService.mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
+        mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
                 userRotation);
         if (changed) {
             mService.updateRotation(true /* alwaysSendConfiguration */,
@@ -291,9 +325,8 @@
                 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
     }
 
-    /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
-    boolean isDefaultOrientationForced() {
-        return mForceDefaultOrientation;
+    boolean isFixedToUserRotation() {
+        return mFixedToUserRotation;
     }
 
     public int getLandscapeRotation() {
@@ -399,6 +432,12 @@
      * screen is switched off.
      */
     private boolean needSensorRunning() {
+        if (mFixedToUserRotation) {
+            // We are sure we only respect user rotation settings, so we are sure we will not
+            // support sensor rotation.
+            return false;
+        }
+
         if (mSupportAutoRotation) {
             if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
                     || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
@@ -459,8 +498,8 @@
                         );
         }
 
-        if (mForceDefaultOrientation) {
-            return Surface.ROTATION_0;
+        if (mFixedToUserRotation) {
+            return mUserRotation;
         }
 
         int sensorRotation = mOrientationListener != null
@@ -701,8 +740,8 @@
         // demo, hdmi, vr, etc mode.
 
         // Determine if the rotation is currently forced.
-        if (mForceDefaultOrientation) {
-            return false; // Rotation is forced to default orientation.
+        if (mFixedToUserRotation) {
+            return false; // Rotation is forced to user settings.
         }
 
         final int lidState = mDisplayPolicy.getLidState();
@@ -861,6 +900,7 @@
         pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
         pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
         pw.println(prefix + "  mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+        pw.println(prefix + "  mFixedToUserRotation=" + mFixedToUserRotation);
     }
 
     private class OrientationListener extends WindowOrientationListener {
@@ -945,4 +985,10 @@
             }
         }
     }
+
+    @VisibleForTesting
+    interface ContentObserverRegister {
+        void registerContentObserver(Uri uri, boolean notifyForDescendants,
+                ContentObserver observer, @UserIdInt int userHandle);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f7dfd3f..45d77de 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -80,6 +80,7 @@
         private boolean mShouldShowWithInsecureKeyguard = false;
         private boolean mShouldShowSystemDecors = false;
         private boolean mShouldShowIme = false;
+        private boolean mFixedToUserRotation;
 
         private Entry(String name) {
             mName = name;
@@ -97,7 +98,8 @@
                     && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
                     && !mShouldShowWithInsecureKeyguard
                     && !mShouldShowSystemDecors
-                    && !mShouldShowIme;
+                    && !mShouldShowIme
+                    && !mFixedToUserRotation;
         }
     }
 
@@ -186,6 +188,13 @@
         writeSettingsIfNeeded(entry, displayInfo);
     }
 
+    void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mFixedToUserRotation = fixedToUserRotation;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
     private int getWindowingModeLocked(Entry entry, int displayId) {
         int windowingMode = entry != null ? entry.mWindowingMode
                 : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -331,7 +340,8 @@
         displayInfo.overscanRight = entry.mOverscanRight;
         displayInfo.overscanBottom = entry.mOverscanBottom;
 
-        dc.getDisplayRotation().restoreUserRotation(entry.mUserRotationMode, entry.mUserRotation);
+        dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
+                entry.mUserRotation, entry.mFixedToUserRotation);
 
         if (entry.mForcedDensity != 0) {
             dc.mBaseDisplayDensity = entry.mForcedDensity;
@@ -458,6 +468,8 @@
                     "shouldShowWithInsecureKeyguard");
             entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
             entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
+            entry.mFixedToUserRotation = getBooleanAttribute(parser,
+                    "fixedToUserRotation");
             mEntries.put(name, entry);
         }
         XmlUtils.skipCurrentTag(parser);
@@ -541,6 +553,10 @@
                 if (entry.mShouldShowIme) {
                     out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
                 }
+                if (entry.mFixedToUserRotation) {
+                    out.attribute(null, "fixedToUserRotation",
+                            Boolean.toString(entry.mFixedToUserRotation));
+                }
                 out.endTag(null, "display");
             }
 
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
new file mode 100644
index 0000000..e96f0b1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.view.InsetsSource;
+
+import com.android.internal.util.function.TriConsumer;
+import com.android.server.policy.WindowManagerPolicy;
+
+/**
+ * Controller for a specific inset source on the server. It's called provider as it provides the
+ * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
+ */
+class InsetsSourceProvider {
+
+    private final Rect mTmpRect = new Rect();
+    private final @NonNull InsetsSource mSource;
+    private WindowState mWin;
+    private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
+
+    InsetsSourceProvider(InsetsSource source) {
+        mSource = source;
+    }
+
+    InsetsSource getSource() {
+        return mSource;
+    }
+
+    /**
+     * Updates the window that currently backs this source.
+     *
+     * @param win The window that links to this source.
+     * @param frameProvider Based on display frame state and the window, calculates the resulting
+     *                      frame that should be reported to clients.
+     */
+    void setWindow(@Nullable WindowState win,
+            @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
+        if (mWin != null) {
+            mWin.setInsetProvider(null);
+        }
+        mWin = win;
+        mFrameProvider = frameProvider;
+        if (win == null) {
+            mSource.setVisible(false);
+            mSource.setFrame(new Rect());
+        } else {
+            mSource.setVisible(true);
+            mWin.setInsetProvider(this);
+        }
+    }
+
+    /**
+     * Called when a layout pass has occurred.
+     */
+    void onPostLayout() {
+        if (mWin == null) {
+            return;
+        }
+
+        mTmpRect.set(mWin.getFrameLw());
+        if (mFrameProvider != null) {
+            mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
+        } else {
+            mTmpRect.inset(mWin.mGivenContentInsets);
+        }
+        mSource.setFrame(mTmpRect);
+        mSource.setVisible(mWin.isVisible() && !mWin.mGivenInsetsPending);
+
+    }
+}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
new file mode 100644
index 0000000..1189ee6
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+
+import android.util.ArrayMap;
+import android.view.InsetsState;
+
+import java.io.PrintWriter;
+import java.util.function.Consumer;
+
+/**
+ * Manages global window inset state in the system represented by {@link InsetsState}.
+ */
+class InsetsStateController {
+
+    private final InsetsState mLastState = new InsetsState();
+    private final InsetsState mState = new InsetsState();
+    private final DisplayContent mDisplayContent;
+    private ArrayMap<Integer, InsetsSourceProvider> mControllers = new ArrayMap<>();
+
+    private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
+        if (w.isVisible()) {
+            w.notifyInsetsChanged();
+        }
+    };
+
+    InsetsStateController(DisplayContent displayContent) {
+        mDisplayContent = displayContent;
+    }
+
+    /**
+     * When dispatching window state to the client, we'll need to exclude the source that represents
+     * the window that is being dispatched.
+     *
+     * @param target The client we dispatch the state to.
+     * @return The state stripped of the necessary information.
+     */
+    InsetsState getInsetsForDispatch(WindowState target) {
+        final InsetsSourceProvider provider = target.getInsetProvider();
+        if (provider == null) {
+            return mState;
+        }
+
+        final InsetsState state = new InsetsState();
+        state.set(mState);
+        final int type = provider.getSource().getType();
+        state.removeSource(type);
+
+        // Navigation bar doesn't get influenced by anything else
+        if (type == TYPE_NAVIGATION_BAR) {
+            state.removeSource(TYPE_IME);
+            state.removeSource(TYPE_TOP_BAR);
+        }
+        return state;
+    }
+
+    /**
+     * @return The provider of a specific type.
+     */
+    InsetsSourceProvider getSourceProvider(int type) {
+        return mControllers.computeIfAbsent(type,
+                key -> new InsetsSourceProvider(mState.getSource(key)));
+    }
+
+    /**
+     * Called when a layout pass has occurred.
+     */
+    void onPostLayout() {
+        for (int i = mControllers.size() - 1; i>= 0; i--) {
+            mControllers.valueAt(i).onPostLayout();
+        }
+        if (!mLastState.equals(mState)) {
+            mLastState.set(mState, true /* copySources */);
+            notifyInsetsChanged();
+        }
+    }
+
+    private void notifyInsetsChanged() {
+        mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix + "WindowInsetsStateController");
+        mState.dump(prefix + "  ", pw);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index da9a507..bc6a690 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -269,7 +269,7 @@
         outParams.mBounds.set(persistableParams.mBounds);
     }
 
-    private void onPackageRemoved(String packageName) {
+    void removeRecordForPackage(String packageName) {
         final List<File> fileToDelete = new ArrayList<>();
         for (int i = 0; i < mMap.size(); ++i) {
             int userId = mMap.keyAt(i);
@@ -310,7 +310,7 @@
 
         @Override
         public void onPackageRemoved(String packageName) {
-            LaunchParamsPersister.this.onPackageRemoved(packageName);
+            removeRecordForPackage(packageName);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index c2bc677..80d1368 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -233,6 +233,7 @@
         final DisplayContent existing = getDisplayContent(displayId);
 
         if (existing != null) {
+            initializeDisplayOverrideConfiguration(controller, existing);
             existing.setController(controller);
             return existing;
         }
@@ -242,6 +243,7 @@
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
 
         mService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
+        initializeDisplayOverrideConfiguration(controller, dc);
 
         if (mService.mDisplayManagerInternal != null) {
             mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
@@ -254,6 +256,19 @@
         return dc;
     }
 
+    /**
+     * The display content may have configuration set from {@link #DisplayWindowSettings}. This
+     * callback let the owner of container know there is existing configuration to prevent the
+     * values from being replaced by the initializing {@link #ActivityDisplay}.
+     */
+    private void initializeDisplayOverrideConfiguration(DisplayWindowController controller,
+            DisplayContent displayContent) {
+        if (controller != null && controller.mListener != null) {
+            controller.mListener.onInitializeOverrideConfiguration(
+                    displayContent.getOverrideConfiguration());
+        }
+    }
+
     boolean isLayoutNeeded() {
         final int numDisplays = mChildren.size();
         for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index ee0e89b..3947bd4 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -222,7 +222,7 @@
     }
 
     public ScreenRotationAnimation(Context context, DisplayContent displayContent,
-            boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
+            boolean fixedToUserRotation, boolean isSecure, WindowManagerService service) {
         mService = service;
         mContext = context;
         mDisplayContent = displayContent;
@@ -234,7 +234,7 @@
         final int originalWidth;
         final int originalHeight;
         DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        if (forceDefaultOrientation) {
+        if (fixedToUserRotation) {
             // Emulated orientation.
             mForceDefaultOrientation = true;
             originalWidth = displayContent.mBaseDisplayWidth;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 6838c55..37b5a7c 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -50,6 +50,7 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
+import android.view.InsetsState;
 import android.view.WindowManager;
 
 import com.android.internal.os.logging.MetricsLoggerWrapper;
@@ -153,17 +154,21 @@
     public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
             Rect outStableInsets, Rect outOutsets,
-            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
+            InsetsState outInsetsState) {
         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
-                outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
+                outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,
+                outInsetsState);
     }
 
     @Override
     public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
+            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
+            InsetsState outInsetsState) {
         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                 new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
-                new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */);
+                new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
+                outInsetsState);
     }
 
     @Override
@@ -182,7 +187,7 @@
             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
             Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
-            Surface outSurface) {
+            Surface outSurface, InsetsState outInsetsState) {
         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
@@ -190,7 +195,7 @@
                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                 outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                 outStableInsets, outsets, outBackdropFrame, cutout,
-                mergedConfiguration, outSurface);
+                mergedConfiguration, outSurface, outInsetsState);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 8f02f8a..9a56606 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -66,6 +66,7 @@
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
+import android.view.InsetsState;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -142,6 +143,7 @@
         final Rect taskBounds;
         final Rect tmpContentInsets = new Rect();
         final Rect tmpStableInsets = new Rect();
+        final InsetsState mTmpInsetsState = new InsetsState();
         final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
         int backgroundColor = WHITE;
         int statusBarColor = 0;
@@ -202,7 +204,7 @@
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
                     View.GONE, token.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
-                    tmpRect, tmpCutout, null);
+                    tmpRect, tmpCutout, null, mTmpInsetsState);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
                 return null;
@@ -218,7 +220,7 @@
         try {
             session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
                     tmpFrame, tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
-                    tmpCutout, tmpMergedConfiguration, surface);
+                    tmpCutout, tmpMergedConfiguration, surface, mTmpInsetsState);
         } catch (RemoteException e) {
             // Local call.
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainerListener.java b/services/core/java/com/android/server/wm/WindowContainerListener.java
index 4b3cd36..3d3d2e0 100644
--- a/services/core/java/com/android/server/wm/WindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/WindowContainerListener.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import android.content.res.Configuration;
+
 /**
  * Interface used by the owner/creator of the container to listen to changes with the container.
  * @see WindowContainerController
@@ -23,4 +25,5 @@
 public interface WindowContainerListener {
     void registerConfigurationChangeListener(ConfigurationContainerListener listener);
     void unregisterConfigurationChangeListener(ConfigurationContainerListener listener);
+    default void onInitializeOverrideConfiguration(Configuration config) {}
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5df3451..4085f3d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -218,6 +218,7 @@
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowContentFrameStats;
+import android.view.InsetsState;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.RemoveContentMode;
@@ -1111,7 +1112,8 @@
     public int addWindow(Session session, IWindow client, int seq,
             LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
             Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
-            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
+            InsetsState outInsetsState) {
         int[] appOp = new int[1];
         int res = mPolicy.checkAddPermission(attrs, appOp);
         if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -1459,6 +1461,7 @@
                     outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
                 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
             }
+            outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
 
             if (mInTouchMode) {
                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -1856,7 +1859,7 @@
             long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
             Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
-            Surface outSurface) {
+            Surface outSurface, InsetsState outInsetsState) {
         int result = 0;
         boolean configChanged;
         final boolean hasStatusBarPermission =
@@ -2157,6 +2160,7 @@
                     outStableInsets, outOutsets);
             outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
             outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
+            outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
             if (localLOGV) Slog.v(
                 TAG_WM, "Relayout given client " + client.asBinder()
                 + ", requestedWidth=" + requestedWidth
@@ -3587,6 +3591,17 @@
         }
     }
 
+    void setRotateForApp(int displayId, boolean enabled) {
+        synchronized (mGlobalLock) {
+            final DisplayContent display = mRoot.getDisplayContent(displayId);
+            if (display == null) {
+                Slog.w(TAG, "Trying to set rotate for app for a missing display.");
+                return;
+            }
+            display.getDisplayRotation().setFixedToUserRotation(enabled);
+        }
+    }
+
     @Override
     public void freezeRotation(int rotation) {
         freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation);
@@ -5393,7 +5408,7 @@
 
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
+                    displayContent.getDisplayRotation().isFixedToUserRotation(), isSecure,
                     this);
             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
                     screenRotationAnimation);
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bf77ba8..6865ce3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -76,6 +76,8 @@
                             getNextArgRequired());
                 case "set-user-rotation":
                     return runSetDisplayUserRotation(pw);
+                case "set-fix-to-user-rotation":
+                    return runSetFixToUserRotation(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -297,6 +299,32 @@
         }
     }
 
+    private int runSetFixToUserRotation(PrintWriter pw) {
+        int displayId = Display.DEFAULT_DISPLAY;
+        String arg = getNextArgRequired();
+        if ("-d".equals(arg)) {
+            displayId = Integer.parseInt(getNextArgRequired());
+            arg = getNextArgRequired();
+        }
+
+        final boolean enabled;
+        switch (arg) {
+            case "enabled":
+                enabled = true;
+                break;
+            case "disabled":
+                enabled = false;
+                break;
+            default:
+                getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
+                        + arg);
+                return -1;
+        }
+
+        mInternal.setRotateForApp(displayId, enabled);
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -316,6 +344,8 @@
         pw.println("    Dismiss the keyguard, prompting user for auth if necessary.");
         pw.println("  set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
         pw.println("    Set user rotation mode and user rotation.");
+        pw.println("  set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
+        pw.println("    Enable or disable rotating display for app requested orientation.");
         if (!IS_USER) {
             pw.println("  tracing (start | stop)");
             pw.println("    Start or stop window tracing.");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 91c3288..cfd1f86 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -143,6 +143,7 @@
 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
 
 import android.annotation.CallSuper;
+import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -194,6 +195,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.policy.WindowManagerPolicy.DisplayContentInfo;
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
 import com.android.server.wm.utils.InsetUtils;
 import com.android.server.wm.utils.WmDisplayCutout;
@@ -578,6 +580,8 @@
      */
     private boolean mIsDimming = false;
 
+    private @Nullable InsetsSourceProvider mInsetProvider;
+
     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
 
     void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
@@ -2955,6 +2959,18 @@
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
+    /**
+     * Called when the insets state changed.
+     */
+    void notifyInsetsChanged() {
+        try {
+            mClient.insetsChanged(
+                    getDisplayContent().getInsetsStateController().getInsetsForDispatch(this));
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Failed to deliver inset state change", e);
+        }
+    }
+
     Rect getBackdropFrame(Rect frame) {
         // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
         // start even if we haven't received the relayout window, so that the client requests
@@ -4776,6 +4792,14 @@
         mWindowFrames.setContentChanged(false);
     }
 
+    void setInsetProvider(InsetsSourceProvider insetProvider) {
+        mInsetProvider = insetProvider;
+    }
+
+    InsetsSourceProvider getInsetProvider() {
+        return mInsetProvider;
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 92efc3c..99b827c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.net;
 
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -72,7 +72,6 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
@@ -142,9 +141,8 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
-import com.android.server.net.NetworkPolicyManagerInternal;
-import com.android.server.net.NetworkPolicyManagerService;
-import com.android.server.net.NetworkStatsManagerInternal;
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
 
 import com.google.common.util.concurrent.AbstractFuture;
 
@@ -195,15 +193,6 @@
 
 /**
  * Tests for {@link NetworkPolicyManagerService}.
- *
- * <p>Typical usage:
- *
- * <pre><code>
-    m -j32 FrameworksServicesTests && adb install -r -g \
-    ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
-    adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
-    "com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner"
- * </code></pre>
  */
 @RunWith(AndroidJUnit4.class)
 @MediumTest
@@ -376,7 +365,7 @@
                 return null;
             }
         }).when(mActivityManager).registerUidObserver(any(), anyInt(),
-                eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), isNull(String.class));
+                eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), any(String.class));
 
         mFutureIntent = newRestrictBackgroundChangedFuture();
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
@@ -425,7 +414,7 @@
 
         // catch INetworkManagementEventObserver during systemReady()
         final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
-              ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+                ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
         verify(mNetworkManager).registerObserver(networkObserver.capture());
         mNetworkObserver = networkObserver.getValue();
 
@@ -1782,7 +1771,7 @@
     }
 
     private static NetworkPolicy buildFakeMobilePolicy(int cycleDay, long warningBytes,
-            long limitBytes, boolean inferred){
+            long limitBytes, boolean inferred) {
         final NetworkTemplate template = buildTemplateMobileAll(FAKE_SUBSCRIBER_ID);
         return new NetworkPolicy(template, cycleDay, new Time().timezone, warningBytes,
                 limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
@@ -1880,7 +1869,7 @@
     }
 
     private static void assertNotificationType(int expected, String actualTag) {
-        assertEquals("notification type mismatch for '" + actualTag +"'",
+        assertEquals("notification type mismatch for '" + actualTag + "'",
                 Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
     }
 
@@ -1914,7 +1903,8 @@
         final String action = ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
         final Intent intent = future.get(5, TimeUnit.SECONDS);
         assertNotNull("Didn't get a " + action + "intent in 5 seconds");
-        assertEquals("Wrong package on " + action + " intent", expectedPackage, intent.getPackage());
+        assertEquals("Wrong package on " + action + " intent",
+                expectedPackage, intent.getPackage());
     }
 
     // TODO: replace by Truth, Hamcrest, or a similar tool.
@@ -1935,7 +1925,7 @@
         }
         if (errors.length() > 0) {
             fail("assertContainsInAnyOrder(expected=" + Arrays.toString(expected)
-                    + ", actual=" + Arrays.toString(actual) +") failed: \n" + errors);
+                    + ", actual=" + Arrays.toString(actual) + ") failed: \n" + errors);
         }
     }
 
@@ -1998,7 +1988,7 @@
 
         @Override
         public Void answer(InvocationOnMock invocation) throws Throwable {
-            Log.d(TAG,"counting down on answer: " + invocation);
+            Log.d(TAG, "counting down on answer: " + invocation);
             latch.countDown();
             return null;
         }
@@ -2036,8 +2026,8 @@
             final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml;
             final File netConfigFile = new File(mPolicyDir, "netpolicy.xml");
             Log.d(TAG, "Creating " + netConfigFile + " from asset " + assetPath);
-            try (final InputStream in = context.getResources().getAssets().open(assetPath);
-                    final OutputStream out = new FileOutputStream(netConfigFile)) {
+            try (InputStream in = context.getResources().getAssets().open(assetPath);
+                    OutputStream out = new FileOutputStream(netConfigFile)) {
                 Streams.copy(in, out);
             }
         }
@@ -2049,9 +2039,7 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.METHOD)
     public @interface NetPolicyXml {
-
-        public String value() default "";
-
+        String value() default "";
     }
 
     /**
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index d798865..ce59e6e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -31,6 +31,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
+import android.content.pm.UsesPermissionInfo;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
@@ -464,6 +465,7 @@
         pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
         pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
         pkg.requestedPermissions.add("foo7");
+        pkg.usesPermissionInfos.add(new UsesPermissionInfo("foo7"));
         pkg.implicitPermissions.add("foo25");
 
         pkg.protectedBroadcasts = new ArrayList<>();
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index b823e70..7f390a5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -27,7 +27,12 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.WindowConfiguration;
 import android.platform.test.annotations.Presubmit;
@@ -378,6 +383,33 @@
                 mSecondaryDisplay.getDisplayRotation().getUserRotation());
     }
 
+    @Test
+    public void testNotFixedToUserRotationByDefault() {
+        mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+                Surface.ROTATION_0);
+
+        final DisplayRotation displayRotation = mock(DisplayRotation.class);
+        mPrimaryDisplay = spy(mPrimaryDisplay);
+        when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+    }
+
+    @Test
+    public void testSetFixedToUserRotation() {
+        mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+
+        final DisplayRotation displayRotation = mock(DisplayRotation.class);
+        mPrimaryDisplay = spy(mPrimaryDisplay);
+        when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+        applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+        verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+    }
+
     private static void assertOverscan(DisplayContent display, int left, int top, int right,
             int bottom) {
         final DisplayInfo info = display.getDisplayInfo();
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
new file mode 100644
index 0000000..241b987
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@Presubmit
+public class InsetsSourceProviderTest extends WindowTestsBase {
+
+    private InsetsSourceProvider mProvider = new InsetsSourceProvider(
+            new InsetsSource(TYPE_TOP_BAR));
+
+    @Test
+    public void testPostLayout() {
+        final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        topBar.getFrameLw().set(0, 0, 500, 100);
+        topBar.mHasSurface = true;
+        mProvider.setWindow(topBar, null);
+        mProvider.onPostLayout();
+        assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame());
+        assertEquals(Insets.of(0, 100, 0, 0),
+                mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+                        false /* ignoreVisibility */));
+    }
+
+    @Test
+    public void testPostLayout_invisible() {
+        final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        topBar.getFrameLw().set(0, 0, 500, 100);
+        mProvider.setWindow(topBar, null);
+        mProvider.onPostLayout();
+        assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+                        false /* ignoreVisibility */));
+    }
+
+    @Test
+    public void testPostLayout_frameProvider() {
+        final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        topBar.getFrameLw().set(0, 0, 500, 100);
+        mProvider.setWindow(topBar,
+                (displayFrames, windowState, rect) -> {
+                    rect.set(10, 10, 20, 20);
+                });
+        mProvider.onPostLayout();
+        assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
new file mode 100644
index 0000000..7505db1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsState;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@Presubmit
+public class InsetsStateControllerTest extends WindowTestsBase {
+
+    @Test
+    public void testStripForDispatch_notOwn() {
+        final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+                .setWindow(topBar, null);
+        topBar.setInsetProvider(
+                mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR));
+        assertNotNull(mDisplayContent.getInsetsStateController().getInsetsForDispatch(app)
+                .getSource(TYPE_TOP_BAR));
+    }
+
+    @Test
+    public void testStripForDispatch_own() {
+        final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+                .setWindow(topBar, null);
+        topBar.setInsetProvider(
+                mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR));
+        assertEquals(new InsetsState(),
+                mDisplayContent.getInsetsStateController().getInsetsForDispatch(topBar));
+    }
+
+    @Test
+    public void testStripForDispatch_navBar() {
+        final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        final WindowState ime = createWindow(null, TYPE_APPLICATION, "parentWindow");
+        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+                .setWindow(topBar, null);
+        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_NAVIGATION_BAR)
+                .setWindow(navBar, null);
+        mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_IME)
+                .setWindow(ime, null);
+        assertEquals(new InsetsState(),
+                mDisplayContent.getInsetsStateController().getInsetsForDispatch(navBar));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index 99deeb9..432af0d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -24,6 +24,7 @@
 import android.view.DisplayCutout;
 import android.view.DragEvent;
 import android.view.IWindow;
+import android.view.InsetsState;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -39,6 +40,9 @@
             Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId,
             DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException {
     }
+    @Override
+    public void insetsChanged(InsetsState insetsState) throws RemoteException {
+    }
 
     @Override
     public void moved(int newX, int newY) throws RemoteException {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 38d8e39..6c7ede3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -41,6 +41,7 @@
 
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.AutomaticZenRule;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.content.ComponentName;
@@ -1097,6 +1098,25 @@
         assertFalse(Objects.equals(defaultRuleName, ruleAfterUpdating.name)); // update name
     }
 
+    @Test
+    public void testAddAutomaticZenRule() {
+        AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                new ComponentName("android", "ScheduleConditionProvider"),
+                ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+
+        assertTrue(id != null);
+        ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
+        assertTrue(ruleInConfig != null);
+        assertEquals(zenRule.isEnabled(), ruleInConfig.enabled);
+        assertEquals(zenRule.isModified(), ruleInConfig.modified);
+        assertEquals(zenRule.getConditionId(), ruleInConfig.conditionId);
+        assertEquals(NotificationManager.zenModeFromInterruptionFilter(
+                zenRule.getInterruptionFilter(), -1), ruleInConfig.zenMode);
+        assertEquals(zenRule.getName(), ruleInConfig.name);
+    }
+
     private void setupZenConfig() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index f128b4e2..67acec6 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -37,6 +37,8 @@
 
     <application android:debuggable="true"
                  android:testOnly="true">
+        <uses-library android:name="android.test.mock" android:required="true" />
+
         <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityA" />
         <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityB" />
         <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
new file mode 100644
index 0000000..e988994
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atMost;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.PowerManagerInternal;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.view.Surface;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test class for {@link DisplayRotation}.
+ *
+ * Build/Install/Run:
+ *  atest WmTests:DisplayRotationTests
+ */
+@SmallTest
+@Presubmit
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
+public class DisplayRotationTests {
+    private static final long UI_HANDLER_WAIT_TIMEOUT_MS = 50;
+
+    private StatusBarManagerInternal mPreviousStatusBarManagerInternal;
+
+    private WindowManagerService mMockWm;
+    private DisplayContent mMockDisplayContent;
+    private DisplayPolicy mMockDisplayPolicy;
+    private Context mMockContext;
+    private Resources mMockRes;
+    private SensorManager mMockSensorManager;
+    private Sensor mFakeSensor;
+    private DisplayWindowSettings mMockDisplayWindowSettings;
+    private ContentResolver mMockResolver;
+    private FakeSettingsProvider mFakeSettingsProvider;
+    private StatusBarManagerInternal mMockStatusBarManagerInternal;
+
+    // Fields below are callbacks captured from test target.
+    private ContentObserver mShowRotationSuggestionsObserver;
+    private ContentObserver mAccelerometerRotationObserver;
+    private ContentObserver mUserRotationObserver;
+    private SensorEventListener mOrientationSensorListener;
+
+    private DisplayRotationBuilder mBuilder;
+
+    private DisplayRotation mTarget;
+
+    @Before
+    public void setUp() {
+        FakeSettingsProvider.clearSettingsProvider();
+
+        mMockWm = mock(WindowManagerService.class);
+        mMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class);
+
+        mPreviousStatusBarManagerInternal = LocalServices.getService(
+                StatusBarManagerInternal.class);
+        LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+        mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class);
+        LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);
+
+        mBuilder = new DisplayRotationBuilder();
+    }
+
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+        if (mPreviousStatusBarManagerInternal != null) {
+            LocalServices.addService(StatusBarManagerInternal.class,
+                    mPreviousStatusBarManagerInternal);
+            mPreviousStatusBarManagerInternal = null;
+        }
+    }
+
+    // ================================
+    // Display Settings Related Tests
+    // ================================
+    @Test
+    public void testLocksUserRotation_LockRotation_DefaultDisplay() throws Exception {
+        mBuilder.build();
+
+        freezeRotation(Surface.ROTATION_180);
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+        assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+        assertEquals(0, Settings.System.getInt(mMockResolver,
+                Settings.System.ACCELEROMETER_ROTATION));
+        assertEquals(Surface.ROTATION_180, Settings.System.getInt(mMockResolver,
+                Settings.System.USER_ROTATION));
+    }
+
+    @Test
+    public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
+        mBuilder.mIsDefaultDisplay = false;
+
+        mBuilder.build();
+
+        freezeRotation(Surface.ROTATION_180);
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+        assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+        verify(mMockDisplayWindowSettings).setUserRotation(mMockDisplayContent,
+                WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_180);
+    }
+
+    @Test
+    public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception {
+        mBuilder.build();
+
+        thawRotation();
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+        assertEquals(1, Settings.System.getInt(mMockResolver,
+                Settings.System.ACCELEROMETER_ROTATION));
+    }
+
+    @Test
+    public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
+        mBuilder.mIsDefaultDisplay = false;
+
+        mBuilder.build();
+
+        thawRotation();
+
+        assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+        verify(mMockDisplayWindowSettings).setUserRotation(same(mMockDisplayContent),
+                eq(WindowManagerPolicy.USER_ROTATION_FREE), anyInt());
+    }
+
+    @Test
+    public void testPersistsFixedToUserRotation() throws Exception {
+        mBuilder.build();
+
+        mTarget.setFixedToUserRotation(true);
+
+        verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+
+        reset(mMockDisplayWindowSettings);
+        mTarget.setFixedToUserRotation(false);
+
+        verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+    }
+
+    // ========================================
+    // Tests for User Rotation based Rotation
+    // ========================================
+    @Test
+    public void testReturnsUserRotation_UserRotationLocked_NoAppRequest()
+            throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        freezeRotation(Surface.ROTATION_180);
+
+        assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+    }
+
+    @Test
+    public void testReturnsUserRotation_UserRotationLocked_CompatibleAppRequest()
+            throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        freezeRotation(Surface.ROTATION_180);
+
+        assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90));
+    }
+
+    @Test
+    public void testReturnsSidesays_UserRotationLocked_IncompatibleAppRequest()
+            throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        freezeRotation(Surface.ROTATION_180);
+
+        final int rotation = mTarget.rotationForOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_90);
+        assertTrue("Rotation should be sideways, but it's "
+                        + Surface.rotationToString(rotation),
+                rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+    }
+
+    // =================================
+    // Tests for Sensor based Rotation
+    // =================================
+    private void verifyOrientationListenerRegistration(int numOfInvocation) {
+        final ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(
+                SensorEventListener.class);
+        verify(mMockSensorManager, times(numOfInvocation)).registerListener(
+                listenerCaptor.capture(),
+                same(mFakeSensor),
+                anyInt(),
+                any());
+        if (numOfInvocation > 0) {
+            mOrientationSensorListener = listenerCaptor.getValue();
+        }
+    }
+
+    @Test
+    public void testNotEnablesSensor_AutoRotationNotSupported() throws Exception {
+        mBuilder.setSupportAutoRotation(false).build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_ScreenNotOn() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(false);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_NotAwake() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(false);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_KeyguardNotDrawnCompletely() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(false);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_WindowManagerNotDrawnCompletely() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(false);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_FixedUserRotation() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.setFixedToUserRotation(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
+        mBuilder.build();
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+                .thenReturn(true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
+        mBuilder.build();
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+                .thenReturn(true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    @Test
+    public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
+        mBuilder.build();
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+                .thenReturn(true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(0);
+    }
+
+    private void enableOrientationSensor() {
+        when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+        when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+        when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+        when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+        mTarget.updateOrientationListener();
+        verifyOrientationListenerRegistration(1);
+    }
+
+    private SensorEvent createSensorEvent(int rotation) throws Exception {
+        final Constructor<SensorEvent> constructor =
+                SensorEvent.class.getDeclaredConstructor(int.class);
+        constructor.setAccessible(true);
+        final SensorEvent event = constructor.newInstance(1);
+        event.sensor = mFakeSensor;
+        event.values[0] = rotation;
+        event.timestamp = SystemClock.elapsedRealtimeNanos();
+        return event;
+    }
+
+    @Test
+    public void testReturnsSensorRotation_RotationThawed() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+
+        assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+                SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+    }
+
+    private boolean waitForUiHandler() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        UiThread.getHandler().post(latch::countDown);
+        return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+    }
+
+    @Test
+    public void testUpdatesRotationWhenSensorUpdates_RotationThawed() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+        assertTrue(waitForUiHandler());
+
+        verify(mMockWm).updateRotation(false, false);
+    }
+
+    @Test
+    public void testNotifiesChoiceWhenSensorUpdates_RotationLocked() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        freezeRotation(Surface.ROTATION_270);
+
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+        assertTrue(waitForUiHandler());
+
+        verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true);
+    }
+
+    @Test
+    public void testReturnsCompatibleRotation_SensorEnabled_RotationThawed() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        thawRotation();
+
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+        final int rotation = mTarget.rotationForOrientation(SCREEN_ORIENTATION_LANDSCAPE,
+                Surface.ROTATION_0);
+        assertTrue("Rotation should be sideways but it's "
+                + Surface.rotationToString(rotation),
+                rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+    }
+
+    @Test
+    public void testReturnsUserRotation_SensorEnabled_RotationLocked() throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        freezeRotation(Surface.ROTATION_270);
+
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+        assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+                SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+    }
+
+    // =================================
+    // Tests for Policy based Rotation
+    // =================================
+    @Test
+    public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
+        mBuilder.build();
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+                .thenReturn(true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+                Surface.ROTATION_180));
+    }
+
+    @Test
+    public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
+        mBuilder.build();
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+                .thenReturn(true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+        assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+                Surface.ROTATION_180));
+    }
+
+    @Test
+    public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
+        mBuilder.build();
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+                .thenReturn(true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+        assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+                Surface.ROTATION_180));
+    }
+
+    @Test
+    public void testReturnsLidOpenRotation_LidOpen() throws Exception {
+        mBuilder.setLidOpenRotation(Surface.ROTATION_90).build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        when(mMockDisplayPolicy.getLidState()).thenReturn(
+                WindowManagerPolicy.WindowManagerFuncs.LID_OPEN);
+
+        freezeRotation(Surface.ROTATION_270);
+
+        assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+                SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+    }
+
+    @Test
+    public void testReturnsCarDockRotation_CarDockedMode() throws Exception {
+        mBuilder.setCarDockRotation(Surface.ROTATION_270).build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_CAR);
+
+        freezeRotation(Surface.ROTATION_90);
+
+        assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+                SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+    }
+
+    @Test
+    public void testReturnsDeskDockRotation_DeskDockedMode() throws Exception {
+        mBuilder.setDeskDockRotation(Surface.ROTATION_270).build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK);
+
+        freezeRotation(Surface.ROTATION_90);
+
+        assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+                SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+    }
+
+    @Test
+    public void testReturnsUserRotation_FixedToUserRotation_IgnoreIncompatibleAppRequest()
+            throws Exception {
+        mBuilder.build();
+        configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+        mTarget.setFixedToUserRotation(true);
+
+        freezeRotation(Surface.ROTATION_180);
+
+        final int rotation = mTarget.rotationForOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90);
+        assertEquals(Surface.ROTATION_180, rotation);
+    }
+
+    @Test
+    public void testReturnsUserRotation_NonDefaultDisplay() throws Exception {
+        mBuilder.setIsDefaultDisplay(false).build();
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+        freezeRotation(Surface.ROTATION_90);
+
+        assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+                SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+    }
+
+    /**
+     * Call {@link DisplayRotation#configure(int, int, int, int)} to configure {@link #mTarget}
+     * according to given parameters.
+     */
+    private void configureDisplayRotation(int displayOrientation, boolean isCar, boolean isTv) {
+        final int width;
+        final int height;
+        switch (displayOrientation) {
+            case SCREEN_ORIENTATION_LANDSCAPE:
+                width = 1920;
+                height = 1080;
+                break;
+            case SCREEN_ORIENTATION_PORTRAIT:
+                width = 1080;
+                height = 1920;
+                break;
+            default:
+                throw new IllegalArgumentException("displayOrientation needs to be either landscape"
+                        + " or portrait, but we got "
+                        + ActivityInfo.screenOrientationToString(displayOrientation));
+        }
+
+        final PackageManager mockPackageManager = mock(PackageManager.class);
+        when(mMockContext.getPackageManager()).thenReturn(mockPackageManager);
+        when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+                .thenReturn(isCar);
+        when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+                .thenReturn(isTv);
+
+        final int shortSizeDp = (isCar || isTv) ? 540 : 720;
+        final int longSizeDp = 960;
+        mTarget.configure(width, height, shortSizeDp, longSizeDp);
+    }
+
+    private void freezeRotation(int rotation) {
+        mTarget.freezeRotation(rotation);
+
+        if (mTarget.isDefaultDisplay) {
+            mAccelerometerRotationObserver.onChange(false);
+            mUserRotationObserver.onChange(false);
+        }
+    }
+
+    private void thawRotation() {
+        mTarget.thawRotation();
+
+        if (mTarget.isDefaultDisplay) {
+            mAccelerometerRotationObserver.onChange(false);
+            mUserRotationObserver.onChange(false);
+        }
+    }
+
+    private class DisplayRotationBuilder {
+        private boolean mIsDefaultDisplay = true;
+        private boolean mSupportAutoRotation = true;
+
+        private int mLidOpenRotation = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+        private int mCarDockRotation;
+        private int mDeskDockRotation;
+        private int mUndockedHdmiRotation;
+
+        private DisplayRotationBuilder setIsDefaultDisplay(boolean isDefaultDisplay) {
+            mIsDefaultDisplay = isDefaultDisplay;
+            return this;
+        }
+
+        private DisplayRotationBuilder setSupportAutoRotation(boolean supportAutoRotation) {
+            mSupportAutoRotation = supportAutoRotation;
+            return this;
+        }
+
+        private DisplayRotationBuilder setLidOpenRotation(int rotation) {
+            mLidOpenRotation = rotation;
+            return this;
+        }
+
+        private DisplayRotationBuilder setCarDockRotation(int rotation) {
+            mCarDockRotation = rotation;
+            return this;
+        }
+
+        private DisplayRotationBuilder setDeskDockRotation(int rotation) {
+            mDeskDockRotation = rotation;
+            return this;
+        }
+
+        private DisplayRotationBuilder setUndockedHdmiRotation(int rotation) {
+            mUndockedHdmiRotation = rotation;
+            return this;
+        }
+
+        private void captureObservers() {
+            ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(
+                    ContentObserver.class);
+            verify(mMockResolver, atMost(1)).registerContentObserver(
+                    eq(Settings.Secure.getUriFor(Settings.Secure.SHOW_ROTATION_SUGGESTIONS)),
+                    anyBoolean(),
+                    captor.capture(),
+                    anyInt());
+            if (!captor.getAllValues().isEmpty()) {
+                mShowRotationSuggestionsObserver = captor.getValue();
+            }
+
+            captor = ArgumentCaptor.forClass(ContentObserver.class);
+            verify(mMockResolver, atMost(1)).registerContentObserver(
+                    eq(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION)),
+                    anyBoolean(),
+                    captor.capture(),
+                    anyInt());
+            if (!captor.getAllValues().isEmpty()) {
+                mAccelerometerRotationObserver = captor.getValue();
+            }
+
+            captor = ArgumentCaptor.forClass(ContentObserver.class);
+            verify(mMockResolver, atMost(1)).registerContentObserver(
+                    eq(Settings.System.getUriFor(Settings.System.USER_ROTATION)),
+                    anyBoolean(),
+                    captor.capture(),
+                    anyInt());
+            if (!captor.getAllValues().isEmpty()) {
+                mUserRotationObserver = captor.getValue();
+            }
+        }
+
+        private Sensor createSensor(int type) throws Exception {
+            Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+            constr.setAccessible(true);
+            Sensor sensor = constr.newInstance();
+
+            setSensorType(sensor, type);
+            setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
+            setSensorField(sensor, "mVendor", "Mock Vendor");
+            setSensorField(sensor, "mVersion", 1);
+            setSensorField(sensor, "mHandle", -1);
+            setSensorField(sensor, "mMaxRange", 10);
+            setSensorField(sensor, "mResolution", 1);
+            setSensorField(sensor, "mPower", 1);
+            setSensorField(sensor, "mMinDelay", 1000);
+            setSensorField(sensor, "mMaxDelay", 1000000000);
+            setSensorField(sensor, "mFlags", 0);
+            setSensorField(sensor, "mId", -1);
+
+            return sensor;
+        }
+
+        private void setSensorType(Sensor sensor, int type) throws Exception {
+            Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+            setter.setAccessible(true);
+            setter.invoke(sensor, type);
+        }
+
+        private void setSensorField(Sensor sensor, String fieldName, Object value)
+                throws Exception {
+            Field field = Sensor.class.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            field.set(sensor, value);
+        }
+
+        private int convertRotationToDegrees(@Surface.Rotation int rotation) {
+            switch (rotation) {
+                case Surface.ROTATION_0:
+                    return 0;
+                case Surface.ROTATION_90:
+                    return 90;
+                case Surface.ROTATION_180:
+                    return 180;
+                case Surface.ROTATION_270:
+                    return 270;
+                default:
+                    return -1;
+            }
+        }
+
+        private void build() throws Exception {
+            mMockContext = mock(Context.class);
+
+            mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class);
+            mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
+
+            mMockDisplayPolicy = mock(DisplayPolicy.class);
+
+            mMockRes = mock(Resources.class);
+            when(mMockContext.getResources()).thenReturn((mMockRes));
+            when(mMockRes.getBoolean(com.android.internal.R.bool.config_supportAutoRotation))
+                    .thenReturn(mSupportAutoRotation);
+            when(mMockRes.getInteger(com.android.internal.R.integer.config_lidOpenRotation))
+                    .thenReturn(convertRotationToDegrees(mLidOpenRotation));
+            when(mMockRes.getInteger(com.android.internal.R.integer.config_carDockRotation))
+                    .thenReturn(convertRotationToDegrees(mCarDockRotation));
+            when(mMockRes.getInteger(com.android.internal.R.integer.config_deskDockRotation))
+                    .thenReturn(convertRotationToDegrees(mDeskDockRotation));
+            when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
+                    .thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
+
+            mMockSensorManager = mock(SensorManager.class);
+            when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
+                    .thenReturn(mMockSensorManager);
+            mFakeSensor = createSensor(Sensor.TYPE_DEVICE_ORIENTATION);
+            when(mMockSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION)).thenReturn(
+                    Collections.singletonList(mFakeSensor));
+
+            mMockResolver = mock(ContentResolver.class);
+            when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
+            mFakeSettingsProvider = new FakeSettingsProvider();
+            when(mMockResolver.acquireProvider(Settings.AUTHORITY))
+                    .thenReturn(mFakeSettingsProvider.getIContentProvider());
+
+            mMockDisplayWindowSettings = mock(DisplayWindowSettings.class);
+            mTarget = new DisplayRotation(mMockWm, mMockDisplayContent, mMockDisplayPolicy,
+                    mMockDisplayWindowSettings, mMockContext, new Object());
+
+            captureObservers();
+        }
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 2c3c66b..f3a125b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -272,6 +272,51 @@
     }
 
     @Test
+    public void testClearsRecordInMemory() {
+        mTarget.saveTask(mTestTask);
+
+        mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+        mTarget.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testClearsWriteQueueItem() {
+        mTarget.saveTask(mTestTask);
+
+        mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+        final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+                mUserFolderGetter);
+        target.onSystemReady();
+        target.onUnlockUser(TEST_USER_ID);
+
+        target.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testClearsFile() {
+        mTarget.saveTask(mTestTask);
+        mPersisterQueue.flush();
+
+        mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+        final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+                mUserFolderGetter);
+        target.onSystemReady();
+        target.onUnlockUser(TEST_USER_ID);
+
+        target.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+
+    @Test
     public void testClearsRecordInMemoryOnPackageUninstalled() {
         mTarget.saveTask(mTestTask);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index e56edab..3c87721 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -65,7 +65,7 @@
 
             final DisplayRotation displayRotation = new DisplayRotation(
                     mock(WindowManagerService.class), displayContent, displayPolicy,
-                    context, new Object());
+                    mock(DisplayWindowSettings.class), context, new Object());
             displayRotation.mPortraitRotation = Surface.ROTATION_0;
             displayRotation.mLandscapeRotation = Surface.ROTATION_90;
             displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 34a8c96..45cfe1e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -569,14 +569,6 @@
     public static final String IS_OPPORTUNISTIC = "is_opportunistic";
 
     /**
-     * TelephonyProvider column name for subId of parent subscription of an opportunistic
-     * subscription.
-     * if the parent sub id is valid, then is_opportunistic should always to true.
-     * @hide
-     */
-    public static final String PARENT_SUB_ID = "parent_sub_id";
-
-    /**
      * TelephonyProvider column name for group ID. Subscriptions with same group ID
      * are considered bundled together, and should behave as a single subscription at
      * certain scenarios.
diff --git a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
index ae3914e..d5987a5 100644
--- a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
+++ b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
@@ -26,6 +26,7 @@
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.IWindowSession;
+import android.view.InsetsState;
 import android.view.Surface;
 import android.view.View;
 import android.view.WindowManager;
@@ -105,7 +106,7 @@
                                 window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, -1, mTmpRect,
                                 mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
                                 new DisplayCutout.ParcelableWrapper(), new MergedConfiguration(),
-                                new Surface());
+                                new Surface(), new InsetsState());
                     } catch (RemoteException e) {
                         e.printStackTrace();
                     }
@@ -131,8 +132,9 @@
             final IWindowSession session = WindowManagerGlobal.getWindowSession();
             final Rect tmpRect = new Rect();
             try {
-                final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq, layoutParams,
-                        View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect);
+                final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq,
+                        layoutParams, View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect,
+                        new InsetsState());
             } catch (RemoteException e) {
                 e.printStackTrace();
             }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 3ec8a41..364d5084 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -58,7 +58,7 @@
      */
     oneway void requestActivityInfo(in ResultReceiver result);
 
-    ParceledListSlice getConfiguredNetworks();
+    ParceledListSlice getConfiguredNetworks(String packageName);
 
     ParceledListSlice getPrivilegedConfiguredNetworks();
 
@@ -90,11 +90,11 @@
 
     List<ScanResult> getScanResults(String callingPackage);
 
-    void disconnect(String packageName);
+    boolean disconnect(String packageName);
 
-    void reconnect(String packageName);
+    boolean reconnect(String packageName);
 
-    void reassociate(String packageName);
+    boolean reassociate(String packageName);
 
     WifiInfo getConnectionInfo(String callingPackage);
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7aff03c..8dd6c77 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1067,7 +1067,7 @@
     public List<WifiConfiguration> getConfiguredNetworks() {
         try {
             ParceledListSlice<WifiConfiguration> parceledList =
-                mService.getConfiguredNetworks();
+                    mService.getConfiguredNetworks(mContext.getOpPackageName());
             if (parceledList == null) {
                 return Collections.emptyList();
             }
@@ -1761,8 +1761,7 @@
     @Deprecated
     public boolean disconnect() {
         try {
-            mService.disconnect(mContext.getOpPackageName());
-            return true;
+            return mService.disconnect(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1786,8 +1785,7 @@
     @Deprecated
     public boolean reconnect() {
         try {
-            mService.reconnect(mContext.getOpPackageName());
-            return true;
+            return mService.reconnect(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1811,8 +1809,7 @@
     @Deprecated
     public boolean reassociate() {
         try {
-            mService.reassociate(mContext.getOpPackageName());
-            return true;
+            return mService.reassociate(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2132,14 +2129,14 @@
      * existing networks. You should assume the network IDs can be different
      * after calling this method.
      *
-     * @return {@code false} Will always return true.
+     * @return {@code false}.
      * @deprecated There is no need to call this method -
      * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
      * and {@link #removeNetwork(int)} already persist the configurations automatically.
      */
     @Deprecated
     public boolean saveConfiguration() {
-        return true;
+        return false;
     }
 
     /**
@@ -3406,6 +3403,11 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK
+    })
     public void connect(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         // Use INVALID_NETWORK_ID for arg1 when passing a config object
@@ -3426,7 +3428,12 @@
      * initialized again
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK
+    })
     public void connect(int networkId, ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
@@ -3452,7 +3459,12 @@
      * initialized again
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK
+    })
     public void save(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
@@ -3471,7 +3483,12 @@
      * initialized again
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK
+    })
     public void forget(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
@@ -3486,7 +3503,12 @@
      * initialized again
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK
+    })
     public void disable(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
@@ -3498,6 +3520,12 @@
      * @param SSID, in the format of WifiConfiguration's SSID.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK
+    })
     public void disableEphemeralNetwork(String SSID) {
         if (SSID == null) throw new IllegalArgumentException("SSID cannot be null");
         try {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 529548f..6622a25 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -184,6 +184,9 @@
     public static final String SCAN_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
     /** {@hide} */
     public static final String SCAN_PARAMS_WORK_SOURCE_KEY = "WorkSource";
+    /** {@hide} */
+    public static final String REQUEST_PACKAGE_NAME_KEY = "PackageName";
+
     /**
      * scan configuration parameters to be sent to {@link #startBackgroundScan}
      */
@@ -798,6 +801,7 @@
         Bundle scanParams = new Bundle();
         scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
         scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
+        scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
         mAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, scanParams);
     }
 
@@ -812,8 +816,11 @@
         int key = removeListener(listener);
         if (key == INVALID_KEY) return;
         validateChannel();
-        mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key);
+        Bundle scanParams = new Bundle();
+        scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+        mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key, scanParams);
     }
+
     /**
      * reports currently available scan results on appropriate listeners
      * @return true if all scan results were reported correctly
@@ -821,7 +828,10 @@
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public boolean getScanResults() {
         validateChannel();
-        Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
+        Bundle scanParams = new Bundle();
+        scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+        Message reply =
+                mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0, 0, scanParams);
         return reply.what == CMD_OP_SUCCEEDED;
     }
 
@@ -856,6 +866,7 @@
         Bundle scanParams = new Bundle();
         scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
         scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
+        scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
         mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
     }
 
@@ -870,7 +881,9 @@
         int key = removeListener(listener);
         if (key == INVALID_KEY) return;
         validateChannel();
-        mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
+        Bundle scanParams = new Bundle();
+        scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+        mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key, scanParams);
     }
 
     /**
@@ -879,7 +892,10 @@
      */
     public List<ScanResult> getSingleScanResults() {
         validateChannel();
-        Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0);
+        Bundle scanParams = new Bundle();
+        scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+        Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0, 0,
+                scanParams);
         if (reply.what == WifiScanner.CMD_OP_SUCCEEDED) {
             return Arrays.asList(((ParcelableScanResults) reply.obj).getResults());
         }
diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java
index 04bc557..aa526d2 100644
--- a/wifi/java/com/android/server/wifi/AbstractWifiService.java
+++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java
@@ -73,7 +73,7 @@
     }
 
     @Override
-    public ParceledListSlice getConfiguredNetworks() {
+    public ParceledListSlice getConfiguredNetworks(String packageName) {
         throw new UnsupportedOperationException();
     }
 
@@ -188,17 +188,17 @@
     }
 
     @Override
-    public void disconnect(String packageName) {
+    public boolean disconnect(String packageName) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public void reconnect(String packageName) {
+    public boolean reconnect(String packageName) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public void reassociate(String packageName) {
+    public boolean reassociate(String packageName) {
         throw new UnsupportedOperationException();
     }