Merge "Injecting system calls into alarm manager"
diff --git a/Android.bp b/Android.bp
index dd49a67..2ab91a1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -381,6 +381,7 @@
         "core/java/com/android/internal/backup/IBackupTransport.aidl",
         "core/java/com/android/internal/backup/IObbBackupService.aidl",
         "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
+        "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
         "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
         "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
         "core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
@@ -554,6 +555,7 @@
         "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
         "telephony/java/com/android/internal/telephony/ISms.aidl",
         "telephony/java/com/android/internal/telephony/ISub.aidl",
+        "telephony/java/com/android/internal/telephony/IAnas.aidl",
         "telephony/java/com/android/internal/telephony/ITelephony.aidl",
         "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
         "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index 66a2600d..d8d4a6e 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -23,8 +23,7 @@
 
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal.CallSession;
-
-import java.util.Random;
+import com.android.internal.os.CachedDeviceState;
 
 import org.junit.After;
 import org.junit.Before;
@@ -32,8 +31,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static org.junit.Assert.assertNull;
-
 
 /**
  * Performance tests for {@link BinderCallsStats}
@@ -49,6 +46,8 @@
     @Before
     public void setUp() {
         mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
+        CachedDeviceState deviceState = new CachedDeviceState(false, false);
+        mBinderCallsStats.setDeviceState(deviceState.getReadonlyClient());
     }
 
     @After
diff --git a/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java
new file mode 100644
index 0000000..0f880b7
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/LooperStatsPerfTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.os;
+
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.os.LooperStats;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Performance tests for {@link LooperStats}.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class LooperStatsPerfTest {
+    private static final int DISTINCT_MESSAGE_COUNT = 1000;
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+    private LooperStats mStats;
+    private CachedDeviceState mDeviceState;
+    private HandlerThread mThread;
+    private Message[] mMessages = new Message[DISTINCT_MESSAGE_COUNT];
+
+    @Before
+    public void setUp() {
+        mStats = new LooperStats(1, DISTINCT_MESSAGE_COUNT - 1);
+        mDeviceState = new CachedDeviceState(false, false);
+        mStats.setDeviceState(mDeviceState.getReadonlyClient());
+        // The tests are all single-threaded. HandlerThread is created to allow creating Handlers.
+        mThread = new HandlerThread("UnusedThread");
+        mThread.start();
+        for (int i = 0; i < DISTINCT_MESSAGE_COUNT; i++) {
+            mMessages[i] = mThread.getThreadHandler().obtainMessage(i);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        mThread.quit();
+    }
+
+    @Test
+    public void timeHundredPercentSampling() {
+        mStats.setSamplingInterval(1);
+        runScenario();
+    }
+
+    @Test
+    public void timeOnePercentSampling() {
+        mStats.setSamplingInterval(100);
+        runScenario();
+    }
+
+    @Test
+    public void timeCollectionDisabled() {
+        // We do not collect data on charger.
+        mDeviceState.setCharging(true);
+        runScenario();
+    }
+
+    private void runScenario() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < DISTINCT_MESSAGE_COUNT; i++) {
+                Object token = mStats.messageDispatchStarting();
+                mStats.messageDispatched(token, mMessages[i]);
+            }
+        }
+    }
+}
diff --git a/api/current.txt b/api/current.txt
index 8bdafa9..7389855 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -13986,6 +13986,8 @@
     method public float getRunAdvance(char[], int, int, int, int, boolean, int);
     method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
     method public android.graphics.Shader getShader();
+    method public float getStrikeThruPosition();
+    method public float getStrikeThruThickness();
     method public android.graphics.Paint.Cap getStrokeCap();
     method public android.graphics.Paint.Join getStrokeJoin();
     method public float getStrokeMiter();
@@ -14006,6 +14008,9 @@
     method public int getTextWidths(java.lang.String, int, int, float[]);
     method public int getTextWidths(java.lang.String, float[]);
     method public android.graphics.Typeface getTypeface();
+    method public float getUnderlinePosition();
+    method public float getUnderlineThickness();
+    method public float getWordSpacing();
     method public android.graphics.Xfermode getXfermode();
     method public boolean hasGlyph(java.lang.String);
     method public final boolean isAntiAlias();
@@ -14057,6 +14062,7 @@
     method public void setTextSkewX(float);
     method public android.graphics.Typeface setTypeface(android.graphics.Typeface);
     method public void setUnderlineText(boolean);
+    method public void setWordSpacing(float);
     method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
     field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
     field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
@@ -42617,6 +42623,7 @@
     method public static int getDefaultSmsSubscriptionId();
     method public static int getDefaultSubscriptionId();
     method public static int getDefaultVoiceSubscriptionId();
+    method public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
     method public boolean isNetworkRoaming(int);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
@@ -45986,6 +45993,7 @@
     method public float getDimension(android.util.DisplayMetrics);
     method public final float getFloat();
     method public float getFraction(float, float);
+    method public boolean isColorType();
     method public void setTo(android.util.TypedValue);
     field public static final int COMPLEX_MANTISSA_MASK = 16777215; // 0xffffff
     field public static final int COMPLEX_MANTISSA_SHIFT = 8; // 0x8
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 02719e3f8..45e38cf 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -152,8 +152,8 @@
 Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V
 Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V
 Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V
-Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;Landroid/view/InputChannel;)V
-Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;)Z
+Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;ILandroid/view/InputChannel;)V
+Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;I)Z
 Landroid/view/IWindowManager;->endProlongedAnimations()V
 Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V
 Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;Z)V
diff --git a/core/java/android/accessibilityservice/TEST_MAPPING b/core/java/android/accessibilityservice/TEST_MAPPING
new file mode 100644
index 0000000..c7c4c3a
--- /dev/null
+++ b/core/java/android/accessibilityservice/TEST_MAPPING
@@ -0,0 +1,23 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    },
+    {
+      "name": "CtsAccessibilityTestCases"
+    }
+  ]
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1108f93..225b6cf 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -615,6 +615,13 @@
     public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
 
     /**
+     * Value for {@link #privateFlags}: whether this app is signed with the
+     * platform key.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+
+    /**
      * Value for {@link #privateFlags}: whether this app is pre-installed on the
      * google partition of the system image.
      * @hide
@@ -622,11 +629,11 @@
     public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
 
     /**
-     * Value for {@link #privateFlags}: whether this app is signed with the
-     * platform key.
+     * Indicates whether this package requires access to non-SDK APIs.
+     * Only system apps and tests are allowed to use this property.
      * @hide
      */
-    public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+    public static final int PRIVATE_FLAG_USES_NON_SDK_API = 1 << 22;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
@@ -1009,13 +1016,6 @@
     public String appComponentFactory;
 
     /**
-     * Indicates whether this package requires access to non-SDK APIs. Only system apps
-     * and tests are allowed to use this property.
-     * @hide
-     */
-    public boolean usesNonSdkApi;
-
-    /**
      * The category of this app. Categories are used to cluster multiple apps
      * together into meaningful groups, such as when summarizing battery,
      * network, or disk usage. Apps should only define this value when they fit
@@ -1294,6 +1294,7 @@
                 pw.println(prefix + "category=" + category);
             }
             pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
+            pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
         }
         super.dumpBack(pw, prefix);
     }
@@ -1718,11 +1719,18 @@
         return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
     }
 
+    /**
+     * @hide
+     */
+    public boolean usesNonSdkApi() {
+        return (privateFlags & PRIVATE_FLAG_USES_NON_SDK_API) != 0;
+    }
+
     private boolean isAllowedToUseHiddenApis() {
         if (isSignedWithPlatformKey()) {
             return true;
         } else if (isSystemApp() || isUpdatedSystemApp()) {
-            return usesNonSdkApi || isPackageWhitelistedForHiddenApis();
+            return usesNonSdkApi() || isPackageWhitelistedForHiddenApis();
         } else {
             return false;
         }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8b058dc..6d49362 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3659,8 +3659,10 @@
             ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
         }
 
-        ai.usesNonSdkApi = sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false);
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestApplication_usesNonSdkApi, false)) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
+        }
 
         if (outError[0] == null) {
             CharSequence pname;
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 2c7e51a..00a1f6f 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -35,6 +35,7 @@
 import android.view.inputmethod.InputMethodSession;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputContext;
@@ -60,7 +61,7 @@
     private static final String TAG = "InputMethodWrapper";
 
     private static final int DO_DUMP = 1;
-    private static final int DO_ATTACH_TOKEN = 10;
+    private static final int DO_INITIALIZE_INTERNAL = 10;
     private static final int DO_SET_INPUT_CONTEXT = 20;
     private static final int DO_UNSET_INPUT_CONTEXT = 30;
     private static final int DO_START_INPUT = 32;
@@ -159,9 +160,15 @@
                 args.recycle();
                 return;
             }
-            
-            case DO_ATTACH_TOKEN: {
-                inputMethod.attachToken((IBinder)msg.obj);
+
+            case DO_INITIALIZE_INTERNAL: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                try {
+                    inputMethod.initializeInternal((IBinder) args.arg1,
+                            (IInputMethodPrivilegedOperations) args.arg2);
+                } finally {
+                    args.recycle();
+                }
                 return;
             }
             case DO_SET_INPUT_CONTEXT: {
@@ -246,8 +253,9 @@
 
     @BinderThread
     @Override
-    public void attachToken(IBinder token) {
-        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
+    public void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageOO(DO_INITIALIZE_INTERNAL, token, privOps));
     }
 
     @BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 9295bb7..ea7d42e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -42,6 +42,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -79,6 +80,9 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -342,7 +346,8 @@
     private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING;
 
     InputMethodManager mImm;
-    
+    private IInputMethodPrivilegedOperations mPrivOps;
+
     @UnsupportedAppUsage
     int mTheme = 0;
     
@@ -446,14 +451,32 @@
     public class InputMethodImpl extends AbstractInputMethodImpl {
         /**
          * {@inheritDoc}
+         * @hide
+         */
+        @MainThread
+        @Override
+        public final void initializeInternal(IBinder token,
+                IInputMethodPrivilegedOperations privilegedOperations) {
+            if (mToken != null) {
+                throw new IllegalStateException("initializeInternal() must be called at most once."
+                        + " privOps=" + privilegedOperations);
+            }
+            mPrivOps = privilegedOperations;
+            attachToken(token);
+        }
+
+        /**
+         * {@inheritDoc}
          */
         @MainThread
         @Override
         public void attachToken(IBinder token) {
-            if (mToken == null) {
-                mToken = token;
-                mWindow.setToken(token);
+            if (mToken != null) {
+                throw new IllegalStateException(
+                        "attachToken() must be called at most once. token=" + token);
             }
+            mToken = token;
+            mWindow.setToken(token);
         }
 
         /**
@@ -468,9 +491,7 @@
             mInputConnection = binding.getConnection();
             if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
                     + " ic=" + mInputConnection);
-            if (mImm != null && mToken != null) {
-                mImm.reportFullscreenMode(mToken, mIsFullscreen);
-            }
+            reportFullscreenMode();
             initialize();
             onBindInput();
         }
@@ -519,7 +540,11 @@
         public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
                 @NonNull EditorInfo editorInfo, boolean restarting,
                 @NonNull IBinder startInputToken) {
-            mImm.reportStartInput(mToken, startInputToken);
+            try {
+                mPrivOps.reportStartInput(startInputToken);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
 
             // This needs to be dispatched to interface methods rather than doStartInput().
             // Otherwise IME developers who have overridden those interface methods will lose
@@ -561,8 +586,8 @@
             }
             clearInsetOfPreviousIme();
             // If user uses hard keyboard, IME button should always be shown.
-            mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()),
-                    mBackDisposition);
+            setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+
             if (resultReceiver != null) {
                 resultReceiver.send(wasVis != isInputViewShown()
                         ? InputMethodManager.RESULT_SHOWN
@@ -581,6 +606,17 @@
         }
     }
 
+    private void setImeWindowStatus(int visibilityFlags, int backDisposition) {
+        if (mPrivOps == null) {
+            return;
+        }
+        try {
+            mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /**
      * Concrete implementation of
      * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
@@ -1037,8 +1073,7 @@
             }
             // If user uses hard keyboard, IME button should always be shown.
             boolean showing = onEvaluateInputViewShown();
-            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
-                    mBackDisposition);
+            setImeWindowStatus(IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition);
         }
     }
 
@@ -1088,7 +1123,7 @@
             return;
         }
         mBackDisposition = disposition;
-        mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+        setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
     }
 
     /**
@@ -1186,7 +1221,18 @@
     public EditorInfo getCurrentInputEditorInfo() {
         return mInputEditorInfo;
     }
-    
+
+    private void reportFullscreenMode() {
+        if (mPrivOps == null) {
+            return;
+        }
+        try {
+            mPrivOps.reportFullscreenMode(mIsFullscreen);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /**
      * Re-evaluate whether the input method should be running in fullscreen
      * mode, and update its UI if this has changed since the last time it
@@ -1201,9 +1247,7 @@
         if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
             changed = true;
             mIsFullscreen = isFullscreen;
-            if (mImm != null && mToken != null) {
-                mImm.reportFullscreenMode(mToken, mIsFullscreen);
-            }
+            reportFullscreenMode();
             mFullscreenApplied = true;
             initialize();
             LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
@@ -1821,7 +1865,7 @@
 
         final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());
         if (previousImeWindowStatus != nextImeWindowStatus) {
-            mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
+            setImeWindowStatus(nextImeWindowStatus, mBackDisposition);
         }
         if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
             if (DEBUG) Log.v(TAG, "showWindow: showing!");
@@ -1846,7 +1890,7 @@
     }
 
     private void doHideWindow() {
-        mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
+        setImeWindowStatus(0, mBackDisposition);
         hideWindow();
     }
 
@@ -1887,11 +1931,31 @@
                 + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
         if (!mShouldClearInsetOfPreviousIme) return;
 
-        mImm.clearLastInputMethodWindowForTransition(mToken);
+        clearLastInputMethodWindowForTransition();
         mShouldClearInsetOfPreviousIme = false;
     }
 
     /**
+     * Tells the system that the IME decided to not show a window and the system no longer needs to
+     * use the previous IME's inset.
+     *
+     * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
+     * is the only expected caller of this method.  Do not depend on this anywhere else.</p>
+     *
+     * <p>TODO: We probably need to reconsider how IME should be handled.</p>
+     */
+    private void clearLastInputMethodWindowForTransition() {
+        if (mPrivOps == null) {
+            return;
+        }
+        try {
+            mPrivOps.clearLastInputMethodWindowForTransition();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Called when a new client has bound to the input method.  This
      * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
      * and {@link #onFinishInput()} calls as the user navigates through its
@@ -2804,7 +2868,40 @@
         if (getCurrentInputConnection() != inputConnection) {
             return;
         }
-        mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo());
+        exposeContentInternal(inputContentInfo, getCurrentInputEditorInfo());
+    }
+
+    /**
+     * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+     * permission to the content.
+     *
+     * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
+     * InputConnection)} for details.</p>
+     *
+     * @param inputContentInfo Content to be temporarily exposed from the input method to the
+     * application.
+     * This cannot be {@code null}.
+     * @param editorInfo The editor that receives {@link InputContentInfo}.
+     */
+    private void exposeContentInternal(@NonNull InputContentInfo inputContentInfo,
+            @NonNull EditorInfo editorInfo) {
+        if (mPrivOps == null) {
+            return;
+        }
+        final IInputContentUriToken uriToken;
+        final Uri contentUri = inputContentInfo.getContentUri();
+        try {
+            uriToken = mPrivOps.createInputContentUriToken(contentUri, editorInfo.packageName);
+            if (uriToken == null) {
+                return;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
+                    + " packageName=" + editorInfo.packageName, e);
+            return;
+        }
+        inputContentInfo.setUriToken(uriToken);
+        return;
     }
 
     private static int mapToImeWindowStatus(boolean isInputViewShown) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 71938d2..e007398 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7256,6 +7256,14 @@
         private static final Validator DOZE_REACH_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
+         * Gesture that wakes up the display, showing the ambient version of the status bar.
+         * @hide
+         */
+        public static final String DOZE_WAKE_SCREEN_GESTURE = "doze_wake_screen_gesture";
+
+        private static final Validator DOZE_WAKE_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * The current night mode that has been selected by the user.  Owned
          * and controlled by UiModeManagerService.  Constants are as per
          * UiModeManager.
@@ -8158,6 +8166,7 @@
             DOZE_PICK_UP_GESTURE,
             DOZE_DOUBLE_TAP_GESTURE,
             DOZE_REACH_GESTURE,
+            DOZE_WAKE_SCREEN_GESTURE,
             NFC_PAYMENT_DEFAULT_COMPONENT,
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
             FACE_UNLOCK_KEYGUARD_ENABLED,
@@ -8302,6 +8311,7 @@
             VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_REACH_GESTURE, DOZE_REACH_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
             VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
             VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
                     AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
@@ -13310,6 +13320,19 @@
         public static final String BINDER_CALLS_STATS = "binder_calls_stats";
 
         /**
+         * Looper stats settings.
+         *
+         * The following strings are supported as keys:
+         * <pre>
+         *     enabled              (boolean)
+         *     sampling_interval    (int)
+         * </pre>
+         *
+         * @hide
+         */
+        public static final String LOOPER_STATS = "looper_stats";
+
+        /**
          * Default user id to boot into. They map to user ids, for example, 10, 11, 12.
          *
          * @hide
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 2c9bb66..9640173 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -232,6 +232,16 @@
     };
 
     /**
+     * Determine if a value is a color by comparing {@link type} to {@link #TYPE_FIRST_COLOR_INT}
+     * and {@link #TYPE_LAST_COLOR_INT}.
+     *
+     * @return true if this value is a color
+     */
+    public boolean isColorType() {
+        return (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT);
+    }
+
+    /**
      * Retrieve the base value from a complex data integer.  This uses the 
      * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of 
      * the data to compute a floating point representation of the number they 
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c205af0..bfe1e95 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -391,15 +391,16 @@
     void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber);
 
     /**
-     * Create an input consumer by name.
+     * Create an input consumer by name and display id.
      */
-    void createInputConsumer(IBinder token, String name, out InputChannel inputChannel);
+    void createInputConsumer(IBinder token, String name, int displayId,
+        out InputChannel inputChannel);
 
     /**
-     * Destroy an input consumer by name.  This method will also dispose the input channels
-     * associated with that InputConsumer.
+     * Destroy an input consumer by name and display id.
+     * This method will also dispose the input channels associated with that InputConsumer.
      */
-    boolean destroyInputConsumer(String name);
+    boolean destroyInputConsumer(String name, int displayId);
 
     /**
      * Return the touch region for the current IME window, or an empty region if there is none.
diff --git a/core/java/android/view/accessibility/TEST_MAPPING b/core/java/android/view/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..d2bd6ea
--- /dev/null
+++ b/core/java/android/view/accessibility/TEST_MAPPING
@@ -0,0 +1,53 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsUiAutomationTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    },
+    {
+      "name": "CtsUiAutomationTestCases"
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        }
+      ]
+    }
+  ]
+}
diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java
index 7104a28..0d0fea6 100644
--- a/core/java/android/view/inputmethod/InputContentInfo.java
+++ b/core/java/android/view/inputmethod/InputContentInfo.java
@@ -183,7 +183,15 @@
     @Nullable
     public Uri getLinkUri() { return mLinkUri; }
 
-    void setUriToken(IInputContentUriToken token) {
+    /**
+     * Update the internal state of this object to be associated with the given token.
+     *
+     * <p>TODO(yukawa): Come up with an idea to make {@link InputContentInfo} immutable.</p>
+     *
+     * @param token special URI token obtained from the system.
+     * @hide
+     */
+    public void setUriToken(IInputContentUriToken token) {
         if (mUriToken != null) {
             throw new IllegalStateException("URI token is already set");
         }
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index ab8886b..f45507c 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -25,6 +25,8 @@
 import android.os.IBinder;
 import android.os.ResultReceiver;
 
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+
 /**
  * The InputMethod interface represents an input method which can generate key
  * events and text, such as digital, email addresses, CJK characters, other
@@ -79,17 +81,35 @@
     public interface SessionCallback {
         public void sessionCreated(InputMethodSession session);
     }
-    
+
+    /**
+     * Called first thing after an input method is created, this supplies a
+     * unique token for the session it has with the system service as well as
+     * IPC endpoint to do some other privileged operations.
+     *
+     * @param token special token for the system to identify
+     *              {@link InputMethodService}
+     * @param privilegedOperations IPC endpoint to do some privileged
+     *                             operations that are allowed only to the
+     *                             current IME.
+     * @hide
+     */
+    @MainThread
+    default void initializeInternal(IBinder token,
+            IInputMethodPrivilegedOperations privilegedOperations) {
+        attachToken(token);
+    }
+
     /**
      * Called first thing after an input method is created, this supplies a
      * unique token for the session it has with the system service.  It is
      * needed to identify itself with the service to validate its operations.
      * This token <strong>must not</strong> be passed to applications, since
      * it grants special priviledges that should not be given to applications.
-     * 
-     * <p>Note: to protect yourself from malicious clients, you should only
-     * accept the first token given to you.  Any after that may come from the
-     * client.
+     *
+     * <p>The system guarantees that this method is called back between
+     * {@link InputMethodService#onCreate()} and {@link InputMethodService#onDestroy()}
+     * at most once.
      */
     @MainThread
     public void attachToken(IBinder token);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d3fd0cf..baac4cd 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -29,7 +29,6 @@
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -56,7 +55,6 @@
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
 import android.view.autofill.AutofillManager;
 
-import com.android.internal.inputmethod.IInputContentUriToken;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.view.IInputConnectionWrapper;
 import com.android.internal.view.IInputContext;
@@ -810,24 +808,6 @@
     }
 
     /** @hide */
-    public void setImeWindowStatus(IBinder imeToken, int vis, int backDisposition) {
-        try {
-            mService.setImeWindowStatus(imeToken, vis, backDisposition);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** @hide */
-    public void reportStartInput(IBinder imeToken, IBinder startInputToken) {
-        try {
-            mService.reportStartInput(imeToken, startInputToken);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** @hide */
     @UnsupportedAppUsage
     public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
         try {
@@ -859,17 +839,6 @@
     }
 
     /**
-     * @hide
-     */
-    public void reportFullscreenMode(IBinder token, boolean fullscreen) {
-        try {
-            mService.reportFullscreenMode(token, fullscreen);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Return true if the given view is the currently active view for the
      * input method.
      */
@@ -2333,7 +2302,13 @@
     }
 
     /**
-     * @return The current height of the input method window.
+     * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
+     *
+     * <p>TODO(Bug 113914148): Check if we can remove this.  We have accidentally exposed
+     * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
+     * started relying on it.</p>
+     *
+     * @return Something that is not well-defined.
      * @hide
      */
     @UnsupportedAppUsage
@@ -2348,28 +2323,6 @@
     }
 
     /**
-     * Tells the system that the IME decided to not show a window and the system no longer needs to
-     * use the previous IME's inset.
-     *
-     * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
-     * is the only expected caller of this method.  Do not depend on this anywhere else.</p>
-     *
-     * <p>TODO: We probably need to reconsider how IME should be handled.</p>
-     * @hide
-     * @param token Supplies the identifying token given to an input method when it was started,
-     * which allows it to perform this operation on itself.
-     */
-    public void clearLastInputMethodWindowForTransition(final IBinder token) {
-        synchronized (mH) {
-            try {
-                mService.clearLastInputMethodWindowForTransition(token);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
      * Force switch to the last used input method and subtype. If the last input method didn't have
      * any subtypes, the framework will simply switch to the last input method with no subtype
      * specified.
@@ -2507,40 +2460,6 @@
         }
     }
 
-    /**
-     * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
-     * permission to the content.
-     *
-     * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
-     * InputConnection)} for details.</p>
-     *
-     * @param token Supplies the identifying token given to an input method when it was started,
-     * which allows it to perform this operation on itself.
-     * @param inputContentInfo Content to be temporarily exposed from the input method to the
-     * application.
-     * This cannot be {@code null}.
-     * @param editorInfo The editor that receives {@link InputContentInfo}.
-     * @hide
-     */
-    public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
-            @NonNull EditorInfo editorInfo) {
-        final IInputContentUriToken uriToken;
-        final Uri contentUri = inputContentInfo.getContentUri();
-        try {
-            uriToken = mService.createInputContentUriToken(token, contentUri,
-                    editorInfo.packageName);
-            if (uriToken == null) {
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
-                    + " packageName=" + editorInfo.packageName, e);
-            return;
-        }
-        inputContentInfo.setUriToken(uriToken);
-        return;
-    }
-
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method client state for " + this + ":");
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 8728367..cb282b6 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -75,6 +75,15 @@
         return !TextUtils.isEmpty(reachSensorType());
     }
 
+    public boolean wakeScreenGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
+                && wakeScreenGestureAvailable();
+    }
+
+    public boolean wakeScreenGestureAvailable() {
+        return !TextUtils.isEmpty(wakeScreenSensorType());
+    }
+
     public String doubleTapSensorType() {
         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
     }
@@ -87,6 +96,10 @@
         return mContext.getResources().getString(R.string.config_dozeReachSensorType);
     }
 
+    public String wakeScreenSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeWakeScreenSensorType);
+    }
+
     public boolean pulseOnLongPressEnabled(int user) {
         return pulseOnLongPressAvailable() && boolSettingDefaultOff(
                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
new file mode 100644
index 0000000..449b4a5
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.inputmethod;
+
+import android.net.Uri;
+
+import com.android.internal.inputmethod.IInputContentUriToken;
+
+/**
+ * Defines priviledged operations that only the current IME is allowed to call.
+ * Actual operations are implemented and handled by InputMethodManagerService.
+ */
+interface IInputMethodPrivilegedOperations {
+    void setImeWindowStatus(int vis, int backDisposition);
+    void reportStartInput(in IBinder startInputToken);
+    void clearLastInputMethodWindowForTransition();
+    IInputContentUriToken createInputContentUriToken(in Uri contentUri, in String packageName);
+    void reportFullscreenMode(boolean fullscreen);
+}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 4aa30f6..c0c358d 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -16,16 +16,9 @@
 
 package com.android.internal.os;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
 import android.os.Binder;
-import android.os.OsProtoEnums;
-import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.format.DateFormat;
@@ -37,7 +30,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BinderInternal.CallSession;
-import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
 import java.lang.reflect.InvocationTargetException;
@@ -63,7 +55,6 @@
 
     private static final String TAG = "BinderCallsStats";
     private static final int CALL_SESSIONS_POOL_SIZE = 100;
-    private static final int PERIODIC_SAMPLING_INTERVAL = 10;
     private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
     private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
 
@@ -81,25 +72,7 @@
     private final Random mRandom;
     private long mStartTime = System.currentTimeMillis();
 
-    // State updated by the broadcast receiver below.
-    private boolean mScreenInteractive;
-    private boolean mCharging;
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            switch (intent.getAction()) {
-                case Intent.ACTION_BATTERY_CHANGED:
-                    mCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
-                    break;
-                case Intent.ACTION_SCREEN_ON:
-                    mScreenInteractive = true;
-                    break;
-                case Intent.ACTION_SCREEN_OFF:
-                    mScreenInteractive = false;
-                    break;
-            }
-        }
-    };
+    private CachedDeviceState.Readonly mDeviceState;
 
     /** Injector for {@link BinderCallsStats}. */
     public static class Injector {
@@ -112,65 +85,14 @@
         this.mRandom = injector.getRandomGenerator();
     }
 
-    public void systemReady(Context context) {
-        registerBroadcastReceiver(context);
-        setInitialState(queryScreenInteractive(context), queryIsCharging());
-    }
-
-    /**
-     * Listens for screen/battery state changes.
-     */
-    @VisibleForTesting
-    public void registerBroadcastReceiver(Context context) {
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
-        filter.addAction(Intent.ACTION_SCREEN_ON);
-        filter.addAction(Intent.ACTION_SCREEN_OFF);
-        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
-        context.registerReceiver(mBroadcastReceiver, filter);
-    }
-
-    /**
-     * Sets the battery/screen initial state.
-     *
-     * This has to be updated *after* the broadcast receiver is installed.
-     */
-    @VisibleForTesting
-    public void setInitialState(boolean isScreenInteractive, boolean isCharging) {
-        this.mScreenInteractive = isScreenInteractive;
-        this.mCharging = isCharging;
-        // Data collected previously was not accurate since the battery/screen state was not set.
-        reset();
-    }
-
-    private boolean queryIsCharging() {
-        final BatteryManagerInternal batteryManager =
-                LocalServices.getService(BatteryManagerInternal.class);
-        if (batteryManager == null) {
-            Slog.wtf(TAG, "BatteryManager null while starting BinderCallsStatsService");
-            // Default to true to not collect any data.
-            return true;
-        } else {
-            return batteryManager.getPlugType() != OsProtoEnums.BATTERY_PLUGGED_NONE;
-        }
-    }
-
-    private boolean queryScreenInteractive(Context context) {
-        final PowerManager powerManager = context.getSystemService(PowerManager.class);
-        final boolean screenInteractive;
-        if (powerManager == null) {
-            Slog.wtf(TAG, "PowerManager null while starting BinderCallsStatsService",
-                    new Throwable());
-            return true;
-        } else {
-            return powerManager.isInteractive();
-        }
+    public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
+        mDeviceState = deviceState;
     }
 
     @Override
     @Nullable
     public CallSession callStarted(Binder binder, int code) {
-        if (mCharging) {
+        if (mDeviceState == null || mDeviceState.isCharging()) {
             return null;
         }
 
@@ -221,7 +143,7 @@
 
         synchronized (mLock) {
             // This was already checked in #callStart but check again while synchronized.
-            if (mCharging) {
+            if (mDeviceState == null || mDeviceState.isCharging()) {
                 return;
             }
 
@@ -233,7 +155,7 @@
                 uidEntry.recordedCallCount++;
 
                 final CallStat callStat = uidEntry.getOrCreate(
-                        s.binderClass, s.transactionCode, mScreenInteractive);
+                        s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
                 callStat.callCount++;
                 callStat.recordedCallCount++;
                 callStat.cpuTimeMicros += duration;
@@ -252,7 +174,7 @@
                 // Only record the total call count if we already track data for this key.
                 // It helps to keep the memory usage down when sampling is enabled.
                 final CallStat callStat = uidEntry.get(
-                        s.binderClass, s.transactionCode, mScreenInteractive);
+                        s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
                 if (callStat != null) {
                     callStat.callCount++;
                 }
@@ -319,13 +241,13 @@
     public ArrayList<ExportedCallStat> getExportedCallStats() {
         // We do not collect all the data if detailed tracking is off.
         if (!mDetailedTracking) {
-            return new ArrayList<ExportedCallStat>();
+            return new ArrayList<>();
         }
 
         ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
         synchronized (mLock) {
             final int uidEntriesSize = mUidEntries.size();
-            for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++){
+            for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++) {
                 final UidEntry entry = mUidEntries.valueAt(entryIdx);
                 for (CallStat stat : entry.getCallStatsList()) {
                     ExportedCallStat exported = new ExportedCallStat();
@@ -387,13 +309,15 @@
         }
     }
 
-    public void dump(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+    /** Writes the collected statistics to the supplied {@link PrintWriter}.*/
+    public void dump(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap, boolean verbose) {
         synchronized (mLock) {
             dumpLocked(pw, appIdToPkgNameMap, verbose);
         }
     }
 
-    private void dumpLocked(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+    private void dumpLocked(PrintWriter pw, Map<Integer, String> appIdToPkgNameMap,
+            boolean verbose) {
         long totalCallsCount = 0;
         long totalRecordedCallsCount = 0;
         long totalCpuTime = 0;
@@ -450,13 +374,13 @@
         for (UidEntry entry : summaryEntries) {
             String uidStr = uidToString(entry.uid, appIdToPkgNameMap);
             pw.println(String.format("  %10d %3.0f%% %8d %8d %s",
-                        entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
-                        entry.recordedCallCount, entry.callCount, uidStr));
+                    entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
+                    entry.recordedCallCount, entry.callCount, uidStr));
         }
         pw.println();
         pw.println(String.format("  Summary: total_cpu_time=%d, "
-                    + "calls_count=%d, avg_call_cpu_time=%.0f",
-                    totalCpuTime, totalCallsCount, (double)totalCpuTime / totalRecordedCallsCount));
+                        + "calls_count=%d, avg_call_cpu_time=%.0f",
+                totalCpuTime, totalCallsCount, (double) totalCpuTime / totalRecordedCallsCount));
         pw.println();
 
         pw.println("Exceptions thrown (exception_count, class_name):");
@@ -723,11 +647,6 @@
         return result;
     }
 
-    @VisibleForTesting
-    public BroadcastReceiver getBroadcastReceiver() {
-        return mBroadcastReceiver;
-    }
-
     private static int compareByCpuDesc(
             ExportedCallStat a, ExportedCallStat b) {
         return Long.compare(b.cpuTimeMicros, a.cpuTimeMicros);
diff --git a/core/java/com/android/internal/os/CachedDeviceState.java b/core/java/com/android/internal/os/CachedDeviceState.java
new file mode 100644
index 0000000..8c90682
--- /dev/null
+++ b/core/java/com/android/internal/os/CachedDeviceState.java
@@ -0,0 +1,66 @@
+/*
+ * 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.os;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Stores the device state (e.g. charging/on battery, screen on/off) to be shared with
+ * the System Server telemetry services.
+ *
+ * @hide
+ */
+public class CachedDeviceState {
+    private volatile boolean mScreenInteractive;
+    private volatile boolean mCharging;
+
+    public CachedDeviceState() {
+        mCharging = true;
+        mScreenInteractive = false;
+    }
+
+    @VisibleForTesting
+    public CachedDeviceState(boolean isCharging, boolean isScreenInteractive) {
+        mCharging = isCharging;
+        mScreenInteractive = isScreenInteractive;
+    }
+
+    public void setScreenInteractive(boolean screenInteractive) {
+        mScreenInteractive = screenInteractive;
+    }
+
+    public void setCharging(boolean charging) {
+        mCharging = charging;
+    }
+
+    public Readonly getReadonlyClient() {
+        return new CachedDeviceState.Readonly();
+    }
+
+    /**
+     * Allows for only a readonly access to the device state.
+     */
+    public class Readonly {
+        public boolean isCharging() {
+            return mCharging;
+        }
+
+        public boolean isScreenInteractive() {
+            return mScreenInteractive;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index edf475f..02a8b22 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -37,31 +37,30 @@
  */
 public class LooperStats implements Looper.Observer {
     private static final int TOKEN_POOL_SIZE = 50;
-    private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
-    private static final int DEFAULT_SAMPLING_INTERVAL = 100;
 
     @GuardedBy("mLock")
-    private final SparseArray<Entry> mEntries = new SparseArray<>(256);
+    private final SparseArray<Entry> mEntries = new SparseArray<>(512);
     private final Object mLock = new Object();
     private final Entry mOverflowEntry = new Entry("OVERFLOW");
     private final Entry mHashCollisionEntry = new Entry("HASH_COLLISION");
     private final ConcurrentLinkedQueue<DispatchSession> mSessionPool =
             new ConcurrentLinkedQueue<>();
-    private final int mSamplingInterval;
     private final int mEntriesSizeCap;
-
-    public LooperStats() {
-        this(DEFAULT_SAMPLING_INTERVAL, DEFAULT_ENTRIES_SIZE_CAP);
-    }
+    private int mSamplingInterval;
+    private CachedDeviceState.Readonly mDeviceState;
 
     public LooperStats(int samplingInterval, int entriesSizeCap) {
         this.mSamplingInterval = samplingInterval;
         this.mEntriesSizeCap = entriesSizeCap;
     }
 
+    public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) {
+        mDeviceState = deviceState;
+    }
+
     @Override
     public Object messageDispatchStarting() {
-        if (shouldCollectDetailedData()) {
+        if (deviceStateAllowsCollection() && shouldCollectDetailedData()) {
             DispatchSession session = mSessionPool.poll();
             session = session == null ? new DispatchSession() : session;
             session.startTimeMicro = getElapsedRealtimeMicro();
@@ -74,6 +73,10 @@
 
     @Override
     public void messageDispatched(Object token, Message msg) {
+        if (!deviceStateAllowsCollection()) {
+            return;
+        }
+
         DispatchSession session = (DispatchSession) token;
         Entry entry = getOrCreateEntry(msg);
         synchronized (entry) {
@@ -94,6 +97,10 @@
 
     @Override
     public void dispatchingThrewException(Object token, Message msg, Exception exception) {
+        if (!deviceStateAllowsCollection()) {
+            return;
+        }
+
         DispatchSession session = (DispatchSession) token;
         Entry entry = getOrCreateEntry(msg);
         synchronized (entry) {
@@ -102,6 +109,11 @@
         recycleSession(session);
     }
 
+    private boolean deviceStateAllowsCollection() {
+        // Do not collect data if on charger or the state is not set.
+        return mDeviceState != null && !mDeviceState.isCharging();
+    }
+
     /** Returns an array of {@link ExportedEntry entries} with the aggregated statistics. */
     public List<ExportedEntry> getEntries() {
         final ArrayList<ExportedEntry> entries;
@@ -142,9 +154,14 @@
         }
     }
 
+    public void setSamplingInterval(int samplingInterval) {
+        mSamplingInterval = samplingInterval;
+    }
+
     @NonNull
     private Entry getOrCreateEntry(Message msg) {
-        final int id = Entry.idFor(msg);
+        final boolean isInteractive = mDeviceState.isScreenInteractive();
+        final int id = Entry.idFor(msg, isInteractive);
         Entry entry;
         synchronized (mLock) {
             entry = mEntries.get(id);
@@ -153,14 +170,14 @@
                     // If over the size cap, track totals under a single entry.
                     return mOverflowEntry;
                 }
-                entry = new Entry(msg);
+                entry = new Entry(msg, isInteractive);
                 mEntries.put(id, entry);
             }
         }
 
         if (entry.handler.getClass() != msg.getTarget().getClass()
-                || entry.handler.getLooper().getThread()
-                != msg.getTarget().getLooper().getThread()) {
+                || entry.handler.getLooper().getThread() != msg.getTarget().getLooper().getThread()
+                || entry.isInteractive != isInteractive) {
             // If a hash collision happened, track totals under a single entry.
             return mHashCollisionEntry;
         }
@@ -194,6 +211,7 @@
     private static class Entry {
         public final Handler handler;
         public final String messageName;
+        public final boolean isInteractive;
         public long messageCount;
         public long recordedMessageCount;
         public long exceptionCount;
@@ -202,14 +220,16 @@
         public long cpuUsageMicro;
         public long maxCpuUsageMicro;
 
-        Entry(Message msg) {
-            handler = msg.getTarget();
-            messageName = handler.getMessageName(msg);
+        Entry(Message msg, boolean isInteractive) {
+            this.handler = msg.getTarget();
+            this.messageName = handler.getMessageName(msg);
+            this.isInteractive = isInteractive;
         }
 
         Entry(String specialEntryName) {
-            handler = null;
-            messageName = specialEntryName;
+            this.messageName = specialEntryName;
+            this.handler = null;
+            this.isInteractive = false;
         }
 
         void reset() {
@@ -222,10 +242,11 @@
             maxCpuUsageMicro = 0;
         }
 
-        static int idFor(Message msg) {
+        static int idFor(Message msg, boolean isInteractive) {
             int result = 7;
             result = 31 * result + msg.getTarget().getLooper().getThread().hashCode();
             result = 31 * result + msg.getTarget().getClass().hashCode();
+            result = 31 * result + (isInteractive ? 1231 : 1237);
             if (msg.getCallback() != null) {
                 return 31 * result + msg.getCallback().getClass().hashCode();
             } else {
@@ -239,6 +260,7 @@
         public final String handlerClassName;
         public final String threadName;
         public final String messageName;
+        public final boolean isInteractive;
         public final long messageCount;
         public final long recordedMessageCount;
         public final long exceptionCount;
@@ -256,6 +278,7 @@
                 this.handlerClassName = "";
                 this.threadName = "";
             }
+            this.isInteractive = entry.isInteractive;
             this.messageName = entry.messageName;
             this.messageCount = entry.messageCount;
             this.recordedMessageCount = entry.recordedMessageCount;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 189c8d5..d4c4ab3 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -16,9 +16,6 @@
 
 package com.android.internal.view;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.SomeArgs;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
@@ -37,6 +34,9 @@
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputContentInfo;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
 public abstract class IInputConnectionWrapper extends IInputContext.Stub {
     private static final String TAG = "IInputConnectionWrapper";
     private static final boolean DEBUG = false;
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 5b29f4c..b6a654a 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -22,6 +22,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.IInputSessionCallback;
@@ -32,7 +33,7 @@
  * {@hide}
  */
 oneway interface IInputMethod {
-    void attachToken(IBinder token);
+    void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps);
 
     void bindInput(in InputBinding binding);
 
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 4b004e2..c08c871 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -16,13 +16,12 @@
 
 package com.android.internal.view;
 
-import android.net.Uri;
 import android.os.ResultReceiver;
 import android.text.style.SuggestionSpan;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.EditorInfo;
-import com.android.internal.inputmethod.IInputContentUriToken;
+
 import com.android.internal.view.InputBindResult;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -69,8 +68,6 @@
     void hideMySoftInput(in IBinder token, int flags);
     void showMySoftInput(in IBinder token, int flags);
     void updateStatusIcon(in IBinder token, String packageName, int iconId);
-    void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
-    void reportStartInput(in IBinder token, in IBinder startInputToken);
     void registerSuggestionSpansForNotification(in SuggestionSpan[] spans);
     boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index);
     InputMethodSubtype getCurrentInputMethodSubtype();
@@ -79,13 +76,9 @@
     boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme);
     boolean shouldOfferSwitchingToNextInputMethod(in IBinder token);
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
+    // This is kept due to @UnsupportedAppUsage.
+    // TODO(Bug 113914148): Consider removing this.
     int getInputMethodWindowVisibleHeight();
-    void clearLastInputMethodWindowForTransition(in IBinder token);
-
-    IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri,
-            in String packageName);
-
-    void reportFullscreenMode(in IBinder token, boolean fullscreen);
 
     oneway void notifyUserAction(int sequenceNumber);
 }
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index f1bd63b..1257336 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -271,7 +271,7 @@
     optional .android.graphics.RectProto containing_frame = 8 [deprecated=true];
     optional .android.graphics.RectProto parent_frame = 9 [deprecated=true];
     optional .android.graphics.RectProto content_frame = 10 [deprecated=true];
-    optional .android.graphics.RectProto content_insets = 11;
+    optional .android.graphics.RectProto content_insets = 11 [deprecated=true];
     optional .android.graphics.RectProto surface_insets = 12;
     optional WindowStateAnimatorProto animator = 13;
     optional bool animating_exit = 14;
@@ -288,10 +288,10 @@
     optional .android.graphics.RectProto visible_frame = 26 [deprecated=true];
     optional .android.graphics.RectProto decor_frame = 27 [deprecated=true];
     optional .android.graphics.RectProto outset_frame = 28 [deprecated=true];
-    optional .android.graphics.RectProto overscan_insets = 29;
-    optional .android.graphics.RectProto visible_insets = 30;
-    optional .android.graphics.RectProto stable_insets = 31;
-    optional .android.graphics.RectProto outsets = 32;
+    optional .android.graphics.RectProto overscan_insets = 29 [deprecated=true];
+    optional .android.graphics.RectProto visible_insets = 30 [deprecated=true];
+    optional .android.graphics.RectProto stable_insets = 31 [deprecated=true];
+    optional .android.graphics.RectProto outsets = 32 [deprecated=true];
     optional .android.view.DisplayCutoutProto cutout = 33 [deprecated=true];
     optional bool remove_on_exit = 34;
     optional bool destroying = 35;
@@ -380,4 +380,9 @@
     optional .android.graphics.RectProto parent_frame = 8;
     optional .android.graphics.RectProto visible_frame = 9;
     optional .android.view.DisplayCutoutProto cutout = 10;
+    optional .android.graphics.RectProto content_insets = 11;
+    optional .android.graphics.RectProto overscan_insets = 12;
+    optional .android.graphics.RectProto visible_insets = 13;
+    optional .android.graphics.RectProto stable_insets = 14;
+    optional .android.graphics.RectProto outsets = 15;
 }
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 3308128..13f6bce 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -40,7 +40,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index bb0d4d5..d45b91a 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -38,7 +38,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 1241a9d..b520d5d 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -41,7 +41,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 232f149..650aa62 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -28,7 +28,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 1d2e625..4bb68dc 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -24,7 +24,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index ef1ecd2..11bfa05 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -43,7 +43,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cf1320c..235f85b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2116,6 +2116,9 @@
     <!-- Type of the reach sensor. Empty if reach is not supported. -->
     <string name="config_dozeReachSensorType" translatable="false"></string>
 
+    <!-- Type of the wake up sensor. Empty if not supported. -->
+    <string name="config_dozeWakeScreenSensorType" translatable="false"></string>
+
     <!-- Control whether the always on display mode is available. This should only be enabled on
          devices where the display has been tuned to be power efficient in DOZE and/or DOZE_SUSPEND
          states. -->
@@ -2793,7 +2796,7 @@
         <item>SUPL_PORT=7275</item>
         <item>SUPL_VER=0x20000</item>
         <item>SUPL_MODE=1</item>
-        <item>SUPL_ES=0</item>
+        <item>SUPL_ES=1</item>
         <item>LPP_PROFILE=0</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 48c263e..92cca72 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3462,4 +3462,5 @@
 
   <java-symbol type="integer" name="db_wal_truncate_size" />
   <java-symbol type="integer" name="config_wakeUpDelayDoze" />
+  <java-symbol type="string" name="config_dozeWakeScreenSensorType" />
 </resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 517cf4d..e84aed1 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -282,6 +282,7 @@
                     Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
                     Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
                     Settings.Global.LOCK_SOUND,
+                    Settings.Global.LOOPER_STATS,
                     Settings.Global.LOW_BATTERY_SOUND,
                     Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
                     Settings.Global.LOW_POWER_MODE,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
index 3c04895..3e03414 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
@@ -40,7 +40,7 @@
     // and assertAccessibilityEventCleared
 
     /** The number of properties of the {@link AccessibilityEvent} class. */
-    private static final int A11Y_EVENT_NON_STATIC_FIELD_COUNT = 32;
+    private static final int A11Y_EVENT_NON_STATIC_FIELD_COUNT = 33;
 
     // The number of fields tested in the corresponding CTS AccessibilityRecordTest:
     // assertAccessibilityRecordCleared, fullyPopulateAccessibilityRecord,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 7fa6ce4..922b79a 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -57,7 +57,7 @@
 
     // The number of flags held in boolean properties. Their values should also be double-checked
     // in the methods above.
-    private static final int NUM_BOOLEAN_PROPERTIES = 22;
+    private static final int NUM_BOOLEAN_PROPERTIES = 17;
 
     @Test
     public void testStandardActions_serializationFlagIsValid() {
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index ace6b2d..364dcfd 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -18,10 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.content.Intent;
-import android.os.BatteryManager;
 import android.os.Binder;
-import android.os.OsProtoEnums;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -34,7 +31,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -50,6 +46,7 @@
     private static final int TEST_UID = 1;
     private static final int REQUEST_SIZE = 2;
     private static final int REPLY_SIZE = 3;
+    private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true);
 
     @Test
     public void testDetailedOff() {
@@ -388,43 +385,27 @@
     }
 
     @Test
-    public void testDataResetWhenInitialStateSet() {
+    public void testNoDataCollectedBeforeInitialDeviceStateSet() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDeviceState(null);
         bcs.setDetailedTracking(true);
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.time += 10;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
-        bcs.setInitialState(true, true);
+        bcs.setDeviceState(mDeviceState.getReadonlyClient());
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(0, uidEntries.size());
     }
 
     @Test
-    public void testScreenAndChargerInitialStates() {
-        TestBinderCallsStats bcs = new TestBinderCallsStats();
-        bcs.setDetailedTracking(true);
-        Binder binder = new Binder();
-        bcs.setInitialState(true /** screen iteractive */, false);
-
-        CallSession callSession = bcs.callStarted(binder, 1);
-        bcs.time += 10;
-        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
-
-        List<BinderCallsStats.CallStat> callStatsList =
-                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
-        assertEquals(true, callStatsList.get(0).screenInteractive);
-    }
-
-    @Test
     public void testNoDataCollectedOnCharger() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
-                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
-        bcs.getBroadcastReceiver().onReceive(null, intent);
+        mDeviceState.setCharging(true);
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -436,7 +417,7 @@
     public void testScreenOff() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_OFF));
+        mDeviceState.setScreenInteractive(false);
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -453,7 +434,7 @@
     public void testScreenOn() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+        mDeviceState.setScreenInteractive(true);
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -470,9 +451,8 @@
     public void testOnCharger() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
-                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
-        bcs.getBroadcastReceiver().onReceive(null, intent);
+        mDeviceState.setCharging(true);
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -484,9 +464,8 @@
     public void testOnBattery() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
-                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
-        bcs.getBroadcastReceiver().onReceive(null, intent);
+        mDeviceState.setCharging(false);
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
@@ -522,7 +501,6 @@
     public void testGetExportedStatsWhenDetailedTrackingEnabled() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
-        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
 
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
@@ -561,7 +539,7 @@
         assertEquals(0, bcs.getExceptionCounts().size());
     }
 
-    static class TestBinderCallsStats extends BinderCallsStats {
+    class TestBinderCallsStats extends BinderCallsStats {
         int callingUid = TEST_UID;
         long time = 1234;
         long elapsedTime = 0;
@@ -580,6 +558,7 @@
                 }
             });
             setSamplingInterval(1);
+            setDeviceState(mDeviceState.getReadonlyClient());
         }
 
         @Override
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 297202b..0eb3d06 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -43,6 +43,7 @@
     private Handler mHandlerFirst;
     private Handler mHandlerSecond;
     private Handler mHandlerAnonymous;
+    private CachedDeviceState mDeviceState;
 
     @Before
     public void setUp() {
@@ -58,6 +59,9 @@
         mHandlerAnonymous = new Handler(mThreadFirst.getLooper()) {
             /* To create an anonymous subclass. */
         };
+        mDeviceState = new CachedDeviceState();
+        mDeviceState.setCharging(false);
+        mDeviceState.setScreenInteractive(true);
     }
 
     @After
@@ -82,6 +86,7 @@
         assertThat(entry.handlerClassName).isEqualTo(
                 "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
         assertThat(entry.messageName).isEqualTo("0x3e8" /* 1000 in hex */);
+        assertThat(entry.isInteractive).isEqualTo(true);
         assertThat(entry.messageCount).isEqualTo(1);
         assertThat(entry.recordedMessageCount).isEqualTo(1);
         assertThat(entry.exceptionCount).isEqualTo(0);
@@ -108,6 +113,7 @@
         assertThat(entry.handlerClassName).isEqualTo(
                 "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
         assertThat(entry.messageName).isEqualTo("0x7"  /* 7 in hex */);
+        assertThat(entry.isInteractive).isEqualTo(true);
         assertThat(entry.messageCount).isEqualTo(0);
         assertThat(entry.recordedMessageCount).isEqualTo(0);
         assertThat(entry.exceptionCount).isEqualTo(1);
@@ -194,6 +200,70 @@
     }
 
     @Test
+    public void testDataNotCollectedBeforeDeviceStateSet() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+        looperStats.setDeviceState(null);
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(0);
+    }
+
+    @Test
+    public void testDataNotCollectedOnCharger() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+        mDeviceState.setCharging(true);
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(0);
+    }
+
+    @Test
+    public void testScreenStateCollected() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+        mDeviceState.setScreenInteractive(true);
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token2, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        Object token3 = looperStats.messageDispatchStarting();
+        // If screen state changed during the call, we take the final state into account.
+        mDeviceState.setScreenInteractive(false);
+        looperStats.messageDispatched(token3, mHandlerFirst.obtainMessage(1000));
+        Object token4 = looperStats.messageDispatchStarting();
+        looperStats.dispatchingThrewException(token4, mHandlerFirst.obtainMessage(1000),
+                new IllegalArgumentException());
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(2);
+        entries.sort(Comparator.comparing(e -> e.isInteractive));
+
+        LooperStats.ExportedEntry entry1 = entries.get(0);
+        assertThat(entry1.isInteractive).isEqualTo(false);
+        assertThat(entry1.messageCount).isEqualTo(1);
+        assertThat(entry1.exceptionCount).isEqualTo(1);
+
+        LooperStats.ExportedEntry entry2 = entries.get(1);
+        assertThat(entry2.isInteractive).isEqualTo(true);
+        assertThat(entry2.messageCount).isEqualTo(1);
+        assertThat(entry2.exceptionCount).isEqualTo(1);
+    }
+
+    @Test
     public void testMessagesOverSizeCap() {
         TestableLooperStats looperStats = new TestableLooperStats(2, 1 /* sizeCap */);
 
@@ -281,7 +351,7 @@
         }
     }
 
-    private static final class TestableLooperStats extends LooperStats {
+    private final class TestableLooperStats extends LooperStats {
         private static final long INITIAL_MICROS = 10001000123L;
         private int mCount;
         private long mRealtimeMicros;
@@ -291,6 +361,7 @@
         TestableLooperStats(int samplingInterval, int sizeCap) {
             super(samplingInterval, sizeCap);
             this.mSamplingInterval = samplingInterval;
+            this.setDeviceState(mDeviceState.getReadonlyClient());
         }
 
         void tickRealtime(long micros) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 9dab536..7fc1787 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.annotation.Px;
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
@@ -805,25 +806,39 @@
      * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
      *
      * @return true if the underlineText bit is set in the paint's flags.
+     * @see #getUnderlinePosition()
+     * @see #getUnderlineThickness()
+     * @see #setUnderlineText(boolean)
      */
     public final boolean isUnderlineText() {
         return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
     }
 
     /**
-     * Distance from top of the underline to the baseline. Positive values mean below the baseline.
-     * This method returns where the underline should be drawn independent of if the underlineText
-     * bit is set at the moment.
-     * @hide
+     * Returns the distance from top of the underline to the baseline in pixels.
+     *
+     * The result is positive for positions that are below the baseline.
+     * This method returns where the underline should be drawn independent of if the {@link
+     * #UNDERLINE_TEXT_FLAG} bit is set.
+     *
+     * @return the position of the underline in pixels
+     * @see #isUnderlineText()
+     * @see #getUnderlineThickness()
+     * @see #setUnderlineText(boolean)
      */
-    public float getUnderlinePosition() {
+    public @Px float getUnderlinePosition() {
         return nGetUnderlinePosition(mNativePaint);
     }
 
     /**
-     * @hide
+     * Returns the thickness of the underline in pixels.
+     *
+     * @return the thickness of the underline in pixels
+     * @see #isUnderlineText()
+     * @see #getUnderlinePosition()
+     * @see #setUnderlineText(boolean)
      */
-    public float getUnderlineThickness() {
+    public @Px float getUnderlineThickness() {
         return nGetUnderlineThickness(mNativePaint);
     }
 
@@ -832,6 +847,9 @@
      *
      * @param underlineText true to set the underlineText bit in the paint's
      *                      flags, false to clear it.
+     * @see #isUnderlineText()
+     * @see #getUnderlinePosition()
+     * @see #getUnderlineThickness()
      */
     public void setUnderlineText(boolean underlineText) {
         nSetUnderlineText(mNativePaint, underlineText);
@@ -840,26 +858,40 @@
     /**
      * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
      *
-     * @return true if the strikeThruText bit is set in the paint's flags.
+     * @return true if the {@link #STRIKE_THRU_TEXT_FLAG} bit is set in the paint's flags.
+     * @see #getStrikeThruPosition()
+     * @see #getStrikeThruThickness()
+     * @see #setStrikeThruText(boolean)
      */
     public final boolean isStrikeThruText() {
         return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
     }
 
     /**
-     * Distance from top of the strike-through line to the baseline. Negative values mean above the
-     * baseline. This method returns where the strike-through line should be drawn independent of if
-     * the strikeThruText bit is set at the moment.
-     * @hide
+     * Distance from top of the strike-through line to the baseline in pixels.
+     *
+     * The result is negative for positions that are above the baseline.
+     * This method returns where the strike-through line should be drawn independent of if the
+     * {@link #STRIKE_THRU_TEXT_FLAG} bit is set.
+     *
+     * @return the position of the strike-through line in pixels
+     * @see #getStrikeThruThickness()
+     * @see #setStrikeThruText(boolean)
+     * @see #isStrikeThruText()
      */
-    public float getStrikeThruPosition() {
+    public @Px float getStrikeThruPosition() {
         return nGetStrikeThruPosition(mNativePaint);
     }
 
     /**
-     * @hide
+     * Returns the thickness of the strike-through line in pixels.
+     *
+     * @return the position of the strike-through line in pixels
+     * @see #getStrikeThruPosition()
+     * @see #setStrikeThruText(boolean)
+     * @see #isStrikeThruText()
      */
-    public float getStrikeThruThickness() {
+    public @Px float getStrikeThruThickness() {
         return nGetStrikeThruThickness(mNativePaint);
     }
 
@@ -868,6 +900,9 @@
      *
      * @param strikeThruText true to set the strikeThruText bit in the paint's
      *                       flags, false to clear it.
+     * @see #getStrikeThruPosition()
+     * @see #getStrikeThruThickness()
+     * @see #isStrikeThruText()
      */
     public void setStrikeThruText(boolean strikeThruText) {
         nSetStrikeThruText(mNativePaint, strikeThruText);
@@ -1560,22 +1595,25 @@
     }
 
     /**
-     * Return the paint's word-spacing for text. The default value is 0.
+     * Return the paint's extra word-spacing for text.
      *
-     * @return the paint's word-spacing for drawing text.
-     * @hide
+     * The default value is 0.
+     *
+     * @return the paint's extra word-spacing for drawing text in pixels.
+     * @see #setWordSpacing(float)
      */
     public float getWordSpacing() {
         return nGetWordSpacing(mNativePaint);
     }
 
     /**
-     * Set the paint's word-spacing for text. The default value is 0.
-     * The value is in pixels (note the units are not the same as for
-     * letter-spacing).
+     * Set the paint's extra word-spacing for text.
      *
-     * @param wordSpacing set the paint's word-spacing for drawing text.
-     * @hide
+     * Increases the white space width between words with the given amount of pixels.
+     * The default value is 0.
+     *
+     * @param wordSpacing set the paint's extra word-spacing for drawing text in pixels.
+     * @see #getWordSpacing()
      */
     public void setWordSpacing(float wordSpacing) {
         nSetWordSpacing(mNativePaint, wordSpacing);
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e8bc622..0476222 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1035,7 +1035,7 @@
             return fromGetVolumeControlStream ?
                     AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
         }
-        if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
+        if ((aa.getAllFlags() & FLAG_SCO) == FLAG_SCO) {
             return fromGetVolumeControlStream ?
                     AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
         }
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 0892f73..967e13f 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -38,7 +38,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center_horizontal|bottom"
         android:gravity="center_vertical"
-        android:visibility="invisible">
+        android:alpha="0">
 
         <ImageView
             android:id="@+id/next_alarm_icon"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
index 0d25c91..0cde9da 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputConsumerController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shared.system;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
 
@@ -146,8 +147,9 @@
         if (mInputEventReceiver == null) {
             final InputChannel inputChannel = new InputChannel();
             try {
-                mWindowManager.destroyInputConsumer(mName);
-                mWindowManager.createInputConsumer(mToken, mName, inputChannel);
+                // TODO(b/113087003): Support Picture-in-picture in multi-display.
+                mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
+                mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to create input consumer", e);
             }
@@ -164,7 +166,8 @@
     public void unregisterInputConsumer() {
         if (mInputEventReceiver != null) {
             try {
-                mWindowManager.destroyInputConsumer(mName);
+                // TODO(b/113087003): Support Picture-in-picture in multi-display.
+                mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to destroy input consumer", e);
             }
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index 5605b7a..ac8f024 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -39,6 +39,7 @@
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.systemui.util.EmergencyDialerConstants;
 
 /**
  * This class implements a smart emergency button that updates itself based
@@ -48,11 +49,13 @@
  */
 public class EmergencyButton extends Button {
     private static final Intent INTENT_EMERGENCY_DIAL = new Intent()
-            .setAction("com.android.phone.EmergencyDialer.DIAL")
+            .setAction(EmergencyDialerConstants.ACTION_DIAL)
             .setPackage("com.android.phone")
             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                    | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+            .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+                    EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
 
     private static final String LOG_TAG = "EmergencyButton";
     private final EmergencyAffordanceManager mEmergencyAffordanceManager;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 51cc4a1..e6026c1 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -35,7 +35,7 @@
     private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
     static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
-    private static final int PULSE_REASONS = 7;
+    private static final int REASONS = 8;
 
     public static final int PULSE_REASON_NONE = -1;
     public static final int PULSE_REASON_INTENT = 0;
@@ -45,6 +45,7 @@
     public static final int PULSE_REASON_SENSOR_DOUBLE_TAP = 4;
     public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5;
     public static final int PULSE_REASON_SENSOR_REACH = 6;
+    public static final int REASON_SENSOR_WAKE_UP = 7;
 
     private static boolean sRegisterKeyguardCallback = true;
 
@@ -74,7 +75,7 @@
     public static void tracePulseStart(int reason) {
         if (!ENABLED) return;
         sPulsing = true;
-        log("pulseStart reason=" + pulseReasonToString(reason));
+        log("pulseStart reason=" + reasonToString(reason));
     }
 
     public static void tracePulseFinish() {
@@ -102,8 +103,8 @@
                 sScreenOnPulsingStats = new SummaryStats();
                 sScreenOnNotPulsingStats = new SummaryStats();
                 sEmergencyCallStats = new SummaryStats();
-                sProxStats = new SummaryStats[PULSE_REASONS][2];
-                for (int i = 0; i < PULSE_REASONS; i++) {
+                sProxStats = new SummaryStats[REASONS][2];
+                for (int i = 0; i < REASONS; i++) {
                     sProxStats[i][0] = new SummaryStats();
                     sProxStats[i][1] = new SummaryStats();
                 }
@@ -157,6 +158,12 @@
         log("missedTick by=" + delay);
     }
 
+    public static void traceTimeTickScheduled(long when, long triggerAt) {
+        if (!ENABLED) return;
+        log("timeTickScheduled at=" + FORMAT.format(new Date(when)) + " triggerAt="
+                + FORMAT.format(new Date(triggerAt)));
+    }
+
     public static void traceKeyguard(boolean showing) {
         if (!ENABLED) return;
         log("keyguard " + showing);
@@ -176,15 +183,15 @@
     }
 
     public static void traceProximityResult(Context context, boolean near, long millis,
-            int pulseReason) {
+            int reason) {
         if (!ENABLED) return;
         init(context);
-        log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
+        log("proximityResult reason=" + reasonToString(reason) + " near=" + near
                 + " millis=" + millis);
-        sProxStats[pulseReason][near ? 0 : 1].append();
+        sProxStats[reason][near ? 0 : 1].append();
     }
 
-    public static String pulseReasonToString(int pulseReason) {
+    public static String reasonToString(int pulseReason) {
         switch (pulseReason) {
             case PULSE_REASON_INTENT: return "intent";
             case PULSE_REASON_NOTIFICATION: return "notification";
@@ -193,6 +200,7 @@
             case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
             case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress";
             case PULSE_REASON_SENSOR_REACH: return "reach";
+            case REASON_SENSOR_WAKE_UP: return "wakeup";
             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
         }
     }
@@ -218,8 +226,8 @@
             sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
             sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
             sEmergencyCallStats.dump(pw, "Emergency call");
-            for (int i = 0; i < PULSE_REASONS; i++) {
-                final String reason = pulseReasonToString(i);
+            for (int i = 0; i < REASONS; i++) {
+                final String reason = reasonToString(i);
                 sProxStats[i][0].dump(pw, "Proximity near (" + reason + ")");
                 sProxStats[i][1].dump(pw, "Proximity far (" + reason + ")");
             }
@@ -262,10 +270,10 @@
         }
     }
 
-    public static void traceSensor(Context context, int pulseReason) {
+    public static void traceSensor(Context context, int reason) {
         if (!ENABLED) return;
         init(context);
-        log("sensor type=" + pulseReasonToString(pulseReason));
+        log("sensor type=" + reasonToString(reason));
     }
 
     private static class SummaryStats {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 045a98c..f9dfb5d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -63,6 +63,7 @@
     private final AmbientDisplayConfiguration mConfig;
     private final WakeLock mWakeLock;
     private final Consumer<Boolean> mProxCallback;
+    private final Consumer<Boolean> mWakeScreenCallback;
     private final Callback mCallback;
 
     private final Handler mHandler = new Handler();
@@ -70,9 +71,9 @@
 
 
     public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
-            DozeParameters dozeParameters,
-            AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
-            Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) {
+            DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
+            Callback callback, Consumer<Boolean> proxCallback,
+            Consumer<Boolean> wakeScreenCallback, AlwaysOnDisplayPolicy policy) {
         mContext = context;
         mAlarmManager = alarmManager;
         mSensorManager = sensorManager;
@@ -80,6 +81,7 @@
         mConfig = config;
         mWakeLock = wakeLock;
         mProxCallback = proxCallback;
+        mWakeScreenCallback = wakeScreenCallback;
         mResolver = mContext.getContentResolver();
 
         mSensors = new TriggerSensor[] {
@@ -117,6 +119,7 @@
                         DozeLog.PULSE_REASON_SENSOR_REACH,
                         false /* reports touch coordinates */,
                         false /* touchscreen */),
+                new WakeScreenSensor(),
         };
 
         mProxSensor = new ProxSensor(policy);
@@ -302,9 +305,9 @@
         final boolean mSettingDefault;
         final boolean mRequiresTouchscreen;
 
-        private boolean mRequested;
-        private boolean mRegistered;
-        private boolean mDisabled;
+        protected boolean mRequested;
+        protected boolean mRegistered;
+        protected boolean mDisabled;
 
         public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
                 boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
@@ -348,7 +351,7 @@
             }
         }
 
-        private boolean enabledBySetting() {
+        protected boolean enabledBySetting() {
             if (TextUtils.isEmpty(mSetting)) {
                 return true;
             }
@@ -401,7 +404,7 @@
             }
         }
 
-        private String triggerEventToString(TriggerEvent event) {
+        protected String triggerEventToString(TriggerEvent event) {
             if (event == null) return null;
             final StringBuilder sb = new StringBuilder("TriggerEvent[")
                     .append(event.timestamp).append(',')
@@ -415,6 +418,28 @@
         }
     }
 
+    private class WakeScreenSensor extends TriggerSensor {
+
+        WakeScreenSensor() {
+            super(findSensorWithType(mConfig.wakeScreenSensorType()),
+                    Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, true /* configured */,
+                    DozeLog.REASON_SENSOR_WAKE_UP, false /* reportsTouchCoordinates */,
+                    false /* requiresTouchscreen */);
+        }
+
+        @Override
+        @AnyThread
+        public void onTrigger(TriggerEvent event) {
+            DozeLog.traceSensor(mContext, mPulseReason);
+            mHandler.post(mWakeLock.wrap(() -> {
+                if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
+                mRegistered = false;
+                mWakeScreenCallback.accept(event.values[0] > 0);
+                updateListener();  // reregister, this sensor only fires once
+            }));
+        }
+    }
+
     public interface Callback {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 73cbd7d..1589969 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -84,7 +84,7 @@
         mWakeLock = wakeLock;
         mAllowPulseTriggers = allowPulseTriggers;
         mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
-                config, wakeLock, this::onSensor, this::onProximityFar,
+                config, wakeLock, this::onSensor, this::onProximityFar, this::onWakeScreen,
                 dozeParameters.getPolicy());
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
     }
@@ -103,7 +103,7 @@
 
     private void proximityCheckThenCall(IntConsumer callback,
             boolean alreadyPerformedProxCheck,
-            int pulseReason) {
+            int reason) {
         Boolean cachedProxFar = mDozeSensors.isProximityCurrentlyFar();
         if (alreadyPerformedProxCheck) {
             callback.accept(ProximityCheck.RESULT_NOT_CHECKED);
@@ -116,7 +116,7 @@
                 public void onProximityResult(int result) {
                     final long end = SystemClock.uptimeMillis();
                     DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
-                            end - start, pulseReason);
+                            end - start, reason);
                     callback.accept(result);
                 }
             }.check();
@@ -182,6 +182,28 @@
         }
     }
 
+    private void onWakeScreen(boolean wake) {
+        DozeMachine.State state = mMachine.getState();
+        boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
+        boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
+
+        if (wake) {
+            proximityCheckThenCall((result) -> {
+                if (result == ProximityCheck.RESULT_NEAR) {
+                    // In pocket, drop event.
+                    return;
+                }
+                if (pausing || paused) {
+                    mMachine.requestState(DozeMachine.State.DOZE_AOD);
+                }
+            }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
+        } else {
+            if (!pausing && !paused) {
+                mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
+            }
+        }
+    }
+
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         switch (newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 7863245..67aa82d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -158,8 +158,12 @@
             return;
         }
 
-        long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
-        mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+        long time = System.currentTimeMillis();
+        long delta = roundToNextMinute(time) - System.currentTimeMillis();
+        boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+        if (scheduled) {
+            DozeLog.traceTimeTickScheduled(time, time + delta);
+        }
         mLastTimeTickElapsed = SystemClock.elapsedRealtime();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 06d4434..cc1b9e8 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -89,6 +89,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.util.EmergencyDialerConstants;
 import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
 
 import java.util.ArrayList;
@@ -449,9 +450,6 @@
     }
 
     private class EmergencyDialerAction extends SinglePressAction {
-        private static final String ACTION_EMERGENCY_DIALER_DIAL =
-                "com.android.phone.EmergencyDialer.DIAL";
-
         private EmergencyDialerAction() {
             super(R.drawable.ic_faster_emergency,
                     R.string.global_action_emergency);
@@ -460,8 +458,10 @@
         @Override
         public void onPress() {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU);
-            Intent intent = new Intent(ACTION_EMERGENCY_DIALER_DIAL);
+            Intent intent = new Intent(EmergencyDialerConstants.ACTION_DIAL);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+                    EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU);
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4977ff7..1655c01 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -503,9 +503,6 @@
                 case READY:
                     synchronized (KeyguardViewMediator.this) {
                         if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing);
-                        if (mShowing) {
-                            resetStateLocked();
-                        }
                         mLockWhenSimRemoved = true;
                     }
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index ff5ac76..b988c55 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -547,38 +547,23 @@
 
     /**
      * Fades in the updated status text. Note that if there's already a status showing, this will
-     * immediately hide it and fade in the updated status.
+     * immediately fade it out and fade in the updated status.
      */
     private void showStatus() {
         mStatusContainer.setAlpha(0f);
-        mStatusContainer.setVisibility(View.VISIBLE);
 
-        // Animate the alarm back in. Make sure to clear the animator listener for the animation!
         mStatusContainer.animate()
                 .alpha(1f)
                 .setDuration(FADE_ANIMATION_DURATION_MS)
-                .setListener(null)
                 .start();
     }
 
-    /** Fades out and hides the status text. */
+    /** Fades out the status text. */
     private void hideStatusText() {
-        if (mStatusContainer.getVisibility() == View.VISIBLE) {
-            mStatusContainer.animate()
-                    .alpha(0f)
-                    .setListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            if (DEBUG) Log.d(TAG, "hideAlarmText: Hid alarm text");
-
-                            // Reset the alpha regardless of how the animation ends for the next
-                            // time we show this view/want to animate it.
-                            mStatusContainer.setVisibility(View.INVISIBLE);
-                            mStatusContainer.setAlpha(1f);
-                        }
-                    })
-                    .start();
-        }
+        mStatusContainer.animate()
+                .alpha(0f)
+                .setDuration(FADE_ANIMATION_DURATION_MS)
+                .start();
     }
 
     public void updateEverything() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index afd64f3..0d3ba77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -45,7 +45,7 @@
         public void onDisplayBlanked() {
             if (DEBUG) {
                 Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason="
-                        + DozeLog.pulseReasonToString(mPulseReason));
+                        + DozeLog.reasonToString(mPulseReason));
             }
             if (!mDozing) {
                 return;
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
index f7f61af..a791376 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
@@ -44,7 +44,15 @@
         mHandler = handler;
     }
 
-    public void schedule(long timeout, int mode) {
+    /**
+     * Schedules an alarm in {@code timeout} milliseconds in the future.
+     *
+     * @param timeout How long to wait from now.
+     * @param mode {@link #MODE_CRASH_IF_SCHEDULED}, {@link #MODE_IGNORE_IF_SCHEDULED} or
+     *             {@link #MODE_RESCHEDULE_IF_SCHEDULED}.
+     * @return {@code true} when scheduled successfully, {@code false} otherwise.
+     */
+    public boolean schedule(long timeout, int mode) {
         switch (mode) {
             case MODE_CRASH_IF_SCHEDULED:
                 if (mScheduled) {
@@ -53,7 +61,7 @@
                 break;
             case MODE_IGNORE_IF_SCHEDULED:
                 if (mScheduled) {
-                    return;
+                    return false;
                 }
                 break;
             case MODE_RESCHEDULE_IF_SCHEDULED:
@@ -68,6 +76,7 @@
         mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                 SystemClock.elapsedRealtime() + timeout, mTag, this, mHandler);
         mScheduled = true;
+        return true;
     }
 
     public boolean isScheduled() {
diff --git a/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
new file mode 100644
index 0000000..d101ccb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
@@ -0,0 +1,38 @@
+/*
+ * 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.systemui.util;
+
+/**
+ * Constants defined and used in emergency dialer.
+ * Please keep these constants being consistent with those in com.android.phone.EmergencyDialer.
+ */
+public class EmergencyDialerConstants {
+    // Intent action for emergency dialer activity.
+    public static final String ACTION_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+
+    /**
+     * Extra included in {@link #ACTION_DIAL} to indicate the entry type that user starts
+     * the emergency dialer.
+     */
+    public static final String EXTRA_ENTRY_TYPE =
+            "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE";
+
+    // Indicating the entrance to emergency dialer
+    public static final int ENTRY_TYPE_UNKNOWN = 0;
+    public static final int ENTRY_TYPE_LOCKSCREEN_BUTTON = 1;
+    public static final int ENTRY_TYPE_POWER_MENU = 2;
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index b668623..7edcdcb 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -6508,6 +6508,10 @@
     // OS: Q
     ACTION_EMERGENCY_DIALER_FROM_POWER_MENU = 1569;
 
+    // OPEN: Settings > System > Input & Gesture > Wake screen
+    // OS: Q
+    SETTINGS_GESTURE_WAKE_SCREEN = 1570;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/accessibility/TEST_MAPPING b/services/accessibility/TEST_MAPPING
new file mode 100644
index 0000000..320924c
--- /dev/null
+++ b/services/accessibility/TEST_MAPPING
@@ -0,0 +1,105 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsAccessibilityTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsUiAutomationTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.accessibility"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "com.android.internal.accessibility"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsAccessibilityServiceTestCases"
+    },
+    {
+      "name": "CtsAccessibilityTestCases"
+    },
+    {
+      "name": "CtsUiAutomationTestCases"
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.accessibility"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "com.android.internal.accessibility"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "android.view.accessibility"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 50f15ca0..a85b69b 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -399,6 +399,12 @@
 
     private void update(android.hardware.health.V2_0.HealthInfo info) {
         traceBegin("HealthInfoUpdate");
+
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryChargeCounter",
+                info.legacy.batteryChargeCounter);
+        Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent",
+                info.legacy.batteryCurrent);
+
         synchronized (mLock) {
             if (!mUpdatesStopped) {
                 mHealthInfo = info.legacy;
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 9a7c345..15673a7 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -33,7 +33,7 @@
 
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BinderCallsStats;
-import com.android.internal.os.BinderInternal;
+import com.android.internal.os.CachedDeviceState;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -41,7 +41,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Random;
 
 public class BinderCallsStatsService extends Binder {
 
@@ -156,8 +155,10 @@
         @Override
         public void onBootPhase(int phase) {
             if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+                CachedDeviceState.Readonly deviceState = getLocalService(
+                        CachedDeviceState.Readonly.class);
                 mService.systemReady(getContext());
-                mBinderCallsStats.systemReady(getContext());
+                mBinderCallsStats.setDeviceState(deviceState);
             }
         }
     }
diff --git a/services/core/java/com/android/server/CachedDeviceStateService.java b/services/core/java/com/android/server/CachedDeviceStateService.java
new file mode 100644
index 0000000..38269d3
--- /dev/null
+++ b/services/core/java/com/android/server/CachedDeviceStateService.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;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
+import android.util.Slog;
+
+import com.android.internal.os.CachedDeviceState;
+
+/**
+ * Tracks changes to the device state (e.g. charging/on battery, screen on/off) to share it with
+ * the System Server telemetry services.
+ *
+ * @hide Only for use within the system server.
+ */
+public class CachedDeviceStateService extends SystemService {
+    private static final String TAG = "CachedDeviceStateService";
+    private final CachedDeviceState mDeviceState = new CachedDeviceState();
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case Intent.ACTION_BATTERY_CHANGED:
+                    mDeviceState.setCharging(
+                            intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,
+                                    OsProtoEnums.BATTERY_PLUGGED_NONE)
+                                    != OsProtoEnums.BATTERY_PLUGGED_NONE);
+                    break;
+                case Intent.ACTION_SCREEN_ON:
+                    mDeviceState.setScreenInteractive(true);
+                    break;
+                case Intent.ACTION_SCREEN_OFF:
+                    mDeviceState.setScreenInteractive(false);
+                    break;
+            }
+        }
+    };
+
+    public CachedDeviceStateService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        publishLocalService(CachedDeviceState.Readonly.class, mDeviceState.getReadonlyClient());
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+            filter.addAction(Intent.ACTION_SCREEN_ON);
+            filter.addAction(Intent.ACTION_SCREEN_OFF);
+            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+            getContext().registerReceiver(mBroadcastReceiver, filter);
+            mDeviceState.setCharging(queryIsCharging());
+            mDeviceState.setScreenInteractive(queryScreenInteractive(getContext()));
+        }
+    }
+
+    private boolean queryIsCharging() {
+        final BatteryManagerInternal batteryManager =
+                LocalServices.getService(BatteryManagerInternal.class);
+        if (batteryManager == null) {
+            Slog.wtf(TAG, "BatteryManager null while starting CachedDeviceStateService");
+            // Default to true to not collect any data.
+            return true;
+        } else {
+            return batteryManager.getPlugType() != OsProtoEnums.BATTERY_PLUGGED_NONE;
+        }
+    }
+
+    private boolean queryScreenInteractive(Context context) {
+        final PowerManager powerManager = context.getSystemService(PowerManager.class);
+        if (powerManager == null) {
+            Slog.wtf(TAG, "PowerManager null while starting CachedDeviceStateService");
+            return false;
+        } else {
+            return powerManager.isInteractive();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 44dddd1..f981b26 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -127,6 +127,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.IInputContentUriToken;
+import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
 import com.android.internal.inputmethod.InputMethodUtils;
@@ -198,7 +199,7 @@
     static final int MSG_SHOW_SOFT_INPUT = 1020;
     static final int MSG_HIDE_SOFT_INPUT = 1030;
     static final int MSG_HIDE_CURRENT_INPUT_METHOD = 1035;
-    static final int MSG_ATTACH_TOKEN = 1040;
+    static final int MSG_INITIALIZE_IME = 1040;
     static final int MSG_CREATE_SESSION = 1050;
 
     static final int MSG_START_INPUT = 2000;
@@ -1968,7 +1969,7 @@
                 }
                 if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
                 executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
-                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
+                        MSG_INITIALIZE_IME, mCurMethod, mCurToken));
                 if (mCurClient != null) {
                     clearClientSessionLocked(mCurClient);
                     requestClientSessionLocked(mCurClient);
@@ -2217,8 +2218,7 @@
 
     @BinderThread
     @SuppressWarnings("deprecation")
-    @Override
-    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
+    private void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
         if (!calledWithValidToken(token)) {
             return;
         }
@@ -2253,8 +2253,7 @@
     }
 
     @BinderThread
-    @Override
-    public void reportStartInput(IBinder token, IBinder startInputToken) {
+    private void reportStartInput(IBinder token, IBinder startInputToken) {
         if (!calledWithValidToken(token)) {
             return;
         }
@@ -3145,13 +3144,21 @@
         return;
     }
 
+    /**
+     * This is kept due to {@link android.annotation.UnsupportedAppUsage} in
+     * {@link InputMethodManager#getInputMethodWindowVisibleHeight()} and a dependency in
+     * {@link InputMethodService#onCreate()}.
+     *
+     * <p>TODO(Bug 113914148): Check if we can remove this.</p>
+     * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()}
+     */
     @Override
     public int getInputMethodWindowVisibleHeight() {
         return mWindowManagerInternal.getInputMethodWindowVisibleHeight();
     }
 
-    @Override
-    public void clearLastInputMethodWindowForTransition(IBinder token) {
+    @BinderThread
+    private void clearLastInputMethodWindowForTransition(IBinder token) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -3346,11 +3353,13 @@
                     hideCurrentInputLocked(0, null);
                 }
                 return true;
-            case MSG_ATTACH_TOKEN:
+            case MSG_INITIALIZE_IME:
                 args = (SomeArgs)msg.obj;
                 try {
                     if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
-                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
+                    final IBinder token = (IBinder) args.arg2;
+                    ((IInputMethod) args.arg1).initializeInternal(token,
+                            new InputMethodPrivilegedOperationsImpl(this, token));
                 } catch (RemoteException e) {
                 }
                 args.recycle();
@@ -4424,8 +4433,8 @@
         }
     }
 
-    @Override
-    public IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
+    @BinderThread
+    private IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
             @Nullable Uri contentUri, @Nullable String packageName) {
         if (!calledFromValidUser()) {
             return null;
@@ -4482,8 +4491,8 @@
         }
     }
 
-    @Override
-    public void reportFullscreenMode(IBinder token, boolean fullscreen) {
+    @BinderThread
+    private void reportFullscreenMode(IBinder token, boolean fullscreen) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -4958,4 +4967,45 @@
             return ShellCommandResult.SUCCESS;
         }
     }
+
+    private static final class InputMethodPrivilegedOperationsImpl
+            extends IInputMethodPrivilegedOperations.Stub {
+        private final InputMethodManagerService mImms;
+        private final IBinder mToken;
+        InputMethodPrivilegedOperationsImpl(InputMethodManagerService imms, IBinder token) {
+            mImms = imms;
+            mToken = token;
+        }
+
+        @BinderThread
+        @Override
+        public void setImeWindowStatus(int vis, int backDisposition) {
+            mImms.setImeWindowStatus(mToken, vis, backDisposition);
+        }
+
+        @BinderThread
+        @Override
+        public void reportStartInput(IBinder startInputToken) {
+            mImms.reportStartInput(mToken, startInputToken);
+        }
+
+        @BinderThread
+        @Override
+        public void clearLastInputMethodWindowForTransition() {
+            mImms.clearLastInputMethodWindowForTransition(mToken);
+        }
+
+        @BinderThread
+        @Override
+        public IInputContentUriToken createInputContentUriToken(Uri contentUri,
+                String packageName) {
+            return mImms.createInputContentUriToken(mToken, contentUri, packageName);
+        }
+
+        @BinderThread
+        @Override
+        public void reportFullscreenMode(boolean fullscreen) {
+            mImms.reportFullscreenMode(mToken, fullscreen);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index 237e169..23b30cc 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -17,12 +17,21 @@
 package com.android.server;
 
 import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Looper;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
 
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.CachedDeviceState;
 import com.android.internal.os.LooperStats;
 import com.android.internal.util.DumpUtils;
 
@@ -38,6 +47,13 @@
 public class LooperStatsService extends Binder {
     private static final String TAG = "LooperStatsService";
     private static final String LOOPER_STATS_SERVICE_NAME = "looper_stats";
+    private static final String SETTINGS_ENABLED_KEY = "enabled";
+    private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
+    private static final String DEBUG_SYS_LOOPER_STATS_ENABLED =
+            "debug.sys.looper_stats_enabled";
+    private static final int DEFAULT_SAMPLING_INTERVAL = 100;
+    private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
+    private static final boolean DEFAULT_ENABLED = false;
 
     private final Context mContext;
     private final LooperStats mStats;
@@ -48,6 +64,24 @@
         this.mStats = stats;
     }
 
+    private void initFromSettings() {
+        final KeyValueListParser parser = new KeyValueListParser(',');
+
+        try {
+            parser.setString(Settings.Global.getString(mContext.getContentResolver(),
+                    Settings.Global.LOOPER_STATS));
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Bad looper_stats settings", e);
+        }
+
+        setSamplingInterval(
+                parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL));
+        // Manually specified value takes precedence over Settings.
+        setEnabled(SystemProperties.getBoolean(
+                DEBUG_SYS_LOOPER_STATS_ENABLED,
+                parser.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED)));
+    }
+
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
             String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
@@ -66,6 +100,7 @@
                 "thread_name",
                 "handler_class",
                 "message_name",
+                "is_interactive",
                 "message_count",
                 "recorded_message_count",
                 "total_latency_micros",
@@ -75,10 +110,11 @@
                 "exception_count"));
         pw.println(header);
         for (LooperStats.ExportedEntry entry : entries) {
-            pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.threadName, entry.handlerClassName,
-                    entry.messageName, entry.messageCount, entry.recordedMessageCount,
-                    entry.totalLatencyMicros, entry.maxLatencyMicros, entry.cpuUsageMicros,
-                    entry.maxCpuUsageMicros, entry.exceptionCount);
+            pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.threadName,
+                    entry.handlerClassName, entry.messageName, entry.isInteractive,
+                    entry.messageCount, entry.recordedMessageCount, entry.totalLatencyMicros,
+                    entry.maxLatencyMicros, entry.cpuUsageMicros, entry.maxCpuUsageMicros,
+                    entry.exceptionCount);
         }
     }
 
@@ -90,20 +126,55 @@
         }
     }
 
+    private void setSamplingInterval(int samplingInterval) {
+        mStats.setSamplingInterval(samplingInterval);
+    }
+
     /**
      * Manages the lifecycle of LooperStatsService within System Server.
      */
     public static class Lifecycle extends SystemService {
+        private final SettingsObserver mSettingsObserver;
+        private final LooperStatsService mService;
+        private final LooperStats mStats;
+
         public Lifecycle(Context context) {
             super(context);
+            mStats = new LooperStats(DEFAULT_SAMPLING_INTERVAL, DEFAULT_ENTRIES_SIZE_CAP);
+            mService = new LooperStatsService(getContext(), mStats);
+            mSettingsObserver = new SettingsObserver(mService);
         }
 
         @Override
         public void onStart() {
-            LooperStats stats = new LooperStats();
-            publishLocalService(LooperStats.class, stats);
+            publishLocalService(LooperStats.class, mStats);
             // TODO: publish LooperStatsService as a binder service when the SE Policy is changed.
         }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+                mService.initFromSettings();
+                Uri settingsUri = Settings.Global.getUriFor(Settings.Global.LOOPER_STATS);
+                getContext().getContentResolver().registerContentObserver(
+                        settingsUri, false, mSettingsObserver, UserHandle.USER_SYSTEM);
+                mStats.setDeviceState(getLocalService(CachedDeviceState.Readonly.class));
+            }
+        }
+    }
+
+    private static class SettingsObserver extends ContentObserver {
+        private final LooperStatsService mService;
+
+        SettingsObserver(LooperStatsService service) {
+            super(BackgroundThread.getHandler());
+            mService = service;
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            mService.initFromSettings();
+        }
     }
 
     private class LooperShellCommand extends ShellCommand {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b91a449..e6ff0d8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17061,7 +17061,7 @@
             activeInstr.mUiAutomationConnection = uiAutomationConnection;
             activeInstr.mResultClass = className;
 
-            boolean disableHiddenApiChecks = ai.usesNonSdkApi
+            boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                     || (flags & INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
             if (disableHiddenApiChecks) {
                 enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 9de6875..b24c36a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
 import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -302,7 +303,9 @@
         mSamplingInterval = 0;
         mAutoStop = false;
         mStreaming = false;
-        mUserId = defUser;
+        mUserId = mInternal.mUserController.handleIncomingUser(Binder.getCallingPid(),
+            Binder.getCallingUid(), defUser, false, ALLOW_FULL_ONLY,
+            "ActivityManagerShellCommand", null);
         mDisplayId = INVALID_DISPLAY;
         mWindowingMode = WINDOWING_MODE_UNDEFINED;
         mActivityType = ACTIVITY_TYPE_UNDEFINED;
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 11f8bb1..7eadcb3 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -27,17 +27,7 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.Manifest.permission.STOP_APP_SWITCHES;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.content.pm.PackageManager.FEATURE_PC;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
-import static android.provider.Settings.System.FONT_SCALE;
-import static com.android.server.am.ActivityManagerService.dumpStackTraces;
-import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
-import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
 import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.AppOpsManager.OP_NONE;
@@ -51,15 +41,19 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
 import static android.os.Build.VERSION_CODES.N;
 import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
+import static android.provider.Settings.System.FONT_SCALE;
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
@@ -68,6 +62,7 @@
 import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -86,13 +81,13 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static com.android.server.am.ActivityManagerService.ANIMATE;
 import static com.android.server.am.ActivityManagerService.MY_PID;
 import static com.android.server.am.ActivityManagerService.SEND_LOCALE_TO_MOUNT_DAEMON_MSG;
 import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
 import static com.android.server.am.ActivityManagerService.UPDATE_CONFIGURATION_MSG;
 import static com.android.server.am.ActivityManagerService.checkComponentPermission;
+import static com.android.server.am.ActivityManagerService.dumpStackTraces;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
@@ -100,10 +95,16 @@
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
+import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
 
@@ -118,26 +119,8 @@
 import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
 import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.database.ContentObserver;
-import android.os.IUserManager;
-import android.os.PowerManager;
-import android.os.ServiceManager;
-import android.os.Trace;
-import android.os.UserManager;
-import android.os.WorkSource;
-import android.view.WindowManager;
-import com.android.internal.R;
-import com.android.internal.app.IAppOpsService;
-import com.android.server.AppOpsService;
-import com.android.server.SystemServiceManager;
-import com.android.server.pm.UserManagerService;
-import com.android.server.uri.UriGrantsManagerInternal;
-import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
+import android.app.Dialog;
 import android.app.IActivityController;
 import android.app.IActivityTaskManager;
 import android.app.IApplicationThread;
@@ -157,15 +140,19 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -177,16 +164,22 @@
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IUserManager;
 import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
+import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UpdateLock;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.WorkSource;
 import android.provider.Settings;
 import android.service.voice.IVoiceInteractionSession;
 import android.service.voice.VoiceInteractionManagerInternal;
@@ -197,7 +190,6 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
-
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.StatsLog;
@@ -206,22 +198,30 @@
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
+import android.view.WindowManager;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
+import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.ProcessMap;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.KeyguardDismissCallback;
 import com.android.internal.util.Preconditions;
+import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
 import com.android.server.Watchdog;
+import com.android.server.pm.UserManagerService;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.PinnedStackWindowController;
 import com.android.server.wm.WindowManagerService;
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index bc23316..0a7e127 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -414,7 +414,11 @@
         if (state == BroadcastRecord.IDLE) {
             Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
         }
-        r.duration[r.nextReceiver - 1] = finishTime - r.receiverTime;
+        // If we're abandoning this broadcast before any receivers were actually spun up,
+        // nextReceiver is zero; in which case time-to-process bookkeeping doesn't apply.
+        if (r.nextReceiver > 0) {
+            r.duration[r.nextReceiver - 1] = finishTime - r.receiverTime;
+        }
         r.receiver = null;
         r.intent.setComponent(null);
         if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 2750dc1..a050aa9 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -20,25 +20,6 @@
 import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
 
 import android.annotation.NonNull;
-import android.os.LocaleList;
-import android.os.ShellCallback;
-import android.util.Log;
-import android.view.Display;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.R;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
-import com.android.server.DisplayThread;
-import com.android.server.LocalServices;
-import com.android.server.Watchdog;
-import com.android.server.policy.WindowManagerPolicy;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.Manifest;
 import android.app.IInputForwarder;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -53,8 +34,8 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.TypedArray;
@@ -64,10 +45,10 @@
 import android.hardware.display.DisplayViewport;
 import android.hardware.input.IInputDevicesChangedListener;
 import android.hardware.input.IInputManager;
+import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManagerInternal;
-import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.KeyboardLayout;
 import android.hardware.input.TouchCalibration;
 import android.os.Binder;
@@ -75,6 +56,7 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
@@ -84,6 +66,7 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -100,6 +83,23 @@
 import android.view.ViewConfiguration;
 import android.widget.Toast;
 
+import com.android.internal.R;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+import com.android.server.DisplayThread;
+import com.android.server.LocalServices;
+import com.android.server.Watchdog;
+import com.android.server.policy.WindowManagerPolicy;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import org.xmlpull.v1.XmlPullParser;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -116,9 +116,6 @@
 import java.util.Locale;
 import java.util.Objects;
 
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
 /*
  * Wraps the C++ InputManager and provides its callbacks.
  */
@@ -215,7 +212,8 @@
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
             int policyFlags);
     private static native void nativeToggleCapsLock(long ptr, int deviceId);
-    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
+    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles,
+            int displayId);
     private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
     private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
     private static native void nativeSetFocusedApplication(long ptr,
@@ -1465,7 +1463,7 @@
     }
 
     public void setInputWindows(InputWindowHandle[] windowHandles,
-            InputWindowHandle focusedWindowHandle) {
+            InputWindowHandle focusedWindowHandle, int displayId) {
         final IWindow newFocusedWindow =
             focusedWindowHandle != null ? focusedWindowHandle.clientWindow : null;
         if (mFocusedWindow != newFocusedWindow) {
@@ -1474,7 +1472,7 @@
                 setPointerCapture(false);
             }
         }
-        nativeSetInputWindows(mPtr, windowHandles);
+        nativeSetInputWindows(mPtr, windowHandles, displayId);
     }
 
     public void setFocusedApplication(InputApplicationHandle application) {
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java
index 720eaaa5..bb29bf8 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/services/core/java/com/android/server/input/InputWindowHandle.java
@@ -17,8 +17,8 @@
 package com.android.server.input;
 
 import android.graphics.Region;
-import android.view.InputChannel;
 import android.view.IWindow;
+import android.view.InputChannel;
 
 /**
  * Functions as a handle for a window that can receive input.
@@ -106,7 +106,7 @@
 
     @Override
     public String toString() {
-        return new StringBuilder(name)
+        return new StringBuilder(name != null ? name : "")
                 .append(", layer=").append(layer)
                 .append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
                         .append(frameRight).append(",").append(frameBottom).append("]")
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b775918..6da9f10 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -32,29 +32,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-
+import static android.view.WindowManager.TRANSIT_UNSET;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_UNSET;
-
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.logWithStack;
 import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
 import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
 import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
@@ -78,6 +60,23 @@
 import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
 import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
 import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.logWithStack;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 
 import android.annotation.CallSuper;
@@ -1845,8 +1844,8 @@
             surfaceInsets = win.getAttrs().surfaceInsets;
             // XXX(b/72757033): These are insets relative to the window frame, but we're really
             // interested in the insets relative to the frame we chose in the if-blocks above.
-            insets.set(win.mContentInsets);
-            stableInsets.set(win.mStableInsets);
+            win.getContentInsets(insets);
+            win.getStableInsets(stableInsets);
         }
 
         if (mLaunchTaskBehind) {
@@ -2099,7 +2098,7 @@
         WindowState win = findMainWindow();
         Rect appRect = win != null ? win.getContentFrameLw() :
                 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
-        Rect insets = win != null ? win.mContentInsets : null;
+        final Rect insets = win != null ? win.getContentInsets() : null;
         final Configuration displayConfig = mDisplayContent.getConfiguration();
         return mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(
                 appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9490ae2..d3e534c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -814,9 +814,7 @@
         // {@link DisplayContent} ready for use.
         mDisplayReady = true;
 
-        // TODO(b/112081256): Use independent InputMonitor.
-        mInputMonitor = isDefaultDisplay ? new InputMonitor(service, mDisplayId)
-                : mService.getDefaultDisplayContentLocked().mInputMonitor;
+        mInputMonitor = new InputMonitor(service, mDisplayId);
     }
 
     boolean isReady() {
@@ -2185,6 +2183,7 @@
             mRemovingDisplay = false;
         }
 
+        mInputMonitor.onRemoved();
         mService.onDisplayRemoved(mDisplayId);
     }
 
@@ -3009,7 +3008,7 @@
             if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
                 w.mWinAnimator.mDrawState = DRAW_PENDING;
                 // Force add to mResizingWindows.
-                w.mLastContentInsets.set(-1, -1, -1, -1);
+                w.resetLastContentInsets();
                 mService.mWaitingForDrawn.add(w);
             }
         }, true /* traverseTopToBottom */);
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 6a08f4d..585a4f5 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -20,9 +20,9 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.view.Display;
 import android.view.InputChannel;
 import android.view.WindowManager;
+
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index c4beb55..3309798 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -367,6 +367,13 @@
         }
     }
 
+    void onRemoved() {
+        // If DisplayContent removed, we need find a way to remove window handles of this display
+        // from InputDispatcher, so pass an empty InputWindowHandles to remove them.
+        mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+                mDisplayId);
+    }
+
     private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
         InputConsumerImpl navInputConsumer;
         InputConsumerImpl pipInputConsumer;
@@ -399,8 +406,7 @@
             this.inDrag = inDrag;
             wallpaperController = mService.mRoot.mWallpaperController;
 
-            // TODO(b/112081256): Use independent InputMonitor for each display.
-            mService.mRoot/*.getDisplayContent(mDisplayId)*/.forAllWindows(this,
+            mService.mRoot.getDisplayContent(mDisplayId).forAllWindows(this,
                     true /* traverseTopToBottom */);
             if (mAddWallpaperInputConsumerHandle) {
                 // No visible wallpaper found, add the wallpaper input consumer at the end.
@@ -408,8 +414,8 @@
             }
 
             // Send windows to native code.
-            // TODO: Update Input windows and focus by display?
-            mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
+            mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+                    mDisplayId);
 
             clearInputWindowHandlesLw();
 
@@ -429,7 +435,8 @@
             final int flags = w.mAttrs.flags;
             final int privateFlags = w.mAttrs.privateFlags;
             final int type = w.mAttrs.type;
-            final boolean hasFocus = w == mInputFocus;
+            // TODO(b/111361570): multi-display focus, one focus window per display.
+            final boolean hasFocus = w.isFocused();
             final boolean isVisible = w.isVisibleLw();
 
             if (mAddRecentsAnimationInputConsumerHandle) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 4dbd858..1eae567 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -373,7 +373,7 @@
                             : null;
             final Rect contentInsets;
             if (mTargetAppToken != null && mTargetAppToken.findMainWindow() != null) {
-                contentInsets = mTargetAppToken.findMainWindow().mContentInsets;
+                contentInsets = mTargetAppToken.findMainWindow().getContentInsets();
             } else {
                 // If the window for the activity had not yet been created, use the display insets.
                 mService.getStableInsets(mDisplayId, mTmpRect);
@@ -583,7 +583,8 @@
             if (mainWindow == null) {
                 return null;
             }
-            final Rect insets = new Rect(mainWindow.mContentInsets);
+            final Rect insets = new Rect();
+            mainWindow.getContentInsets(insets);
             InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
                     !topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 67ef471..00422e3 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -305,7 +305,8 @@
                     || mCapturedLeash == null) {
                 return null;
             }
-            final Rect insets = new Rect(mainWindow.mContentInsets);
+            final Rect insets = new Rect();
+            mainWindow.getContentInsets(insets);
             InsetUtils.addInsets(insets, mAppWindowToken.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
                     mCapturedLeash, !mAppWindowToken.fillsParent(),
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 6c8572a..b7507a4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -303,7 +303,7 @@
     private Rect getInsets(WindowState state) {
         // XXX(b/72757033): These are insets relative to the window frame, but we're really
         // interested in the insets relative to the task bounds.
-        final Rect insets = minRect(state.mContentInsets, state.mStableInsets);
+        final Rect insets = minRect(state.getContentInsets(), state.getStableInsets());
         InsetUtils.addInsets(insets, state.mAppToken.getLetterboxInsets());
         return insets;
     }
@@ -373,7 +373,7 @@
         node.setClipToBounds(false);
         final DisplayListCanvas c = node.start(width, height);
         c.drawColor(color);
-        decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
+        decorPainter.setInsets(mainWindow.getContentInsets(), mainWindow.getStableInsets());
         decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
         node.end(c);
         final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
@@ -383,7 +383,7 @@
         // Note, the app theme snapshot is never translucent because we enforce a non-translucent
         // color above
         return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
-                topChild.getConfiguration().orientation, mainWindow.mStableInsets,
+                topChild.getConfiguration().orientation, mainWindow.getStableInsets(),
                 ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
                 false /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
                 false);
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 228bfad..9381fc6 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -18,20 +18,27 @@
 
 import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME;
 import static com.android.server.wm.WindowFramesProto.CONTENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.CONTENT_INSETS;
 import static com.android.server.wm.WindowFramesProto.CUTOUT;
 import static com.android.server.wm.WindowFramesProto.DECOR_FRAME;
 import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME;
 import static com.android.server.wm.WindowFramesProto.FRAME;
+import static com.android.server.wm.WindowFramesProto.OUTSETS;
 import static com.android.server.wm.WindowFramesProto.OUTSET_FRAME;
 import static com.android.server.wm.WindowFramesProto.OVERSCAN_FRAME;
+import static com.android.server.wm.WindowFramesProto.OVERSCAN_INSETS;
 import static com.android.server.wm.WindowFramesProto.PARENT_FRAME;
+import static com.android.server.wm.WindowFramesProto.STABLE_INSETS;
 import static com.android.server.wm.WindowFramesProto.VISIBLE_FRAME;
+import static com.android.server.wm.WindowFramesProto.VISIBLE_INSETS;
 
 import android.annotation.NonNull;
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayCutout;
+import android.view.WindowManager;
 
+import com.android.server.wm.utils.InsetUtils;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import java.io.PrintWriter;
@@ -60,7 +67,7 @@
      *
      * TODO(b/111611553): The name is unclear and most likely should be swapped with
      * {@link #mParentFrame}
-    */
+     */
     public final Rect mDisplayFrame = new Rect();
 
     /**
@@ -118,6 +125,12 @@
      */
     final Rect mLastFrame = new Rect();
 
+    private boolean mFrameSizeChanged = false;
+
+    // Frame that is scaled to the application's coordinate space when in
+    // screen size compatibility mode.
+    final Rect mCompatFrame = new Rect();
+
     /**
      * Whether the parent frame would have been different if there was no display cutout.
      */
@@ -131,7 +144,52 @@
     /**
      * The last cutout that has been reported to the client.
      */
-    WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+    private WmDisplayCutout mLastDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+
+    private boolean mDisplayCutoutChanged;
+
+    /**
+     * Insets that determine the area covered by the display overscan region.  These are in the
+     * application's coordinate space (without compatibility scale applied).
+     */
+    final Rect mOverscanInsets = new Rect();
+    final Rect mLastOverscanInsets = new Rect();
+    private boolean mOverscanInsetsChanged;
+
+    /**
+     * Insets that determine the area covered by the stable system windows.  These are in the
+     * application's coordinate space (without compatibility scale applied).
+     */
+    final Rect mStableInsets = new Rect();
+    final Rect mLastStableInsets = new Rect();
+    private boolean mStableInsetsChanged;
+
+    /**
+     * Outsets determine the area outside of the surface where we want to pretend that it's possible
+     * to draw anyway.
+     */
+    final Rect mOutsets = new Rect();
+    final Rect mLastOutsets = new Rect();
+    private boolean mOutsetsChanged = false;
+
+    /**
+     * Insets that determine the actually visible area.  These are in the application's
+     * coordinate space (without compatibility scale applied).
+     */
+    final Rect mVisibleInsets = new Rect();
+    final Rect mLastVisibleInsets = new Rect();
+    private boolean mVisibleInsetsChanged;
+
+    /**
+     * Insets that are covered by system windows (such as the status bar) and
+     * transient docking windows (such as the IME).  These are in the application's
+     * coordinate space (without compatibility scale applied).
+     */
+    final Rect mContentInsets = new Rect();
+    final Rect mLastContentInsets = new Rect();
+    private boolean mContentInsetsChanged;
+
+    private final Rect mTmpRect = new Rect();
 
     public WindowFrames() {
     }
@@ -171,15 +229,141 @@
     /**
      * @return true if the width or height has changed since last reported to the client.
      */
-    boolean didFrameSizeChange() {
+    private boolean didFrameSizeChange() {
         return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
     }
 
     /**
-     * @return true if the display cutout has changed since last reported to the client.
+     * Calculates the outsets for this windowFrame. The outsets are calculated by the area between
+     * the {@link #mOutsetFrame} and the {@link #mContentFrame}. If there are no outsets, then
+     * {@link #mOutsets} is set to empty.
+     *
+     * @param hasOutsets Whether this frame has outsets.
      */
-    boolean didDisplayCutoutChange() {
-        return !mLastDisplayCutout.equals(mDisplayCutout);
+    void calculateOutsets(boolean hasOutsets) {
+        if (hasOutsets) {
+            InsetUtils.insetsBetweenFrames(mOutsetFrame, mContentFrame, mOutsets);
+        } else {
+            mOutsets.setEmpty();
+        }
+    }
+
+    /**
+     * Calculate the insets for the type {@link WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
+     *
+     * @param cutoutInsets The insets for the cutout.
+     */
+    void calculateDockedDividerInsets(Rect cutoutInsets) {
+        // For the docked divider, we calculate the stable insets like a full-screen window
+        // so it can use it to calculate the snap positions.
+        mTmpRect.set(mDisplayFrame);
+        mTmpRect.inset(cutoutInsets);
+        mTmpRect.intersectUnchecked(mStableFrame);
+        InsetUtils.insetsBetweenFrames(mDisplayFrame, mTmpRect, mStableInsets);
+
+        // The divider doesn't care about insets in any case, so set it to empty so we don't
+        // trigger a relayout when moving it.
+        mContentInsets.setEmpty();
+        mVisibleInsets.setEmpty();
+        mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
+    }
+
+    /**
+     * Calculate the insets for a window.
+     *
+     * @param windowsAreFloating    Whether the window is in a floating task such as pinned or
+     *                              freeform
+     * @param inFullscreenContainer Whether the window is in a container that takes up the screen's
+     *                              entire space
+     * @param windowBounds          The bounds for the window
+     */
+    void calculateInsets(boolean windowsAreFloating, boolean inFullscreenContainer,
+            Rect windowBounds) {
+        // Override right and/or bottom insets in case if the frame doesn't fit the screen in
+        // non-fullscreen mode.
+        boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
+                && mFrame.right > windowBounds.right;
+        boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
+                && mFrame.bottom > windowBounds.bottom;
+
+        mTmpRect.set(mFrame.left, mFrame.top, overrideRightInset ? mTmpRect.right : mFrame.right,
+                overrideBottomInset ? mTmpRect.bottom : mFrame.bottom);
+
+        InsetUtils.insetsBetweenFrames(mTmpRect, mContentFrame, mContentInsets);
+        InsetUtils.insetsBetweenFrames(mTmpRect, mVisibleFrame, mVisibleInsets);
+        InsetUtils.insetsBetweenFrames(mTmpRect, mStableFrame, mStableInsets);
+    }
+
+    /**
+     * Scales all the insets by a specific amount.
+     *
+     * @param scale The amount to scale the insets by.
+     */
+    void scaleInsets(float scale) {
+        mOverscanInsets.scale(scale);
+        mContentInsets.scale(scale);
+        mVisibleInsets.scale(scale);
+        mStableInsets.scale(scale);
+        mOutsets.scale(scale);
+    }
+
+    void offsetFrames(int layoutXDiff, int layoutYDiff) {
+        mFrame.offset(layoutXDiff, layoutYDiff);
+        mContentFrame.offset(layoutXDiff, layoutYDiff);
+        mVisibleFrame.offset(layoutXDiff, layoutYDiff);
+        mStableFrame.offset(layoutXDiff, layoutYDiff);
+    }
+
+    /**
+     * Updates info about whether the size of the window has changed since last reported.
+     *
+     * @return true if info about size has changed since last reported.
+     */
+    boolean setReportResizeHints() {
+        mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
+        mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
+        mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
+        mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
+        mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
+        mFrameSizeChanged |= didFrameSizeChange();
+        mDisplayCutoutChanged |= !mLastDisplayCutout.equals(mDisplayCutout);
+        return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
+                || mStableInsetsChanged || mOutsetsChanged || mFrameSizeChanged
+                || mDisplayCutoutChanged;
+    }
+
+    /**
+     * Resets the insets changed flags so they're all set to false again. This should be called
+     * after the insets are reported to client.
+     */
+    void resetInsetsChanged() {
+        mOverscanInsetsChanged = false;
+        mContentInsetsChanged = false;
+        mVisibleInsetsChanged = false;
+        mStableInsetsChanged = false;
+        mOutsetsChanged = false;
+        mFrameSizeChanged = false;
+        mDisplayCutoutChanged = false;
+    }
+
+    /**
+     * Copy over inset values as the last insets that were sent to the client.
+     */
+    void updateLastInsetValues() {
+        mLastOverscanInsets.set(mOverscanInsets);
+        mLastContentInsets.set(mContentInsets);
+        mLastVisibleInsets.set(mVisibleInsets);
+        mLastStableInsets.set(mStableInsets);
+        mLastOutsets.set(mOutsets);
+        mLastDisplayCutout = mDisplayCutout;
+    }
+
+    /**
+     * Sets the last content insets as (-1, -1, -1, -1) to force the next layout pass to update
+     * the client.
+     */
+    void resetLastContentInsets() {
+        mLastContentInsets.set(-1, -1, -1, -1);
     }
 
     public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) {
@@ -194,6 +378,12 @@
         mContainingFrame.writeToProto(proto, CONTAINING_FRAME);
         mFrame.writeToProto(proto, FRAME);
         mDisplayCutout.getDisplayCutout().writeToProto(proto, CUTOUT);
+        mContentInsets.writeToProto(proto, CONTENT_INSETS);
+        mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
+        mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
+        mStableInsets.writeToProto(proto, STABLE_INSETS);
+        mOutsets.writeToProto(proto, OUTSETS);
+
         proto.end(token);
     }
 
@@ -211,5 +401,34 @@
                 + " last=" + mLastFrame.toShortString(sTmpSB));
         pw.println(prefix + " cutout=" + mDisplayCutout.getDisplayCutout()
                 + " last=" + mLastDisplayCutout.getDisplayCutout());
+        pw.print(prefix + "Cur insets: overscan=" + mOverscanInsets.toShortString(sTmpSB)
+                + " content=" + mContentInsets.toShortString(sTmpSB)
+                + " visible=" + mVisibleInsets.toShortString(sTmpSB)
+                + " stable=" + mStableInsets.toShortString(sTmpSB)
+                + " outsets=" + mOutsets.toShortString(sTmpSB));
+        pw.println(prefix + "Lst insets: overscan=" + mLastOverscanInsets.toShortString(sTmpSB)
+                + " content=" + mLastContentInsets.toShortString(sTmpSB)
+                + " visible=" + mLastVisibleInsets.toShortString(sTmpSB)
+                + " stable=" + mLastStableInsets.toShortString(sTmpSB)
+                + " outset=" + mLastOutsets.toShortString(sTmpSB));
+    }
+
+    String getInsetsInfo() {
+        return "ci=" + mContentInsets.toShortString()
+                + " vi=" + mVisibleInsets.toShortString()
+                + " si=" + mStableInsets.toShortString()
+                + " of=" + mOutsets.toShortString();
+    }
+
+    String getInsetsChangedInfo() {
+        return "contentInsetsChanged=" + mContentInsetsChanged
+                + " " + mContentInsets.toShortString()
+                + " visibleInsetsChanged=" + mVisibleInsetsChanged
+                + " " + mVisibleInsets.toShortString()
+                + " stableInsetsChanged=" + mStableInsetsChanged
+                + " " + mStableInsets.toShortString()
+                + " outsetsChanged=" + mOutsetsChanged
+                + " " + mOutsets.toShortString()
+                + " displayCutoutChanged=" + mDisplayCutoutChanged;
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2a381ac..679e0d8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2168,14 +2168,10 @@
             // The last inset values represent the last client state.
             win.updateLastInsetValues();
 
-            outFrame.set(win.mCompatFrame);
-            outOverscanInsets.set(win.mOverscanInsets);
-            outContentInsets.set(win.mContentInsets);
-            win.mLastRelayoutContentInsets.set(win.mContentInsets);
-            outVisibleInsets.set(win.mVisibleInsets);
-            outStableInsets.set(win.mStableInsets);
+            win.getCompatFrame(outFrame);
+            win.getInsetsForRelayout(outOverscanInsets, outContentInsets, outVisibleInsets,
+                    outStableInsets, outOutsets);
             outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
-            outOutsets.set(win.mOutsets);
             outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
             if (localLOGV) Slog.v(
                 TAG_WM, "Relayout given client " + client.asBinder()
@@ -6008,11 +6004,10 @@
     }
 
     @Override
-    public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
+    public void createInputConsumer(IBinder token, String name, int displayId,
+            InputChannel inputChannel) {
         synchronized (mWindowMap) {
-            // TODO(b/112049699): Fix this for multiple displays. There is only one inputChannel
-            // here to accept the return value.
-            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            DisplayContent display = mRoot.getDisplayContent(displayId);
             if (display != null) {
                 display.getInputMonitor().createInputConsumer(token, name, inputChannel,
                         Binder.getCallingPid(), Binder.getCallingUserHandle());
@@ -6021,11 +6016,9 @@
     }
 
     @Override
-    public boolean destroyInputConsumer(String name) {
+    public boolean destroyInputConsumer(String name, int displayId) {
         synchronized (mWindowMap) {
-            // TODO(b/112049699): Fix this for multiple displays. For consistency with
-            // createInputConsumer above.
-            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            DisplayContent display = mRoot.getDisplayContent(displayId);
             if (display != null) {
                 return display.getInputMonitor().destroyInputConsumer(name);
             }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 466e298..637c0ea 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -120,7 +120,6 @@
 import static com.android.server.wm.WindowStateProto.ANIMATOR;
 import static com.android.server.wm.WindowStateProto.ATTRIBUTES;
 import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS;
-import static com.android.server.wm.WindowStateProto.CONTENT_INSETS;
 import static com.android.server.wm.WindowStateProto.DESTROYING;
 import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
 import static com.android.server.wm.WindowStateProto.FINISHED_SEAMLESS_ROTATION_FRAME;
@@ -131,20 +130,16 @@
 import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
 import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
-import static com.android.server.wm.WindowStateProto.OUTSETS;
-import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
 import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION;
 import static com.android.server.wm.WindowStateProto.REMOVED;
 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
 import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH;
-import static com.android.server.wm.WindowStateProto.STABLE_INSETS;
 import static com.android.server.wm.WindowStateProto.STACK_ID;
 import static com.android.server.wm.WindowStateProto.SURFACE_INSETS;
 import static com.android.server.wm.WindowStateProto.SURFACE_POSITION;
 import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY;
 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
-import static com.android.server.wm.WindowStateProto.VISIBLE_INSETS;
 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
 
@@ -200,6 +195,7 @@
 import com.android.server.input.InputWindowHandle;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import com.android.server.wm.utils.InsetUtils;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import java.io.PrintWriter;
@@ -309,22 +305,6 @@
     private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration();
 
     /**
-     * Insets that determine the actually visible area.  These are in the application's
-     * coordinate space (without compatibility scale applied).
-     */
-    final Rect mVisibleInsets = new Rect();
-    private final Rect mLastVisibleInsets = new Rect();
-    private boolean mVisibleInsetsChanged;
-
-    /**
-     * Insets that are covered by system windows (such as the status bar) and
-     * transient docking windows (such as the IME).  These are in the application's
-     * coordinate space (without compatibility scale applied).
-     */
-    final Rect mContentInsets = new Rect();
-    final Rect mLastContentInsets = new Rect();
-
-    /**
      * The last content insets returned to the client in relayout. We use
      * these in the bounds animation to ensure we only observe inset changes
      * at the same time that a client resizes it's surface so that we may use
@@ -333,34 +313,6 @@
      */
     final Rect mLastRelayoutContentInsets = new Rect();
 
-    private boolean mContentInsetsChanged;
-
-    /**
-     * Insets that determine the area covered by the display overscan region.  These are in the
-     * application's coordinate space (without compatibility scale applied).
-     */
-    final Rect mOverscanInsets = new Rect();
-    private final Rect mLastOverscanInsets = new Rect();
-    private boolean mOverscanInsetsChanged;
-
-    /**
-     * Insets that determine the area covered by the stable system windows.  These are in the
-     * application's coordinate space (without compatibility scale applied).
-     */
-    final Rect mStableInsets = new Rect();
-    private final Rect mLastStableInsets = new Rect();
-    private boolean mStableInsetsChanged;
-
-    /**
-     * Outsets determine the area outside of the surface where we want to pretend that it's possible
-     * to draw anyway.
-     */
-    final Rect mOutsets = new Rect();
-    private final Rect mLastOutsets = new Rect();
-    private boolean mOutsetsChanged = false;
-
-    private boolean mDisplayCutoutChanged;
-
     /**
      * Set to true if we are waiting for this window to receive its
      * given internal insets before laying out other windows based on it.
@@ -399,11 +351,6 @@
     float mLastHScale=1, mLastVScale=1;
     final Matrix mTmpMatrix = new Matrix();
 
-    private boolean mFrameSizeChanged = false;
-    // Frame that is scaled to the application's coordinate space when in
-    // screen size compatibility mode.
-    final Rect mCompatFrame = new Rect();
-
     private final WindowFrames mWindowFrames = new WindowFrames();
 
     /**
@@ -988,17 +935,7 @@
         applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
 
         // Calculate the outsets before the content frame gets shrinked to the window frame.
-        if (hasOutsets) {
-            mOutsets.set(
-                    Math.max(mWindowFrames.mContentFrame.left - mWindowFrames.mOutsetFrame.left, 0),
-                    Math.max(mWindowFrames.mContentFrame.top - mWindowFrames.mOutsetFrame.top, 0),
-                    Math.max(mWindowFrames.mOutsetFrame.right - mWindowFrames.mContentFrame.right,
-                            0),
-                    Math.max(mWindowFrames.mOutsetFrame.bottom - mWindowFrames.mContentFrame.bottom,
-                            0));
-        } else {
-            mOutsets.set(0, 0, 0, 0);
-        }
+        mWindowFrames.calculateOutsets(hasOutsets);
 
         // Make sure the content and visible frames are inside of the
         // final window frame.
@@ -1055,90 +992,35 @@
         if (inFullscreenContainer && !windowsAreFloating) {
             // Windows that are not fullscreen can be positioned outside of the display frame,
             // but that is not a reason to provide them with overscan insets.
-            mOverscanInsets.set(
-                    Math.max(mWindowFrames.mOverscanFrame.left - layoutContainingFrame.left, 0),
-                    Math.max(mWindowFrames.mOverscanFrame.top - layoutContainingFrame.top, 0),
-                    Math.max(layoutContainingFrame.right - mWindowFrames.mOverscanFrame.right, 0),
-                    Math.max(layoutContainingFrame.bottom - mWindowFrames.mOverscanFrame.bottom,
-                            0));
+            InsetUtils.insetsBetweenFrames(layoutContainingFrame, mWindowFrames.mOverscanFrame,
+                    mWindowFrames.mOverscanInsets);
         }
 
         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
-            // For the docked divider, we calculate the stable insets like a full-screen window
-            // so it can use it to calculate the snap positions.
             final WmDisplayCutout c = windowFrames.mDisplayCutout.calculateRelativeTo(
                     mWindowFrames.mDisplayFrame);
-            mTmpRect.set(mWindowFrames.mDisplayFrame);
-            mTmpRect.inset(c.getDisplayCutout().getSafeInsets());
-            mTmpRect.intersectUnchecked(mWindowFrames.mStableFrame);
-
-            mStableInsets.set(Math.max(mTmpRect.left - mWindowFrames.mDisplayFrame.left, 0),
-                    Math.max(mTmpRect.top - mWindowFrames.mDisplayFrame.top, 0),
-                    Math.max(mWindowFrames.mDisplayFrame.right - mTmpRect.right, 0),
-                    Math.max(mWindowFrames.mDisplayFrame.bottom - mTmpRect.bottom, 0));
-
-            // The divider doesn't care about insets in any case, so set it to empty so we don't
-            // trigger a relayout when moving it.
-            mContentInsets.setEmpty();
-            mVisibleInsets.setEmpty();
-            windowFrames.setDisplayCutout(WmDisplayCutout.NO_CUTOUT);
+            mWindowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
         } else {
             getDisplayContent().getBounds(mTmpRect);
-            // Override right and/or bottom insets in case if the frame doesn't fit the screen in
-            // non-fullscreen mode.
-            boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
-                    && mWindowFrames.mFrame.right > mTmpRect.right;
-            boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
-                    && mWindowFrames.mFrame.bottom > mTmpRect.bottom;
-            mContentInsets.set(mWindowFrames.mContentFrame.left - mWindowFrames.mFrame.left,
-                    mWindowFrames.mContentFrame.top - mWindowFrames.mFrame.top,
-                    overrideRightInset ? mTmpRect.right - mWindowFrames.mContentFrame.right
-                            : mWindowFrames.mFrame.right - mWindowFrames.mContentFrame.right,
-                    overrideBottomInset ? mTmpRect.bottom - mWindowFrames.mContentFrame.bottom
-                            : mWindowFrames.mFrame.bottom - mWindowFrames.mContentFrame.bottom);
-
-            mVisibleInsets.set(mWindowFrames.mVisibleFrame.left - mWindowFrames.mFrame.left,
-                    mWindowFrames.mVisibleFrame.top - mWindowFrames.mFrame.top,
-                    overrideRightInset ? mTmpRect.right - mWindowFrames.mVisibleFrame.right
-                            : mWindowFrames.mFrame.right - mWindowFrames.mVisibleFrame.right,
-                    overrideBottomInset ? mTmpRect.bottom - mWindowFrames.mVisibleFrame.bottom
-                            : mWindowFrames.mFrame.bottom - mWindowFrames.mVisibleFrame.bottom);
-
-            mStableInsets.set(
-                    Math.max(mWindowFrames.mStableFrame.left - mWindowFrames.mFrame.left, 0),
-                    Math.max(mWindowFrames.mStableFrame.top - mWindowFrames.mFrame.top, 0),
-                    overrideRightInset ? Math.max(mTmpRect.right - mWindowFrames.mStableFrame.right,
-                            0) : Math.max(
-                            mWindowFrames.mFrame.right - mWindowFrames.mStableFrame.right, 0),
-                    overrideBottomInset ? Math.max(
-                            mTmpRect.bottom - mWindowFrames.mStableFrame.bottom, 0) : Math.max(
-                            mWindowFrames.mFrame.bottom - mWindowFrames.mStableFrame.bottom, 0));
+            mWindowFrames.calculateInsets(windowsAreFloating, inFullscreenContainer, mTmpRect);
         }
 
         mWindowFrames.setDisplayCutout(
                 windowFrames.mDisplayCutout.calculateRelativeTo(mWindowFrames.mFrame));
 
         // Offset the actual frame by the amount layout frame is off.
-        mWindowFrames.mFrame.offset(-layoutXDiff, -layoutYDiff);
-        mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
-        mWindowFrames.mContentFrame.offset(-layoutXDiff, -layoutYDiff);
-        mWindowFrames.mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
-        mWindowFrames.mStableFrame.offset(-layoutXDiff, -layoutYDiff);
+        mWindowFrames.offsetFrames(-layoutXDiff, -layoutYDiff);
 
-        mCompatFrame.set(mWindowFrames.mFrame);
+        mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
         if (mEnforceSizeCompat) {
             // If there is a size compatibility scale being applied to the
             // window, we need to apply this to its insets so that they are
             // reported to the app in its coordinate space.
-            mOverscanInsets.scale(mInvGlobalScale);
-            mContentInsets.scale(mInvGlobalScale);
-            mVisibleInsets.scale(mInvGlobalScale);
-            mStableInsets.scale(mInvGlobalScale);
-            mOutsets.scale(mInvGlobalScale);
+            mWindowFrames.scaleInsets(mInvGlobalScale);
 
             // Also the scaled frame that we report to the app needs to be
             // adjusted to be in its coordinate space.
-            mCompatFrame.scale(mInvGlobalScale);
+            mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
         }
 
         if (mIsWallpaper && (fw != mWindowFrames.mFrame.width()
@@ -1156,10 +1038,7 @@
                 + mRequestedWidth + ", mRequestedheight="
                 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
                 + "): frame=" + mWindowFrames.mFrame.toShortString()
-                + " ci=" + mContentInsets.toShortString()
-                + " vi=" + mVisibleInsets.toShortString()
-                + " si=" + mStableInsets.toShortString()
-                + " of=" + mOutsets.toShortString());
+                + " " + mWindowFrames.getInsetsInfo());
     }
 
     // TODO: Look into whether this override is still necessary.
@@ -1219,6 +1098,14 @@
         return mWindowFrames.mDisplayCutout;
     }
 
+    void getCompatFrame(Rect outFrame) {
+        outFrame.set(mWindowFrames.mCompatFrame);
+    }
+
+    void getCompatFrameSize(Rect outFrame) {
+        outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height());
+    }
+
     @Override
     public boolean getGivenInsetsPendingLw() {
         return mGivenInsetsPending;
@@ -1270,15 +1157,7 @@
     }
 
     boolean setReportResizeHints() {
-        mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
-        mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
-        mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
-        mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
-        mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
-        mFrameSizeChanged |= mWindowFrames.didFrameSizeChange();
-        mDisplayCutoutChanged |= mWindowFrames.didDisplayCutoutChange();
-        return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
-                || mOutsetsChanged || mFrameSizeChanged || mDisplayCutoutChanged;
+        return mWindowFrames.setReportResizeHints();
     }
 
     /**
@@ -1301,7 +1180,7 @@
             return;
         }
 
-        setReportResizeHints();
+        boolean didFrameInsetsChange = setReportResizeHints();
         boolean configChanged = isConfigChanged();
         if (DEBUG_CONFIGURATION && configChanged) {
             Slog.v(TAG_WM, "Win " + this + " config changed: " + getConfiguration());
@@ -1318,31 +1197,18 @@
         // variables, because mFrameSizeChanged only tracks the width and height changing.
         mWindowFrames.mLastFrame.set(mWindowFrames.mFrame);
 
-        if (mContentInsetsChanged
-                || mVisibleInsetsChanged
-                || mStableInsetsChanged
+        if (didFrameInsetsChange
                 || winAnimator.mSurfaceResized
-                || mOutsetsChanged
-                || mFrameSizeChanged
-                || mDisplayCutoutChanged
                 || configChanged
                 || dragResizingChanged
                 || mReportOrientationChanged) {
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
                 Slog.v(TAG_WM, "Resize reasons for w=" + this + ": "
-                        + " contentInsetsChanged=" + mContentInsetsChanged
-                        + " " + mContentInsets.toShortString()
-                        + " visibleInsetsChanged=" + mVisibleInsetsChanged
-                        + " " + mVisibleInsets.toShortString()
-                        + " stableInsetsChanged=" + mStableInsetsChanged
-                        + " " + mStableInsets.toShortString()
-                        + " outsetsChanged=" + mOutsetsChanged
-                        + " " + mOutsets.toShortString()
+                        + " " + mWindowFrames.getInsetsChangedInfo()
                         + " surfaceResized=" + winAnimator.mSurfaceResized
                         + " configChanged=" + configChanged
                         + " dragResizingChanged=" + dragResizingChanged
-                        + " reportOrientationChanged=" + mReportOrientationChanged
-                        + " displayCutoutChanged=" + mDisplayCutoutChanged);
+                        + " reportOrientationChanged=" + mReportOrientationChanged);
             }
 
             // If it's a dead window left on screen, and the configuration changed, there is nothing
@@ -3015,7 +2881,7 @@
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
         try {
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
-                    + ": " + mCompatFrame);
+                    + ": " + mWindowFrames.mCompatFrame);
             final MergedConfiguration mergedConfiguration =
                     new MergedConfiguration(mService.mRoot.getConfiguration(),
                     getMergedOverrideConfiguration());
@@ -3026,11 +2892,11 @@
                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
 
             final Rect frame = mWindowFrames.mFrame;
-            final Rect overscanInsets = mLastOverscanInsets;
-            final Rect contentInsets = mLastContentInsets;
-            final Rect visibleInsets = mLastVisibleInsets;
-            final Rect stableInsets = mLastStableInsets;
-            final Rect outsets = mLastOutsets;
+            final Rect overscanInsets = mWindowFrames.mLastOverscanInsets;
+            final Rect contentInsets = mWindowFrames.mLastContentInsets;
+            final Rect visibleInsets = mWindowFrames.mLastVisibleInsets;
+            final Rect stableInsets = mWindowFrames.mLastStableInsets;
+            final Rect outsets = mWindowFrames.mLastOutsets;
             final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING;
             final boolean reportOrientation = mReportOrientationChanged;
             final int displayId = getDisplayId();
@@ -3061,13 +2927,7 @@
                 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
             }
 
-            mOverscanInsetsChanged = false;
-            mContentInsetsChanged = false;
-            mVisibleInsetsChanged = false;
-            mStableInsetsChanged = false;
-            mOutsetsChanged = false;
-            mFrameSizeChanged = false;
-            mDisplayCutoutChanged = false;
+            mWindowFrames.resetInsetsChanged();
             mWinAnimator.mSurfaceResized = false;
             mReportOrientationChanged = false;
         } catch (RemoteException e) {
@@ -3293,7 +3153,6 @@
         mAttrs.writeToProto(proto, ATTRIBUTES);
         mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS);
         mWindowFrames.writeToProto(proto, WINDOW_FRAMES);
-        mContentInsets.writeToProto(proto, CONTENT_INSETS);
         mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS);
         mSurfacePosition.writeToProto(proto, SURFACE_POSITION);
         mWinAnimator.writeToProto(proto, ANIMATOR);
@@ -3307,10 +3166,6 @@
         proto.write(SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
         proto.write(HAS_SURFACE, mHasSurface);
         proto.write(IS_READY_FOR_DISPLAY, isReadyForDisplay());
-        mOverscanInsets.writeToProto(proto, OVERSCAN_INSETS);
-        mVisibleInsets.writeToProto(proto, VISIBLE_INSETS);
-        mStableInsets.writeToProto(proto, STABLE_INSETS);
-        mOutsets.writeToProto(proto, OUTSETS);
         proto.write(REMOVE_ON_EXIT, mRemoveOnExit);
         proto.write(DESTROYING, mDestroying);
         proto.write(REMOVED, mRemoved);
@@ -3417,21 +3272,11 @@
                 + " isReadyForDisplay()=" + isReadyForDisplay()
                 + " mWindowRemovalAllowed=" + mWindowRemovalAllowed);
         if (mEnforceSizeCompat) {
-            pw.println(prefix + "mCompatFrame=" + mCompatFrame.toShortString(sTmpSB));
+            pw.println(prefix + "mCompatFrame=" + mWindowFrames.mCompatFrame.toShortString(sTmpSB));
         }
         if (dumpAll) {
             mWindowFrames.dump(pw, prefix);
-            pw.print(prefix + "Cur insets: overscan=" + mOverscanInsets.toShortString(sTmpSB)
-                    + " content=" + mContentInsets.toShortString(sTmpSB)
-                    + " visible=" + mVisibleInsets.toShortString(sTmpSB)
-                    + " stable=" + mStableInsets.toShortString(sTmpSB)
-                    + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB)
-                    + " outsets=" + mOutsets.toShortString(sTmpSB));
-            pw.println(prefix + "Lst insets: overscan=" + mLastOverscanInsets.toShortString(sTmpSB)
-                    + " content=" + mLastContentInsets.toShortString(sTmpSB)
-                    + " visible=" + mLastVisibleInsets.toShortString(sTmpSB)
-                    + " stable=" + mLastStableInsets.toShortString(sTmpSB)
-                    + " outset=" + mLastOutsets.toShortString(sTmpSB));
+            pw.println(prefix + " surface=" + mAttrs.surfaceInsets.toShortString(sTmpSB));
         }
         super.dump(pw, prefix, dumpAll);
         pw.println(prefix + mWinAnimator + ":");
@@ -3531,7 +3376,7 @@
         }
     }
 
-    void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
+    private void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
         final int pw = containingFrame.width();
         final int ph = containingFrame.height();
         final Task task = getTask();
@@ -3609,10 +3454,10 @@
 
         // We need to make sure we update the CompatFrame as it is used for
         // cropping decisions, etc, on systems where we lack a decor layer.
-        mCompatFrame.set(mWindowFrames.mFrame);
+        mWindowFrames.mCompatFrame.set(mWindowFrames.mFrame);
         if (mEnforceSizeCompat) {
             // See comparable block in computeFrameLw.
-            mCompatFrame.scale(mInvGlobalScale);
+            mWindowFrames.mCompatFrame.scale(mInvGlobalScale);
         }
     }
 
@@ -4322,13 +4167,15 @@
             // On a different display there is no system decor. Crop the window
             // by the screen boundaries.
             // TODO(multi-display)
-            policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
-            policyCrop.intersect(-mCompatFrame.left, -mCompatFrame.top,
-                    displayInfo.logicalWidth - mCompatFrame.left,
-                    displayInfo.logicalHeight - mCompatFrame.top);
+            policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
+                    mWindowFrames.mCompatFrame.height());
+            policyCrop.intersect(-mWindowFrames.mCompatFrame.left, -mWindowFrames.mCompatFrame.top,
+                    displayInfo.logicalWidth - mWindowFrames.mCompatFrame.left,
+                    displayInfo.logicalHeight - mWindowFrames.mCompatFrame.top);
         } else if (skipDecorCrop()) {
             // Windows without policy decor aren't cropped.
-            policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
+            policyCrop.set(0, 0, mWindowFrames.mCompatFrame.width(),
+                    mWindowFrames.mCompatFrame.height());
         } else {
             // Crop to the system decor specified by policy.
             calculateSystemDecorRect(policyCrop);
@@ -4486,12 +4333,7 @@
      * Updates the last inset values to the current ones.
      */
     void updateLastInsetValues() {
-        mLastOverscanInsets.set(mOverscanInsets);
-        mLastContentInsets.set(mContentInsets);
-        mLastVisibleInsets.set(mVisibleInsets);
-        mLastStableInsets.set(mStableInsets);
-        mLastOutsets.set(mOutsets);
-        mWindowFrames.mLastDisplayCutout = mWindowFrames.mDisplayCutout;
+        mWindowFrames.updateLastInsetValues();
     }
 
     void startAnimation(Animation anim) {
@@ -4880,6 +4722,44 @@
         }
     }
 
+    /**
+     * Copy the inset values over so they can be sent back to the client when a relayout occurs.
+     */
+    void getInsetsForRelayout(Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
+            Rect outStableInsets, Rect outOutsets) {
+        outOverscanInsets.set(mWindowFrames.mOverscanInsets);
+        outContentInsets.set(mWindowFrames.mContentInsets);
+        outVisibleInsets.set(mWindowFrames.mVisibleInsets);
+        outStableInsets.set(mWindowFrames.mStableInsets);
+        outOutsets.set(mWindowFrames.mOutsets);
+
+        mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets);
+    }
+
+    void getContentInsets(Rect outContentInsets) {
+        outContentInsets.set(mWindowFrames.mContentInsets);
+    }
+
+    Rect getContentInsets() {
+        return mWindowFrames.mContentInsets;
+    }
+
+    void getStableInsets(Rect outStableInsets) {
+        outStableInsets.set(mWindowFrames.mStableInsets);
+    }
+
+    Rect getStableInsets() {
+        return mWindowFrames.mStableInsets;
+    }
+
+    void resetLastContentInsets() {
+        mWindowFrames.resetLastContentInsets();
+    }
+
+    Rect getVisibleInsets() {
+        return mWindowFrames.mVisibleInsets;
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b158ae2..c80eb86 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_NONE;
+
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
@@ -46,7 +47,6 @@
 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
 
 import android.content.Context;
 import android.graphics.Matrix;
@@ -476,8 +476,7 @@
             flags |= SurfaceControl.SECURE;
         }
 
-        mTmpSize.set(0, 0, 0, 0);
-        calculateSurfaceBounds(w, attrs);
+        calculateSurfaceBounds(w, attrs, mTmpSize);
         final int width = mTmpSize.width();
         final int height = mTmpSize.height();
 
@@ -556,44 +555,38 @@
         return mSurfaceController;
     }
 
-    private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) {
+    private void calculateSurfaceBounds(WindowState w, LayoutParams attrs, Rect outSize) {
+        outSize.setEmpty();
         if ((attrs.flags & FLAG_SCALED) != 0) {
             // For a scaled surface, we always want the requested size.
-            mTmpSize.right = mTmpSize.left + w.mRequestedWidth;
-            mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight;
+            outSize.right = w.mRequestedWidth;
+            outSize.bottom = w.mRequestedHeight;
         } else {
             // When we're doing a drag-resizing, request a surface that's fullscreen size,
             // so that we don't need to reallocate during the process. This also prevents
             // buffer drops due to size mismatch.
             if (w.isDragResizing()) {
-                if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) {
-                    mTmpSize.left = 0;
-                    mTmpSize.top = 0;
-                }
                 final DisplayInfo displayInfo = w.getDisplayInfo();
-                mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth;
-                mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight;
+                outSize.right = displayInfo.logicalWidth;
+                outSize.bottom = displayInfo.logicalHeight;
             } else {
-                mTmpSize.right = mTmpSize.left + w.mCompatFrame.width();
-                mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height();
+                w.getCompatFrameSize(outSize);
             }
         }
 
         // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
         // This doesn't necessarily mean that there is an error in the system. The sizes might be
         // incorrect, because it is before the first layout or draw.
-        if (mTmpSize.width() < 1) {
-            mTmpSize.right = mTmpSize.left + 1;
+        if (outSize.width() < 1) {
+            outSize.right = 1;
         }
-        if (mTmpSize.height() < 1) {
-            mTmpSize.bottom = mTmpSize.top + 1;
+        if (outSize.height() < 1) {
+            outSize.bottom = 1;
         }
 
         // Adjust for surface insets.
-        mTmpSize.left -= attrs.surfaceInsets.left;
-        mTmpSize.top -= attrs.surfaceInsets.top;
-        mTmpSize.right += attrs.surfaceInsets.right;
-        mTmpSize.bottom += attrs.surfaceInsets.bottom;
+        outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top,
+                -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom);
     }
 
     boolean hasSurface() {
@@ -870,8 +863,7 @@
         final LayoutParams attrs = mWin.getAttrs();
         final Task task = w.getTask();
 
-        mTmpSize.set(0, 0, 0, 0);
-        calculateSurfaceBounds(w, attrs);
+        calculateSurfaceBounds(w, attrs, mTmpSize);
 
         mExtraHScale = (float) 1.0;
         mExtraVScale = (float) 1.0;
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index b467d61..42ade38 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -210,7 +210,7 @@
             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
-    void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
+    void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
     void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
     void setInputDispatchMode(bool enabled, bool frozen);
     void setSystemUiVisibility(int32_t visibility);
@@ -736,7 +736,8 @@
     }
 }
 
-void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray,
+         int32_t displayId) {
     Vector<sp<InputWindowHandle> > windowHandles;
 
     if (windowHandleObjArray) {
@@ -756,7 +757,7 @@
         }
     }
 
-    mInputManager->getDispatcher()->setInputWindows(windowHandles);
+    mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId);
 
     // Do this after the dispatcher has updated the window handle state.
     bool newPointerGesturesEnabled = true;
@@ -1446,10 +1447,10 @@
 }
 
 static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
-        jlong ptr, jobjectArray windowHandleObjArray) {
+        jlong ptr, jobjectArray windowHandleObjArray, jint displayId) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    im->setInputWindows(env, windowHandleObjArray);
+    im->setInputWindows(env, windowHandleObjArray, displayId);
 }
 
 static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
@@ -1678,7 +1679,7 @@
             (void*) nativeInjectInputEvent },
     { "nativeToggleCapsLock", "(JI)V",
             (void*) nativeToggleCapsLock },
-    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
+    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;I)V",
             (void*) nativeSetInputWindows },
     { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
             (void*) nativeSetFocusedApplication },
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4664601..0b6a33f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -743,6 +743,11 @@
             traceEnd();
         }
 
+        // Tracks and caches the device state.
+        traceBeginAndSlog("StartCachedDeviceStateService");
+        mSystemServiceManager.startService(CachedDeviceStateService.class);
+        traceEnd();
+
         // Tracks cpu time spent in binder calls
         traceBeginAndSlog("StartBinderCallsStatsService");
         mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 3cdef1e..ccc092d 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -1385,6 +1385,20 @@
 
     private boolean startIpReachabilityMonitor() {
         try {
+            // TODO: Fetch these parameters from settings, and install a
+            // settings observer to watch for update and re-program these
+            // parameters (Q: is this level of dynamic updatability really
+            // necessary or does reading from settings at startup suffice?).
+            final int NUM_SOLICITS = 5;
+            final int INTER_SOLICIT_INTERVAL_MS = 750;
+            setNeighborParameters(mDependencies.getNetd(), mInterfaceName,
+                    NUM_SOLICITS, INTER_SOLICIT_INTERVAL_MS);
+        } catch (Exception e) {
+            mLog.e("Failed to adjust neighbor parameters", e);
+            // Carry on using the system defaults (currently: 3, 1000);
+        }
+
+        try {
             mIpReachabilityMonitor = new IpReachabilityMonitor(
                     mContext,
                     mInterfaceParams,
@@ -1863,6 +1877,20 @@
         }
     }
 
+    private static void setNeighborParameters(
+            INetd netd, String ifName, int num_solicits, int inter_solicit_interval_ms)
+            throws RemoteException, IllegalArgumentException {
+        Preconditions.checkNotNull(netd);
+        Preconditions.checkArgument(!TextUtils.isEmpty(ifName));
+        Preconditions.checkArgument(num_solicits > 0);
+        Preconditions.checkArgument(inter_solicit_interval_ms > 0);
+
+        for (int family : new Integer[]{INetd.IPV4, INetd.IPV6}) {
+            netd.setProcSysNet(family, INetd.NEIGH, ifName, "retrans_time_ms", Integer.toString(inter_solicit_interval_ms));
+            netd.setProcSysNet(family, INetd.NEIGH, ifName, "ucast_solicit", Integer.toString(num_solicits));
+        }
+    }
+
     // TODO: extract out into CollectionUtils.
     static <T> boolean any(Iterable<T> coll, Predicate<T> fn) {
         for (T t : coll) {
diff --git a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
new file mode 100644
index 0000000..81107cf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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;
+
+
+import static org.mockito.Mockito.when;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.os.IPowerManager;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
+import android.os.RemoteException;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.CachedDeviceState;
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link CachedDeviceStateService}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class CachedDeviceStateServiceTest {
+    @Mock private BatteryManagerInternal mBatteryManager;
+    @Mock private IPowerManager mPowerManager;
+    private BroadcastInterceptingContext mContext;
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+        Context context = InstrumentationRegistry.getContext();
+        PowerManager powerManager = new PowerManager(context, mPowerManager, null);
+        mContext = new BroadcastInterceptingContext(context) {
+            @Override
+            public Object getSystemService(String name) {
+                switch (name) {
+                    case Context.POWER_SERVICE:
+                        return powerManager;
+                    default:
+                        return super.getSystemService(name);
+                }
+            }
+        };
+
+        LocalServices.addService(BatteryManagerInternal.class, mBatteryManager);
+
+        when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE);
+        when(mPowerManager.isInteractive()).thenReturn(true);
+    }
+
+    @After
+    public void tearDown() {
+        // Added by the CachedDeviceStateService.onStart().
+        LocalServices.removeServiceForTest(CachedDeviceState.Readonly.class);
+
+        // Added in @Before.
+        LocalServices.removeServiceForTest(BatteryManagerInternal.class);
+    }
+
+    @Test
+    public void correctlyReportsScreenInteractive() throws RemoteException {
+        CachedDeviceStateService service = new CachedDeviceStateService(mContext);
+        when(mPowerManager.isInteractive()).thenReturn(true); // Screen on.
+
+        service.onStart();
+        CachedDeviceState.Readonly deviceState =
+                LocalServices.getService(CachedDeviceState.Readonly.class);
+
+        // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY.
+        assertThat(deviceState.isScreenInteractive()).isFalse();
+
+        service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        assertThat(deviceState.isScreenInteractive()).isTrue();
+
+        mContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+        assertThat(deviceState.isScreenInteractive()).isFalse();
+
+        mContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+        assertThat(deviceState.isScreenInteractive()).isTrue();
+    }
+
+    @Test
+    public void correctlyReportsCharging() {
+        CachedDeviceStateService service = new CachedDeviceStateService(mContext);
+        when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE);
+
+        service.onStart();
+        CachedDeviceState.Readonly deviceState =
+                LocalServices.getService(CachedDeviceState.Readonly.class);
+
+        // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY.
+        assertThat(deviceState.isCharging()).isTrue();
+
+        service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        assertThat(deviceState.isCharging()).isFalse();
+
+        Intent intentPluggedIn = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intentPluggedIn.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+        mContext.sendBroadcast(intentPluggedIn);
+        assertThat(deviceState.isCharging()).isTrue();
+
+        Intent intentUnplugged = new Intent(Intent.ACTION_BATTERY_CHANGED);
+        intentUnplugged.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
+        mContext.sendBroadcast(intentUnplugged);
+        assertThat(deviceState.isCharging()).isFalse();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
index 360ccbf..a3decb9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureControllerTest.java
@@ -20,6 +20,8 @@
 import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.os.Looper;
+import android.support.test.filters.FlakyTest;
+
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -95,6 +97,7 @@
     }
 
     @Test
+    @FlakyTest
     public void testDetectionActiveCallback_withHandler_shouldPostRunnableToHandler() {
         MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
             message.getCallback().run();
@@ -142,6 +145,7 @@
     }
 
     @Test
+    @FlakyTest
     public void testGestureCallback_withHandler_shouldPostRunnableToHandler() {
         MessageCapturingHandler messageCapturingHandler = new MessageCapturingHandler((message) -> {
             message.getCallback().run();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
index f9d264b..d6d21c6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -43,6 +43,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.support.test.filters.FlakyTest;
 import android.view.MagnificationSpec;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -66,6 +67,7 @@
 import java.util.Locale;
 
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class MagnificationControllerTest {
     static final Rect INITIAL_MAGNIFICATION_BOUNDS = new Rect(0, 0, 100, 200);
     static final PointF INITIAL_MAGNIFICATION_BOUNDS_CENTER = new PointF(
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index ea3a3d0..e648230 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -133,15 +133,15 @@
     }
 
     private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
-        assertRect(w.mContentInsets, left, top, right, bottom);
+        assertRect(w.getContentInsets(), left, top, right, bottom);
     }
 
     private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
-        assertRect(w.mVisibleInsets, left, top, right, bottom);
+        assertRect(w.getVisibleInsets(), left, top, right, bottom);
     }
 
     private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
-        assertRect(w.mStableInsets, left, top, right, bottom);
+        assertRect(w.getStableInsets(), left, top, right, bottom);
     }
 
     private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 119733e..5e3bac5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2007,20 +2007,21 @@
     }
 
     /**
-     * Get User downloaded Profiles.
+     * Get opportunistic data Profiles.
      *
-     *  Provide all available user downloaded profile on the phone.
-     *  @param slotId on which phone the switch will operate on
+     *  Provide all available user downloaded profiles on phone which are used only for
+     *  opportunistic data.
+     *  @param slotIndex slot on which the profiles are queried from.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId) {
+    public List<SubscriptionInfo> getOpportunisticSubscriptions(int slotIndex) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         List<SubscriptionInfo> subInfoList = null;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                subInfoList = iSub.getOpportunisticSubscriptions(slotId, pkgForDebug);
+                subInfoList = iSub.getOpportunisticSubscriptions(slotIndex, pkgForDebug);
             }
         } catch (RemoteException ex) {
             // ignore it
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index abcdeed..b8e4c0e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -64,6 +64,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.ITelecomService;
 import com.android.internal.telephony.CellNetworkScanResult;
+import com.android.internal.telephony.IAnas;
 import com.android.internal.telephony.IPhoneSubInfo;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.ITelephonyRegistry;
@@ -4327,6 +4328,10 @@
         return ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));
     }
 
+    private IAnas getIAnas() {
+        return IAnas.Stub.asInterface(ServiceManager.getService("ianas"));
+    }
+
     //
     //
     // PhoneStateListener
@@ -8193,7 +8198,6 @@
         return UNKNOWN_CARRIER_ID_LIST_VERSION;
     }
 
-
     /**
      * How many modems can have simultaneous data connections.
      * @hide
@@ -8211,4 +8215,62 @@
         }
         return 0;
     }
+
+    /**
+     * Enable or disable AlternativeNetworkAccessService.
+     *
+     * This method should be called to enable or disable
+     * AlternativeNetworkAccess service on the device.
+     *
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @param enable enable(True) or disable(False)
+     * @return returns true if successfully set.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setAlternativeNetworkAccessState(boolean enable) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        boolean ret = false;
+        try {
+            IAnas iAlternativeAccessService = getIAnas();
+            if (iAlternativeAccessService != null) {
+                ret = iAlternativeAccessService.setEnable(enable, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "enableAlternativeNetworkAccess RemoteException", ex);
+        }
+
+        return ret;
+    }
+
+    /**
+     * is AlternativeNetworkAccessService enabled
+     *
+     * This method should be called to determine if the AlternativeNetworkAccessService is
+     * enabled
+     *
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public boolean isAlternativeNetworkAccessEnabled() {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        boolean isEnabled = false;
+
+        try {
+            IAnas iAlternativeAccessService = getIAnas();
+            if (iAlternativeAccessService != null) {
+                isEnabled = iAlternativeAccessService.isEnabled(pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "enableAlternativeNetworkAccess RemoteException", ex);
+        }
+
+        return isEnabled;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/IAnas.aidl b/telephony/java/com/android/internal/telephony/IAnas.aidl
new file mode 100755
index 0000000..88d681a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IAnas.aidl
@@ -0,0 +1,52 @@
+/*
+ * 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.telephony;
+
+
+interface IAnas {
+
+    /**
+    * Enable or disable Alternative Network Access service.
+    *
+    * This method should be called to enable or disable
+    * AlternativeNetworkAccess service on the device.
+    *
+    * <p>
+    * Requires Permission:
+    *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+    * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+    *
+    * @param enable enable(True) or disable(False)
+    * @param callingPackage caller's package name
+    * @return returns true if successfully set.
+    */
+    boolean setEnable(boolean enable, String callingPackage);
+
+    /**
+     * is Alternative Network Access service enabled
+     *
+     * This method should be called to determine if the Alternative Network Access service is enabled
+    *
+    * <p>
+    * Requires Permission:
+    *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+    * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+    *
+    * @param callingPackage caller's package name
+    */
+    boolean isEnabled(String callingPackage);
+}
diff --git a/tools/processors/unsupportedappusage/Android.bp b/tools/processors/unsupportedappusage/Android.bp
index 98f3c95..1aca3ed 100644
--- a/tools/processors/unsupportedappusage/Android.bp
+++ b/tools/processors/unsupportedappusage/Android.bp
@@ -11,5 +11,15 @@
         "guava",
         "unsupportedappusage-annotation"
     ],
+    openjdk9: {
+        javacflags: [
+            "--add-modules=jdk.compiler",
+            "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+            "--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+            "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+            "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+        ],
+    },
+
     use_tools_jar: true,
 }