Merge "Adds silence toggle to notification settings."
diff --git a/api/system-current.txt b/api/system-current.txt
index da1adac..237d4c4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1052,6 +1052,7 @@
     field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
     field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
     field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
+    field public static final java.lang.String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
@@ -2719,6 +2720,7 @@
   public class LocationManager {
     method public deprecated boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
     method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+    method public android.app.PendingIntent createManageLocationPermissionIntent(java.lang.String, java.lang.String);
     method public void flushGnssBatch();
     method public int getGnssBatchSize();
     method public java.lang.String getNetworkProviderPackage();
@@ -3645,9 +3647,9 @@
     method public boolean isPortableHotspotSupported();
     method public boolean isWifiApEnabled();
     method public boolean isWifiScannerSupported();
-    method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
     method public boolean isWpa3SaeSupported();
     method public boolean isWpa3SuiteBSupported();
+    method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
     method public boolean startScan(android.os.WorkSource);
     method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 0d9a393..f11b49d 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1361,15 +1361,11 @@
 Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
 Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
 Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->get_pubkey(Ljava/lang/String;)[B
-Landroid/security/IKeystoreService;->import_key(Ljava/lang/String;[BII)I
 Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
 Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
 Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
 Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->sign(Ljava/lang/String;[B)[B
 Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->verify(Ljava/lang/String;[B[B)I
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
 Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
diff --git a/config/preloaded-classes b/config/preloaded-classes
index b6bff9c..22fc5e8 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -3240,7 +3240,7 @@
 android.view.FocusFinder$FocusSorter
 android.view.FocusFinder$UserSpecifiedFocusComparator
 android.view.FocusFinder$UserSpecifiedFocusComparator$NextFocusGetter
-android.view.FrameInfo
+android.graphics.FrameInfo
 android.view.FrameMetrics
 android.view.FrameMetricsObserver
 android.view.FrameStats
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9079f1a..805fb68 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -72,6 +72,7 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.HardwareRenderer;
 import android.graphics.ImageDecoder;
 import android.hardware.display.DisplayManagerGlobal;
 import android.net.ConnectivityManager;
@@ -5652,7 +5653,7 @@
                     int uid = Process.myUid();
                     String[] packages = getPackageManager().getPackagesForUid(uid);
                     if (packages != null) {
-                        ThreadedRenderer.setupDiskCache(codeCacheDir);
+                        HardwareRenderer.setupDiskCache(codeCacheDir);
                         RenderScriptCacheDir.setupDiskCache(codeCacheDir);
                     }
                 } catch (RemoteException e) {
@@ -5887,7 +5888,8 @@
 
         // Allow renderer debugging features if we're debuggable.
         boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-        ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+        HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+        HardwareRenderer.setPackageName(data.appInfo.packageName);
 
         /**
          * Initialize the default http proxy in this process for the reasons we set the time zone.
@@ -5954,7 +5956,7 @@
                 StrictMode.setThreadPolicyMask(oldMask);
             }
         } else {
-            ThreadedRenderer.setIsolatedProcess(true);
+            HardwareRenderer.setIsolatedProcess(true);
         }
 
         // If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1e2244e..a9819fc 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -28,7 +28,9 @@
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
+import android.database.ContentObserver;
 import android.media.AudioAttributes.AttributeUsage;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -36,6 +38,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.ArrayMap;
 
 import com.android.internal.app.IAppOpsActiveCallback;
@@ -50,6 +53,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * API for interacting with "application operation" tracking.
@@ -1608,9 +1612,56 @@
      * @hide
      */
     public static int opToDefaultMode(int op) {
+        // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+        switch (op) {
+            // SMS permissions
+            case AppOpsManager.OP_SEND_SMS:
+            case AppOpsManager.OP_RECEIVE_SMS:
+            case AppOpsManager.OP_READ_SMS:
+            case AppOpsManager.OP_RECEIVE_WAP_PUSH:
+            case AppOpsManager.OP_RECEIVE_MMS:
+            case AppOpsManager.OP_READ_CELL_BROADCASTS:
+            // CallLog permissions
+            case AppOpsManager.OP_READ_CALL_LOG:
+            case AppOpsManager.OP_WRITE_CALL_LOG:
+            case AppOpsManager.OP_PROCESS_OUTGOING_CALLS: {
+                if (sSmsAndCallLogRestrictionEnabled.get() < 0) {
+                    startWatchingSmsRestrictionEnabled();
+                }
+                if (sSmsAndCallLogRestrictionEnabled.get() == 1) {
+                    return AppOpsManager.MODE_DEFAULT;
+                }
+            }
+        }
         return sOpDefaultMode[op];
     }
 
+    // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+    private static final AtomicInteger sSmsAndCallLogRestrictionEnabled = new AtomicInteger(-1);
+
+    // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+    private static void startWatchingSmsRestrictionEnabled() {
+        final Context context = ActivityThread.currentApplication();
+        if (context == null) {
+            // Should never happen
+            return;
+        }
+
+        sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
+                    .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+
+        final Uri uri = Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
+        context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
+                context.getMainThreadHandler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
+                        context.getContentResolver(),
+                        Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+            }
+        });
+    }
+
     /**
      * Retrieve the default mode for the app op.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6c0fa4c..aa34da8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1753,6 +1753,30 @@
             "android.intent.action.MANAGE_APP_PERMISSIONS";
 
     /**
+     * Activity action: Launch UI to manage a specific permissions of an app.
+     * <p>
+     * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permission
+     * will be managed by the launched UI.
+     * </p>
+     * <p>
+     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the (individual) permission
+     * that should be managed by the launched UI.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     *
+     * @see #EXTRA_PACKAGE_NAME
+     * @see #EXTRA_PERMISSION_NAME
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_APP_PERMISSION =
+            "android.intent.action.MANAGE_APP_PERMISSION";
+
+    /**
      * Activity action: Launch UI to manage permissions.
      * <p>
      * Input: Nothing.
@@ -1882,8 +1906,8 @@
     /**
      * Activity action: Launch UI to manage which apps have a given permission.
      * <p>
-     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access
-     * to which will be managed by the launched UI.
+     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission group
+     * which will be managed by the launched UI.
      * </p>
      * <p>
      * Output: Nothing.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8e4de9f..7a444e0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9174,6 +9174,13 @@
         public static final String DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT
                 = "enable_freeform_support";
 
+        /**
+         * Whether to enable experimental desktop mode on secondary displays.
+         * @hide
+         */
+        public static final String DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS =
+                "force_desktop_mode_on_external_displays";
+
        /**
         * Whether user has enabled development settings.
         */
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b047ef7..67505e5 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -45,7 +45,7 @@
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
         DEFAULT_FLAGS.put("settings_dynamic_homepage", "false");
-        DEFAULT_FLAGS.put("settings_mobile_network_v2", "false");
+        DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
         DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
         DEFAULT_FLAGS.put("settings_seamless_transfer", "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a872776..96ef8ba 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -21,6 +21,7 @@
 
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.FrameInfo;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Build;
 import android.os.Handler;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 597089b..0f38e84 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -40,8 +40,9 @@
     @UnsupportedAppUsage
     private FrameMetrics mFrameMetrics;
 
-    /* package */ Window.OnFrameMetricsAvailableListener mListener;
-    /* package */ VirtualRefBasePtr mNative;
+    /* pacage */ Window.OnFrameMetricsAvailableListener mListener;
+    /** @hide */
+    public VirtualRefBasePtr mNative;
 
     /**
      * Creates a FrameMetricsObserver
diff --git a/core/java/android/view/TextureLayer.java b/core/java/android/view/TextureLayer.java
index d89d634..46dd436 100644
--- a/core/java/android/view/TextureLayer.java
+++ b/core/java/android/view/TextureLayer.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.SurfaceTexture;
@@ -32,10 +33,10 @@
  * @hide
  */
 public final class TextureLayer {
-    private ThreadedRenderer mRenderer;
+    private HardwareRenderer mRenderer;
     private VirtualRefBasePtr mFinalizer;
 
-    private TextureLayer(ThreadedRenderer renderer, long deferredUpdater) {
+    private TextureLayer(HardwareRenderer renderer, long deferredUpdater) {
         if (renderer == null || deferredUpdater == 0) {
             throw new IllegalArgumentException("Either hardware renderer: " + renderer
                     + " or deferredUpdater: " + deferredUpdater + " is invalid");
@@ -139,7 +140,8 @@
         mRenderer.pushLayerUpdate(this);
     }
 
-    static TextureLayer adoptTextureLayer(ThreadedRenderer renderer, long layer) {
+    /** @hide */
+    public static TextureLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
         return new TextureLayer(renderer, layer);
     }
 
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f0f4c1c..bac0154 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,36 +16,24 @@
 
 package android.view;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
 import android.graphics.Point;
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RenderNode;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
-import com.android.internal.util.VirtualRefBasePtr;
 
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 
 /**
  * Threaded renderer that proxies the rendering to a render thread. Most calls
@@ -66,15 +54,7 @@
  *
  * @hide
  */
-public final class ThreadedRenderer {
-    private static final String LOG_TAG = "ThreadedRenderer";
-
-    /**
-     * Name of the file that holds the shaders cache.
-     */
-    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
-    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
-
+public final class ThreadedRenderer extends HardwareRenderer {
     /**
      * System property used to enable or disable threaded rendering profiling.
      * The default value of this property is assumed to be false.
@@ -271,21 +251,6 @@
     }
 
     /**
-     * Sets the directory to use as a persistent storage for threaded rendering
-     * resources.
-     *
-     * @param cacheDir A directory the current process can write to
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static void setupDiskCache(File cacheDir) {
-        ThreadedRenderer.setupShadersDiskCache(
-                new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
-                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
-    }
-
-    /**
      * Creates a threaded renderer using OpenGL.
      *
      * @param translucent True if the surface is translucent, false otherwise
@@ -300,55 +265,10 @@
         return renderer;
     }
 
-    /**
-     * Invoke this method when the system is running out of memory. This
-     * method will attempt to recover as much memory as possible, based on
-     * the specified hint.
-     *
-     * @param level Hint about the amount of memory that should be trimmed,
-     *              see {@link android.content.ComponentCallbacks}
-     */
-    public static void trimMemory(int level) {
-        nTrimMemory(level);
-    }
-
-    public static void overrideProperty(@NonNull String name, @NonNull String value) {
-        if (name == null || value == null) {
-            throw new IllegalArgumentException("name and value must be non-null");
-        }
-        nOverrideProperty(name, value);
-    }
-
-    // Keep in sync with DrawFrameTask.h SYNC_* flags
-    // Nothing interesting to report
-    private static final int SYNC_OK = 0;
-    // Needs a ViewRoot invalidate
-    private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
-    // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
-    private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
-    // setStopped is true, drawing is false
-    // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
-    // This flag isn't really used as there's nothing that we care to do
-    // in response, so it really just exists to differentiate from LOST_SURFACE
-    // but possibly both can just be deleted.
-    private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
-    private static final int SYNC_FRAME_DROPPED = 1 << 3;
-
     private static final String[] VISUALIZERS = {
         PROFILE_PROPERTY_VISUALIZE_BARS,
     };
 
-    private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
-    private static final int FLAG_DUMP_RESET        = 1 << 1;
-    private static final int FLAG_DUMP_ALL          = FLAG_DUMP_FRAMESTATS;
-
-    @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
-            FLAG_DUMP_FRAMESTATS,
-            FLAG_DUMP_RESET
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface DumpFlags {}
-
     // Size of the rendered content.
     private int mWidth, mHeight;
 
@@ -362,51 +282,37 @@
     // Whether the surface has insets. Used to protect opacity.
     private boolean mHasInsets;
 
-    // Light and shadow properties specified by the theme.
+    // Light properties specified by the theme.
     private final float mLightY;
     private final float mLightZ;
     private final float mLightRadius;
-    private final int mAmbientShadowAlpha;
-    private final int mSpotShadowAlpha;
 
-    private long mNativeProxy;
     private boolean mInitialized = false;
-    private RenderNode mRootNode;
     private boolean mRootNodeNeedsUpdate;
 
     private boolean mEnabled;
     private boolean mRequested = true;
-    private boolean mIsOpaque = false;
 
     ThreadedRenderer(Context context, boolean translucent, String name) {
+        super();
+        setName(name);
+        setOpaque(!translucent);
+
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
         mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
         mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
-        mAmbientShadowAlpha =
-                (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
-        mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+        float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+        float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
         a.recycle();
-
-        long rootNodePtr = nCreateRootRenderNode();
-        mRootNode = RenderNode.adopt(rootNodePtr);
-        mRootNode.setClipToBounds(false);
-        mIsOpaque = !translucent;
-        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
-        nSetName(mNativeProxy, name);
-
-        ProcessInitializer.sInstance.init(context, mNativeProxy);
-
-        loadSystemProperties();
+        setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
     }
 
-    /**
-     * Destroys the threaded rendering context.
-     */
-    void destroy() {
+    @Override
+    public void destroy() {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+        super.destroy();
     }
 
     /**
@@ -464,7 +370,7 @@
         boolean status = !mInitialized;
         mInitialized = true;
         updateEnabledState(surface);
-        nInitialize(mNativeProxy, surface);
+        setSurface(surface);
         return status;
     }
 
@@ -505,26 +411,18 @@
      */
     void updateSurface(Surface surface) throws OutOfResourcesException {
         updateEnabledState(surface);
-        nUpdateSurface(mNativeProxy, surface);
+        setSurface(surface);
     }
 
-    /**
-     * Halts any current rendering into the surface. Use this if it is unclear whether
-     * or not the surface used by the ThreadedRenderer will be changing. It
-     * Suspends any rendering into the surface, but will not do any destruction.
-     *
-     * Any subsequent draws will override the pause, resuming normal operation.
-     */
-    boolean pauseSurface(Surface surface) {
-        return nPauseSurface(mNativeProxy, surface);
-    }
-
-    /**
-     * Hard stops or resumes rendering into the surface. This flag is used to
-     * determine whether or not it is safe to use the given surface *at all*
-     */
-    void setStopped(boolean stopped) {
-        nSetStopped(mNativeProxy, stopped);
+    @Override
+    public void setSurface(Surface surface) {
+        // TODO: Do we ever pass a non-null but isValid() = false surface?
+        // This is here to be super conservative for ViewRootImpl
+        if (surface != null && surface.isValid()) {
+            super.setSurface(surface);
+        } else {
+            super.setSurface(null);
+        }
     }
 
     /**
@@ -535,7 +433,7 @@
      */
     void destroyHardwareResources(View view) {
         destroyResources(view);
-        nDestroyHardwareResources(mNativeProxy);
+        destroyHardwareResources();
     }
 
     private static void destroyResources(View view) {
@@ -543,14 +441,6 @@
     }
 
     /**
-     * Detaches the layer's surface texture from the GL context and releases
-     * the texture id
-     */
-    void detachSurfaceTexture(long hardwareLayer) {
-        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
-    }
-
-    /**
      * Sets up the renderer for drawing.
      *
      * @param width The width of the drawing surface.
@@ -581,8 +471,6 @@
         }
 
         mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
-        nSetup(mNativeProxy, mLightRadius,
-                mAmbientShadowAlpha, mSpotShadowAlpha);
 
         setLightCenter(attachInfo);
     }
@@ -598,27 +486,7 @@
         attachInfo.mDisplay.getRealSize(displaySize);
         final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
         final float lightY = mLightY - attachInfo.mWindowTop;
-
-        nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
-    }
-
-    /**
-     * Change the ThreadedRenderer's opacity
-     */
-    void setOpaque(boolean opaque) {
-        mIsOpaque = opaque && !mHasInsets;
-        nSetOpaque(mNativeProxy, mIsOpaque);
-    }
-
-    boolean isOpaque() {
-        return mIsOpaque;
-    }
-
-    /**
-     * Enable/disable wide gamut rendering on this renderer.
-     */
-    void setWideGamut(boolean wideGamut) {
-        nSetWideGamut(mNativeProxy, wideGamut);
+        setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
     }
 
     /**
@@ -663,18 +531,12 @@
                     break;
             }
         }
-        nDumpProfileInfo(mNativeProxy, fd, flags);
+        dumpProfileInfo(fd, flags);
     }
 
-    /**
-     * Loads system properties used by the renderer. This method is invoked
-     * whenever system properties are modified. Implementations can use this
-     * to trigger live updates of the renderer based on properties.
-     *
-     * @return True if a property has changed.
-     */
-    boolean loadSystemProperties() {
-        boolean changed = nLoadSystemProperties(mNativeProxy);
+    @Override
+    public boolean loadSystemProperties() {
+        boolean changed = super.loadSystemProperties();
         if (changed) {
             invalidateRoot();
         }
@@ -695,72 +557,27 @@
         updateViewTreeDisplayList(view);
 
         if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
-            RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+            RecordingCanvas canvas = mRootNode.startRecording(mSurfaceWidth, mSurfaceHeight);
             try {
                 final int saveCount = canvas.save();
                 canvas.translate(mInsetLeft, mInsetTop);
                 callbacks.onPreDraw(canvas);
 
-                canvas.insertReorderBarrier();
+                canvas.enableZ();
                 canvas.drawRenderNode(view.updateDisplayListIfDirty());
-                canvas.insertInorderBarrier();
+                canvas.disableZ();
 
                 callbacks.onPostDraw(canvas);
                 canvas.restoreToCount(saveCount);
                 mRootNodeNeedsUpdate = false;
             } finally {
-                mRootNode.end(canvas);
+                mRootNode.endRecording();
             }
         }
         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
     }
 
     /**
-     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
-     * rendernode of the UI thread.
-     * @param node The node to add.
-     * @param placeFront If true, the render node will be placed in front of the content node,
-     *                   otherwise behind the content node.
-     */
-    @UnsupportedAppUsage
-    public void addRenderNode(RenderNode node, boolean placeFront) {
-        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
-    }
-
-    /**
-     * Only especially added render nodes can be removed.
-     * @param node The node which was added via addRenderNode which should get removed again.
-     */
-    @UnsupportedAppUsage
-    public void removeRenderNode(RenderNode node) {
-        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
-    }
-
-    /**
-     * Draws a particular render node. If the node is not the content node, only the additional
-     * nodes will get drawn and the content remains untouched.
-     * @param node The node to be drawn.
-     */
-    @UnsupportedAppUsage
-    public void drawRenderNode(RenderNode node) {
-        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
-    }
-
-    /**
-     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
-     * will be prevented to overdraw this area. It will be synchronized with the draw call.
-     * This should be updated in the content view's draw call.
-     * @param left The left side of the protected bounds.
-     * @param top The top side of the protected bounds.
-     * @param right The right side of the protected bounds.
-     * @param bottom The bottom side of the protected bounds.
-     */
-    @UnsupportedAppUsage
-    public void setContentDrawBounds(int left, int top, int right, int bottom) {
-        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
-    }
-
-    /**
      * Interface used to receive callbacks whenever a view is drawn by
      * a threaded renderer instance.
      */
@@ -819,11 +636,10 @@
             attachInfo.mPendingAnimatingRenderNodes = null;
         }
 
-        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
         if (frameDrawingCallback != null) {
-            nSetFrameCallback(mNativeProxy, frameDrawingCallback);
+            setFrameCallback(frameDrawingCallback);
         }
-        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
+        int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
         if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
             setEnabled(false);
             attachInfo.mViewRootImpl.mSurface.release();
@@ -831,207 +647,40 @@
             // if it is still needed or do nothing if we are no longer drawing
             attachInfo.mViewRootImpl.invalidate();
         }
-        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+        if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
             attachInfo.mViewRootImpl.invalidate();
         }
     }
 
-    void setFrameCompleteCallback(FrameCompleteCallback callback) {
-        nSetFrameCompleteCallback(mNativeProxy, callback);
-    }
-
-    static void invokeFunctor(long functor, boolean waitForCompletion) {
-        nInvokeFunctor(functor, waitForCompletion);
-    }
-
-    /**
-     * Creates a new hardware layer. A hardware layer built by calling this
-     * method will be treated as a texture layer, instead of as a render target.
-     *
-     * @return A hardware layer
-     */
-    TextureLayer createTextureLayer() {
-        long layer = nCreateTextureLayer(mNativeProxy);
-        return TextureLayer.adoptTextureLayer(this, layer);
-    }
-
-
-    void buildLayer(RenderNode node) {
-        if (node.hasDisplayList()) {
-            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
-        }
-    }
-
-
-    boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
-        return nCopyLayerInto(mNativeProxy,
-                layer.getDeferredLayerUpdater(), bitmap);
-    }
-
-    /**
-     * Indicates that the specified hardware layer needs to be updated
-     * as soon as possible.
-     *
-     * @param layer The hardware layer that needs an update
-     */
-    void pushLayerUpdate(TextureLayer layer) {
-        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
-    }
-
-    /**
-     * Tells the HardwareRenderer that the layer is destroyed. The renderer
-     * should remove the layer from any update queues.
-     */
-    void onLayerDestroyed(TextureLayer layer) {
-        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
-    }
-
-    /**
-     * Blocks until all previously queued work has completed.
-     */
-    void fence() {
-        nFence(mNativeProxy);
-    }
-
-    /**
-     * Prevents any further drawing until draw() is called. This is a signal
-     * that the contents of the RenderNode tree are no longer safe to play back.
-     * In practice this usually means that there are Functor pointers in the
-     * display list that are no longer valid.
-     */
-    void stopDrawing() {
-        nStopDrawing(mNativeProxy);
-    }
-
-    /**
-     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
-     */
-    public void notifyFramePending() {
-        nNotifyFramePending(mNativeProxy);
-    }
-
-
-    void registerAnimatingRenderNode(RenderNode animator) {
-        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
-    }
-
-    void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
-        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
-                animator.getAnimatorNativePtr());
-    }
-
-    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
-        if (srcRect == null) {
-            // Empty rect means entire surface
-            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
-        } else {
-            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
-                    srcRect.right, srcRect.bottom, bitmap);
-        }
-    }
-
-    /**
-     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
-     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
-     * not the RenderNode from a View.
-     **/
-    @UnsupportedAppUsage
-    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
-        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
-    }
-
-    /**
-     * Sets whether or not high contrast text rendering is enabled. The setting is global
-     * but only affects content rendered after the change is made.
-     */
-    public static void setHighContrastText(boolean highContrastText) {
-        nSetHighContrastText(highContrastText);
-    }
-
-    /**
-     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
-     */
-    public static void setIsolatedProcess(boolean isIsolated) {
-        nSetIsolatedProcess(isIsolated);
-    }
-
-    /**
-     * If set extra graphics debugging abilities will be enabled such as dumping skp
-     */
-    public static void setDebuggingEnabled(boolean enable) {
-        nSetDebuggingEnabled(enable);
-    }
-
-    void allocateBuffers(Surface surface) {
-        nAllocateBuffers(mNativeProxy, surface);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            nDeleteProxy(mNativeProxy);
-            mNativeProxy = 0;
-        } finally {
-            super.finalize();
-        }
-    }
-
     /** The root of everything */
     public @NonNull RenderNode getRootNode() {
         return mRootNode;
     }
 
-    private boolean mForceDark = false;
-
-    /**
-     * Whether or not the force-dark feature should be used for this renderer.
-     */
-    public boolean setForceDark(boolean enable) {
-        if (mForceDark != enable) {
-            mForceDark = enable;
-            nSetForceDark(mNativeProxy, enable);
-            return true;
-        }
-        return false;
-    }
-
     /**
      * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
      * TODO: deduplicate against ThreadedRenderer.
      *
      * @hide
      */
-    public static class SimpleRenderer {
-        private final RenderNode mRootNode;
-        private long mNativeProxy;
-        private final float mLightY, mLightZ;
-        private Surface mSurface;
-        private final FrameInfo mFrameInfo = new FrameInfo();
+    public static class SimpleRenderer extends HardwareRenderer {
+        private final float mLightY, mLightZ, mLightRadius;
 
         public SimpleRenderer(final Context context, final String name, final Surface surface) {
+            super();
+            setName(name);
+            setOpaque(false);
+            setSurface(surface);
             final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
             mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
             mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
-            final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+            mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
             final int ambientShadowAlpha =
                     (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
             final int spotShadowAlpha =
                     (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
             a.recycle();
-
-            final long rootNodePtr = nCreateRootRenderNode();
-            mRootNode = RenderNode.adopt(rootNodePtr);
-            mRootNode.setClipToBounds(false);
-            mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
-            nSetName(mNativeProxy, name);
-
-            ProcessInitializer.sInstance.init(context, mNativeProxy);
-            nLoadSystemProperties(mNativeProxy);
-
-            nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
-
-            mSurface = surface;
-            nUpdateSurface(mNativeProxy, surface);
+            setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
         }
 
         /**
@@ -1045,7 +694,7 @@
             final float lightX = displaySize.x / 2f - windowLeft;
             final float lightY = mLightY - windowTop;
 
-            nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
+            setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
         }
 
         public RenderNode getRootNode() {
@@ -1057,222 +706,10 @@
          */
         public void draw(final FrameDrawingCallback callback) {
             final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
-            mFrameInfo.setVsync(vsync, vsync);
-            mFrameInfo.addFlags(1 << 2 /* VSYNC */);
             if (callback != null) {
-                nSetFrameCallback(mNativeProxy, callback);
+                setFrameCallback(callback);
             }
-            nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
-        }
-
-        /**
-         * Destroy the renderer.
-         */
-        public void destroy() {
-            mSurface = null;
-            nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            try {
-                nDeleteProxy(mNativeProxy);
-                mNativeProxy = 0;
-            } finally {
-                super.finalize();
-            }
+            syncAndDrawFrame(vsync);
         }
     }
-
-    /**
-     * Interface used to receive callbacks when a frame is being drawn.
-     */
-    public interface FrameDrawingCallback {
-        /**
-         * Invoked during a frame drawing.
-         *
-         * @param frame The id of the frame being drawn.
-         */
-        void onFrameDraw(long frame);
-    }
-
-    /**
-     * Interface used to be notified when a frame has finished rendering
-     */
-    public interface FrameCompleteCallback {
-        /**
-         * Invoked after a frame draw
-         *
-         * @param frameNr The id of the frame that was drawn.
-         */
-        void onFrameComplete(long frameNr);
-    }
-
-    private static class ProcessInitializer {
-        static ProcessInitializer sInstance = new ProcessInitializer();
-
-        private boolean mInitialized = false;
-
-        private Context mAppContext;
-        private IGraphicsStats mGraphicsStatsService;
-        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
-            @Override
-            public void onRotateGraphicsStatsBuffer() throws RemoteException {
-                rotateBuffer();
-            }
-        };
-
-        private ProcessInitializer() {}
-
-        synchronized void init(Context context, long renderProxy) {
-            if (mInitialized) return;
-            mInitialized = true;
-            mAppContext = context.getApplicationContext();
-
-            initSched(renderProxy);
-
-            if (mAppContext != null) {
-                initGraphicsStats();
-            }
-        }
-
-        private void initSched(long renderProxy) {
-            try {
-                int tid = nGetRenderThreadTid(renderProxy);
-                ActivityManager.getService().setRenderThread(tid);
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
-            }
-        }
-
-        private void initGraphicsStats() {
-            try {
-                IBinder binder = ServiceManager.getService("graphicsstats");
-                if (binder == null) return;
-                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
-                requestBuffer();
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
-            }
-        }
-
-        private void rotateBuffer() {
-            nRotateProcessStatsBuffer();
-            requestBuffer();
-        }
-
-        private void requestBuffer() {
-            try {
-                final String pkg = mAppContext.getApplicationInfo().packageName;
-                ParcelFileDescriptor pfd = mGraphicsStatsService
-                        .requestBufferForProcess(pkg, mGraphicsStatsCallback);
-                nSetProcessStatsBuffer(pfd.getFd());
-                pfd.close();
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
-            }
-        }
-    }
-
-    void addFrameMetricsObserver(FrameMetricsObserver observer) {
-        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
-        observer.mNative = new VirtualRefBasePtr(nativeObserver);
-    }
-
-    void removeFrameMetricsObserver(FrameMetricsObserver observer) {
-        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
-        observer.mNative = null;
-    }
-
-    /** b/68769804: For low FPS experiments. */
-    public static void setFPSDivisor(int divisor) {
-        nHackySetRTAnimationsEnabled(divisor <= 1);
-    }
-
-    /**
-     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
-     * called before any OpenGL context is created.
-     *
-     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
-     */
-    public static void setContextPriority(int priority) {
-        nSetContextPriority(priority);
-    }
-
-    /** Not actually public - internal use only. This doc to make lint happy */
-    public static native void disableVsync();
-
-    static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
-
-    private static native void nRotateProcessStatsBuffer();
-    private static native void nSetProcessStatsBuffer(int fd);
-    private static native int nGetRenderThreadTid(long nativeProxy);
-
-    private static native long nCreateRootRenderNode();
-    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
-    private static native void nDeleteProxy(long nativeProxy);
-
-    private static native boolean nLoadSystemProperties(long nativeProxy);
-    private static native void nSetName(long nativeProxy, String name);
-
-    private static native void nInitialize(long nativeProxy, Surface window);
-    private static native void nUpdateSurface(long nativeProxy, Surface window);
-    private static native boolean nPauseSurface(long nativeProxy, Surface window);
-    private static native void nSetStopped(long nativeProxy, boolean stopped);
-    private static native void nSetup(long nativeProxy,
-            float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
-    private static native void nSetLightCenter(long nativeProxy,
-            float lightX, float lightY, float lightZ);
-    private static native void nSetOpaque(long nativeProxy, boolean opaque);
-    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
-    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
-    private static native void nDestroy(long nativeProxy, long rootRenderNode);
-    private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
-    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
-
-    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
-
-    private static native long nCreateTextureLayer(long nativeProxy);
-    private static native void nBuildLayer(long nativeProxy, long node);
-    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
-    private static native void nPushLayerUpdate(long nativeProxy, long layer);
-    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
-    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
-
-    private static native void nDestroyHardwareResources(long nativeProxy);
-    private static native void nTrimMemory(int level);
-    private static native void nOverrideProperty(String name, String value);
-
-    private static native void nFence(long nativeProxy);
-    private static native void nStopDrawing(long nativeProxy);
-    private static native void nNotifyFramePending(long nativeProxy);
-
-    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
-            @DumpFlags int dumpFlags);
-
-    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
-             boolean placeFront);
-    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
-    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
-    private static native void nSetContentDrawBounds(long nativeProxy, int left,
-             int top, int right, int bottom);
-    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
-    private static native void nSetFrameCompleteCallback(long nativeProxy,
-            FrameCompleteCallback callback);
-
-    private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
-    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
-
-    private static native int nCopySurfaceInto(Surface surface,
-            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
-
-    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
-    private static native void nSetHighContrastText(boolean enabled);
-    // For temporary experimentation b/66945974
-    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
-    private static native void nSetDebuggingEnabled(boolean enabled);
-    private static native void nSetIsolatedProcess(boolean enabled);
-    private static native void nSetContextPriority(int priority);
-    private static native void nAllocateBuffers(long nativeProxy, Surface window);
-    private static native void nSetForceDark(long nativeProxy, boolean enabled);
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dd1f640..a23d68b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -46,6 +46,8 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.FrameInfo;
+import android.graphics.HardwareRenderer.FrameDrawingCallback;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -84,7 +86,6 @@
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl.Transaction;
-import android.view.ThreadedRenderer.FrameDrawingCallback;
 import android.view.View.AttachInfo;
 import android.view.View.FocusDirection;
 import android.view.View.MeasureSpec;
@@ -2148,7 +2149,7 @@
                     // relayoutWindow may decide to destroy mSurface. As that decision
                     // happens in WindowManager service, we need to be defensive here
                     // and stop using the surface in case it gets destroyed.
-                    if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
+                    if (mAttachInfo.mThreadedRenderer.pause()) {
                         // Animations were running so we need to push a frame
                         // to resume them
                         mDirty.set(0, 0, mWidth, mHeight);
@@ -2266,7 +2267,7 @@
                                         & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                                     // Don't pre-allocate if transparent regions
                                     // are requested as they may not be needed
-                                    mAttachInfo.mThreadedRenderer.allocateBuffers(mSurface);
+                                    mAttachInfo.mThreadedRenderer.allocateBuffers();
                                 }
                             } catch (OutOfResourcesException e) {
                                 handleOutOfResourcesException(e);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f512ce4..b8139a7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -556,18 +556,18 @@
         proxy->setWideGamut(true);
     }
     proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
-    proxy->initialize(surface);
+    proxy->setSurface(surface);
     // Shadows can't be used via this interface, so just set the light source
     // to all 0s.
-    proxy->setup(0, 0, 0);
-    proxy->setLightCenter((Vector3){0, 0, 0});
+    proxy->setLightAlpha(0, 0);
+    proxy->setLightGeometry((Vector3){0, 0, 0}, 0);
     return (jlong) proxy;
 }
 
 static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
     sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
-    proxy->updateSurface(surface);
+    proxy->setSurface(surface);
 }
 
 static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7a5b604..702741e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -686,31 +686,20 @@
     env->ReleaseStringUTFChars(jname, name);
 }
 
-static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
-    proxy->initialize(surface);
-}
-
-static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     sp<Surface> surface;
     if (jsurface) {
         surface = android_view_Surface_getSurface(env, jsurface);
     }
-    proxy->updateSurface(surface);
+    proxy->setSurface(surface);
 }
 
-static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
+static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface;
-    if (jsurface) {
-        surface = android_view_Surface_getSurface(env, jsurface);
-    }
-    return proxy->pauseSurface(surface);
+    return proxy->pause();
 }
 
 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
@@ -719,16 +708,16 @@
     proxy->setStopped(stopped);
 }
 
-static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
-        jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
+static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
+        jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
+    proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
 }
 
-static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
+static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
+    proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
 }
 
 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -990,13 +979,12 @@
     {
         ContextFactory factory;
         RenderProxy proxy{true, renderNode, &factory};
-        proxy.loadSystemProperties();
         proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
-        proxy.initialize(surface);
+        proxy.setSurface(surface);
         // Shadows can't be used via this interface, so just set the light source
         // to all 0s.
-        proxy.setup(0, 0, 0);
-        proxy.setLightCenter((Vector3){0, 0, 0});
+        proxy.setLightAlpha(0, 0);
+        proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
         nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
         UiFrameInfoBuilder(proxy.frameInfo())
                 .setVsync(vsync, vsync)
@@ -1058,10 +1046,9 @@
 }
 
 static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
-    proxy->allocateBuffers(surface);
+    proxy->allocateBuffers();
 }
 
 static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
@@ -1118,7 +1105,7 @@
 // JNI Glue
 // ----------------------------------------------------------------------------
 
-const char* const kClassPathName = "android/view/ThreadedRenderer";
+const char* const kClassPathName = "android/graphics/HardwareRenderer";
 
 static const JNINativeMethod gMethods[] = {
     { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
@@ -1129,12 +1116,11 @@
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
     { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
-    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
-    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
-    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
+    { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface },
+    { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause },
     { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
-    { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
+    { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha },
+    { "nSetLightGeometry", "(JFFFF)V", (void*) android_view_ThreadedRenderer_setLightGeometry },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
     { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
@@ -1161,9 +1147,9 @@
     { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
     { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
     { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
-    { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
+    { "nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
             (void*)android_view_ThreadedRenderer_setFrameCallback},
-    { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
+    { "nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
             (void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
     { "nAddFrameMetricsObserver",
             "(JLandroid/view/FrameMetricsObserver;)J",
@@ -1182,7 +1168,7 @@
     { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
     { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
     { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
-    { "nAllocateBuffers", "(JLandroid/view/Surface;)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
+    { "nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
     { "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
 };
 
@@ -1215,12 +1201,12 @@
             env, metricsClass, "mTimingData", "[J");
 
     jclass frameCallbackClass = FindClassOrDie(env,
-            "android/view/ThreadedRenderer$FrameDrawingCallback");
+            "android/graphics/HardwareRenderer$FrameDrawingCallback");
     gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
             "onFrameDraw", "(J)V");
 
     jclass frameCompleteClass = FindClassOrDie(env,
-            "android/view/ThreadedRenderer$FrameCompleteCallback");
+            "android/graphics/HardwareRenderer$FrameCompleteCallback");
     gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
             "onFrameComplete", "(J)V");
 
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 69ebb59..e0e7b6f 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -270,6 +270,7 @@
         optional SettingProto enable_freeform_windows_support = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto force_rtl = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto emulate_display_cutout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto force_desktop_mode_on_external_displays = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Development development = 39;
 
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 36efd0a..c26bebe 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -33,7 +33,7 @@
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index a11dd95..96338b58 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -30,7 +30,7 @@
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 8d29ec1..79f4bb6 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -34,7 +34,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 650aa62..10b007e 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -32,7 +32,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 4bb68dc..657d1e7 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -28,7 +28,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index 735a8c8..ba8c75a 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -34,7 +34,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a8c78a6..bca72f4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2793,7 +2793,7 @@
         <item>LPP_PROFILE=0</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
     <!-- Sprint need a 70 ms delay for 3way call -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8d3992d..200c35d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -248,6 +248,10 @@
         <item>@string/wfcSpnFormat_spn_wifi</item>
         <item>@string/wfcSpnFormat_wifi_calling_bar_spn</item>
         <item>@string/wfcSpnFormat_spn_vowifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling</item>
+        <item>@string/wfcSpnFormat_wifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling_wo_hyphen</item>
+        <item>@string/wfcSpnFormat_vowifi</item>
     </string-array>
 
     <!-- Spn during Wi-Fi Calling: "<operator>" -->
@@ -264,6 +268,14 @@
     <string name="wfcSpnFormat_wifi_calling_bar_spn">WiFi Calling | <xliff:g id="spn" example="Operator">%s</xliff:g></string>
     <!-- Spn during Wi-Fi Calling: "<operator> VoWifi" -->
     <string name="wfcSpnFormat_spn_vowifi"><xliff:g id="spn" example="Operator">%s</xliff:g> VoWifi</string>
+    <!-- Spn during Wi-Fi Calling: "Wi-Fi Calling" -->
+    <string name="wfcSpnFormat_wifi_calling">Wi-Fi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "Wi-Fi" -->
+    <string name="wfcSpnFormat_wifi">Wi-Fi</string>
+    <!-- Spn during Wi-Fi Calling: "WiFi Calling" (without hyphen) -->
+    <string name="wfcSpnFormat_wifi_calling_wo_hyphen">WiFi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "VoWifi" -->
+    <string name="wfcSpnFormat_vowifi">VoWifi</string>
 
     <!-- WFC, summary for Disabled -->
     <string name="wifi_calling_off_summary">Off</string>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 3342266..63dd59a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -197,6 +197,7 @@
                     Settings.Global.DESK_DOCK_SOUND,
                     Settings.Global.DESK_UNDOCK_SOUND,
                     Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
+                    Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
                     Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
                     Settings.Global.DEVELOPMENT_FORCE_RTL,
                     Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
diff --git a/core/java/android/view/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
similarity index 70%
rename from core/java/android/view/FrameInfo.java
rename to graphics/java/android/graphics/FrameInfo.java
index 6c5e048..42a5cc4 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.graphics;
 
 import android.annotation.LongDef;
 
@@ -33,14 +33,14 @@
  * long layout & measure took it's displayListRecordStart - performTraversalsStart.
  *
  * These constants must be kept in sync with FrameInfo.h in libhwui and are
- * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * used for indexing into AttachInfo's frameInfo long[], which is intended
  * to be quick to pass down to native via JNI, hence a pre-packed format
  *
  * @hide
  */
-final class FrameInfo {
+public final class FrameInfo {
 
-    long[] mFrameInfo = new long[9];
+    public long[] frameInfo = new long[9];
 
     // Various flags set to provide extra metadata about the current frame
     private static final int FLAGS = 0;
@@ -48,8 +48,11 @@
     // Is this the first-draw following a window layout?
     public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
 
+    // A renderer associated with just a Surface, not with a ViewRootImpl instance.
+    public static final long FLAG_SURFACE_CANVAS = 1 << 2;
+
     @LongDef(flag = true, value = {
-            FLAG_WINDOW_LAYOUT_CHANGED })
+            FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FrameInfoFlags {}
 
@@ -78,41 +81,48 @@
     // When View:draw() started
     private static final int DRAW_START = 8;
 
+    /** checkstyle */
     public void setVsync(long intendedVsync, long usedVsync) {
-        mFrameInfo[INTENDED_VSYNC] = intendedVsync;
-        mFrameInfo[VSYNC] = usedVsync;
-        mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
-        mFrameInfo[NEWEST_INPUT_EVENT] = 0;
-        mFrameInfo[FLAGS] = 0;
+        frameInfo[INTENDED_VSYNC] = intendedVsync;
+        frameInfo[VSYNC] = usedVsync;
+        frameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+        frameInfo[NEWEST_INPUT_EVENT] = 0;
+        frameInfo[FLAGS] = 0;
     }
 
+    /** checkstyle */
     public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
-        if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
-            mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+        if (inputEventOldestTime < frameInfo[OLDEST_INPUT_EVENT]) {
+            frameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
         }
-        if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
-            mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+        if (inputEventTime > frameInfo[NEWEST_INPUT_EVENT]) {
+            frameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
         }
     }
 
+    /** checkstyle */
     public void markInputHandlingStart() {
-        mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+        frameInfo[HANDLE_INPUT_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markAnimationsStart() {
-        mFrameInfo[ANIMATION_START] = System.nanoTime();
+        frameInfo[ANIMATION_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markPerformTraversalsStart() {
-        mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+        frameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markDrawStart() {
-        mFrameInfo[DRAW_START] = System.nanoTime();
+        frameInfo[DRAW_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void addFlags(@FrameInfoFlags long flags) {
-        mFrameInfo[FLAGS] |= flags;
+        frameInfo[FLAGS] |= flags;
     }
 
 }
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
new file mode 100644
index 0000000..e402055
--- /dev/null
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -0,0 +1,1030 @@
+/*
+ * 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.graphics;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.FrameMetricsObserver;
+import android.view.IGraphicsStats;
+import android.view.IGraphicsStatsCallback;
+import android.view.NativeVectorDrawableAnimator;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.TextureLayer;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import sun.misc.Cleaner;
+
+/**
+ * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
+ * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
+ * HardwareRenderer instances as desired.</p>
+ *
+ * <h3>Threading</h3>
+ * <p>HardwareRenderer is not thread safe. An instance of a HardwareRenderer must only be
+ * created & used from a single thread. It does not matter what thread is used, however
+ * it must have a {@link android.os.Looper}. Multiple instances do not have to share the same
+ * thread, although they can.</p>
+ *
+ * <h3>Resources & lifecycle</h3>
+ * <p>All HardwareRenderer instances share a common render thread. The render thread contains
+ * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
+ * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
+ * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
+ * is to have a HardwareRenderer instance for every active {@link Surface}. For example
+ * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
+ * of which may be drawing at the same time.</p>
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @hide
+ */
+public class HardwareRenderer {
+    private static final String LOG_TAG = "HardwareRenderer";
+
+    // Keep in sync with DrawFrameTask.h SYNC_* flags
+    /**
+     * Nothing interesting to report. Sync & draw kicked off
+     */
+    public static final int SYNC_OK = 0;
+
+    /**
+     * The renderer is requesting a redraw. This can occur if there's an animation that's running
+     * in the RenderNode tree and the hardware renderer is unable to self-animate.
+     *
+     * If this is returned from syncAndDrawFrame the expectation is that syncAndDrawFrame
+     * will be called again on the next vsync signal.
+     */
+    public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
+
+    /**
+     * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
+     * This can happen if {@link Surface#destroy()} was called. The user should no longer
+     * attempt to call syncAndDrawFrame until a new surface has been provided by calling
+     * setSurface.
+     *
+     * Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
+     */
+    public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
+
+    /**
+     * The hardware renderer has been set to a "stopped" state. If this is returned then the
+     * rendering content has been synced, however a frame was not produced.
+     */
+    public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
+
+    /**
+     * The content was synced but the renderer has declined to produce a frame in this vsync
+     * interval. This can happen if a frame was already drawn in this vsync or if the renderer
+     * is outrunning the frame consumer. The renderer will internally re-schedule itself
+     * to render a frame in the next vsync signal, so the caller does not need to do anything
+     * in response to this signal.
+     */
+    public static final int SYNC_FRAME_DROPPED = 1 << 3;
+
+    @IntDef(value = {
+            SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
+            SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SyncAndDrawResult {
+    }
+
+    /** @hide */
+    public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+    /** @hide */
+    public static final int FLAG_DUMP_RESET = 1 << 1;
+    /** @hide */
+    public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
+            FLAG_DUMP_FRAMESTATS,
+            FLAG_DUMP_RESET
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DumpFlags {
+    }
+
+    /**
+     * Name of the file that holds the shaders cache.
+     */
+    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
+    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
+
+    private final long mNativeProxy;
+    /** @hide */
+    protected RenderNode mRootNode;
+    private boolean mOpaque = true;
+    private boolean mForceDark = false;
+    private FrameInfo mScratchInfo;
+
+    /**
+     * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
+     * to opaque with no light source configured.
+     */
+    public HardwareRenderer() {
+        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
+        mRootNode.setClipToBounds(false);
+        mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
+        if (mNativeProxy == 0) {
+            throw new OutOfMemoryError("Unable to create hardware renderer");
+        }
+        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
+        ProcessInitializer.sInstance.init(mNativeProxy);
+    }
+
+    /**
+     * Destroys the rendering context of this HardwareRenderer. This destroys the resources
+     * associated with this renderer and releases the currently set {@link Surface}.
+     *
+     * The renderer may be restored from this state by setting a new {@link Surface}, setting
+     * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
+     * rendering with {@link #syncAndDrawFrame(long)}.
+     *
+     * It is suggested to call this in response to callbacks such as
+     * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
+     *
+     * Note that if there are any outstanding frame commit callbacks they may end up never being
+     * invoked if the frame was deferred to a later vsync.
+     */
+    public void destroy() {
+        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+    }
+
+    /**
+     * Sets a name for this renderer. This is used to identify this renderer instance
+     * when reporting debug information such as the per-window frame time metrics
+     * reported by 'adb shell dumpsys gfxinfo [package] framestats'
+     *
+     * @param name The debug name to use for this HardwareRenderer instance
+     */
+    public void setName(String name) {
+        nSetName(mNativeProxy, name);
+    }
+
+    /**
+     * Sets the center of the light source. The light source point controls the directionality
+     * and shape of shadows rendered by RenderNode Z & elevation.
+     *
+     * The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
+     * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
+     *
+     * The light source should be setup both as part of initial configuration, and whenever
+     * the window moves to ensure the light source stays anchored in display space instead
+     * of in window space.
+     *
+     * This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
+     * before shadows will work.
+     *
+     * @param lightX      The X position of the light source
+     * @param lightY      The Y position of the light source
+     * @param lightZ      The Z position of the light source. Must be >= 0.
+     * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
+     *                    larger radius will have softer shadows.
+     */
+    public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
+            float lightRadius) {
+        validateFinite(lightX, "lightX");
+        validateFinite(lightY, "lightY");
+        validatePositive(lightZ, "lightZ");
+        validatePositive(lightRadius, "lightRadius");
+        nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
+    }
+
+    /**
+     * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
+     * has max alpha, and ramps down from the values provided to zero.
+     *
+     * These values are typically provided by the current theme, see
+     * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
+     *
+     * This must be set at least once along with
+     * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
+     *
+     * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
+     *                           is 0.039f.
+     * @param spotShadowAlpha    The alpha for the spot shadow. If unsure, a reasonable default is
+     *                           0.19f.
+     */
+    public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
+            @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
+        validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
+        validateAlpha(spotShadowAlpha, "spotShadowAlpha");
+        nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
+    }
+
+    /**
+     * Sets the content root to render. It is not necessary to call this whenever the content
+     * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
+     * contained within the content node, will be applied whenever {@link #syncAndDrawFrame(long)}
+     * is called.
+     *
+     * @param content The content to set as the root RenderNode. If null the content root is removed
+     *                and the renderer will draw nothing.
+     */
+    public void setContentRoot(@Nullable RenderNode content) {
+        RecordingCanvas canvas = mRootNode.startRecording();
+        if (content != null) {
+            canvas.drawRenderNode(content);
+        }
+        mRootNode.endRecording();
+    }
+
+    /**
+     * <p>The surface to render into. The surface is assumed to be associated with the display and
+     * as such is still driven by vsync signals such as those from
+     * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
+     * the display's (typically 60hz).</p>
+     *
+     * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+     * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+     * consumers such as {@link android.view.SurfaceView},
+     * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+     * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+     * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+     * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+     * Failure to do so will cause the render thread to stall on that surface, blocking all
+     * HardwareRenderer instances.</p>
+     *
+     * @param surface The surface to render into. If null then rendering will be stopped. If
+     *                non-null then {@link Surface#isValid()} must be true.
+     */
+    public void setSurface(@Nullable Surface surface) {
+        if (surface != null && !surface.isValid()) {
+            throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
+        }
+        nSetSurface(mNativeProxy, surface);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     *
+     * @hide
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
+        return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     *
+     * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+     *                  {@link android.view.Choreographer.FrameCallback}. Must be set and be valid
+     *                  as the renderer uses this time internally to drive animations.
+     * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(long vsyncTime) {
+        if (mScratchInfo == null) {
+            mScratchInfo = new FrameInfo();
+        }
+        mScratchInfo.setVsync(vsyncTime, vsyncTime);
+        mScratchInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
+        return syncAndDrawFrame(mScratchInfo);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     * frameCommitCallback callback will be invoked when the current rendering content has been
+     * rendered into a frame and submitted to the swap chain.
+     *
+     * @param vsyncTime           The vsync timestamp for this frame. Typically this comes from
+     *                            {@link android.view.Choreographer.FrameCallback}. Must be set and
+     *                            be valid as the renderer uses this time internally to drive
+     *                            animations.
+     * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
+     *                            Will be invoked on the current {@link android.os.Looper} thread.
+     * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(long vsyncTime,
+            @Nullable Runnable frameCommitCallback) {
+        if (frameCommitCallback != null) {
+            setFrameCompleteCallback(frameNr -> frameCommitCallback.run());
+        }
+        return syncAndDrawFrame(vsyncTime);
+    }
+
+    /**
+     * Suspends any current rendering into the surface but do not do any destruction. This
+     * is useful to temporarily suspend using the active Surface in order to do any Surface
+     * mutations necessary.
+     *
+     * Any subsequent draws will override the pause, resuming normal operation.
+     *
+     * @return true if there was an outstanding render request, false otherwise. If this is true
+     * the caller should ensure that {@link #syncAndDrawFrame(long)} is called at the soonest
+     * possible time to resume normal operation.
+     *
+     * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
+     * Surface before getting a new one. However things like SurfaceView will ensure that
+     * the old surface remains un-destroyed until after a new frame has been produced with
+     * the new surface.
+     * @hide
+     */
+    public boolean pause() {
+        return nPause(mNativeProxy);
+    }
+
+    /**
+     * Hard stops rendering into the surface. If the renderer is stopped it will
+     * block any attempt to render. Calls to {@link #syncAndDrawFrame(long)} will still
+     * sync over the latest rendering content, however they will not render and instead
+     * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
+     *
+     * If false is passed then rendering will resume as normal. Any pending rendering requests
+     * will produce a new frame at the next vsync signal.
+     *
+     * This is useful in combination with lifecycle events such as {@link Activity#onStop()}
+     * and {@link Activity#onStart()}.
+     *
+     * @param stopped true to stop all rendering, false to resume
+     */
+    public void setStopped(boolean stopped) {
+        nSetStopped(mNativeProxy, stopped);
+    }
+
+    /**
+     * Destroys all hardware rendering resources associated with the current rendering content.
+     * This includes releasing a reference to the current content root RenderNode. It will
+     * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
+     * rendering after calling this.
+     *
+     * It is recommended, but not necessary, to use this in combination with lifecycle events
+     * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
+     * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
+     * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
+     *
+     * See also {@link #setStopped(boolean)}
+     */
+    public void destroyHardwareResources() {
+        nDestroyHardwareResources(mNativeProxy);
+    }
+
+    /**
+     * Whether or not the force-dark feature should be used for this renderer.
+     */
+    public boolean setForceDark(boolean enable) {
+        if (mForceDark != enable) {
+            mForceDark = enable;
+            nSetForceDark(mNativeProxy, enable);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Allocate buffers ahead of time to avoid allocation delays during rendering.
+     *
+     * Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
+     * memory usage of Surfaces that render rarely or never hit triple buffering. However
+     * for UI it can result in a slight bit of jank on first launch. This hint will
+     * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
+     * necessary for typical rendering.
+     *
+     * Must be called after a {@link Surface} has been set.
+     */
+    public void allocateBuffers() {
+        nAllocateBuffers(mNativeProxy);
+    }
+
+    /**
+     * Notifies the hardware renderer that a call to {@link #syncAndDrawFrame(long)} will
+     * be coming soon. This is used to help schedule when RenderThread-driven animations will
+     * happen as the renderer wants to avoid producing more than one frame per vsync signal.
+     */
+    public void notifyFramePending() {
+        nNotifyFramePending(mNativeProxy);
+    }
+
+    /**
+     * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
+     *
+     * If the renderer is set to opaque it is the app's responsibility to ensure that the
+     * content renders to every pixel of the Surface, otherwise corruption may result. Note that
+     * this includes ensuring that the first draw of any given pixel does not attempt to blend
+     * against the destination. If this is false then the hardware renderer will clear to
+     * transparent at the start of every frame.
+     *
+     * @param opaque true if the content rendered is opaque, false if the renderer should clear
+     *               to transparent before rendering
+     */
+    public void setOpaque(boolean opaque) {
+        if (mOpaque != opaque) {
+            mOpaque = opaque;
+            nSetOpaque(mNativeProxy, mOpaque);
+        }
+    }
+
+    /**
+     * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
+     *
+     * @return true if the renderer is opaque, false otherwise
+     */
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    /** @hide */
+    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
+        nSetFrameCompleteCallback(mNativeProxy, callback);
+    }
+
+    /**
+     * TODO: Public API this?
+     *
+     * @hide
+     */
+    public void addFrameMetricsObserver(FrameMetricsObserver observer) {
+        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+        observer.mNative = new VirtualRefBasePtr(nativeObserver);
+    }
+
+    /**
+     * TODO: Public API this?
+     *
+     * @hide
+     */
+    public void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+        observer.mNative = null;
+    }
+
+    /**
+     * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
+     * will be wide gamut depends on the hardware support for such rendering.
+     *
+     * @param wideGamut true if this renderer should render in wide gamut, false if it should
+     *                  render in sRGB
+     *                  TODO: Figure out color...
+     * @hide
+     */
+    public void setWideGamut(boolean wideGamut) {
+        nSetWideGamut(mNativeProxy, wideGamut);
+    }
+
+    /**
+     * Blocks until all previously queued work has completed.
+     *
+     * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
+     * better
+     *
+     * @hide
+     */
+    public void fence() {
+        nFence(mNativeProxy);
+    }
+
+    /** @hide */
+    public void registerAnimatingRenderNode(RenderNode animator) {
+        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
+    }
+
+    /** @hide */
+    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
+        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
+                animator.getAnimatorNativePtr());
+    }
+
+    /**
+     * Prevents any further drawing until {@link #syncAndDrawFrame(long)} is called.
+     * This is a signal that the contents of the RenderNode tree are no longer safe to play back.
+     * In practice this usually means that there are Functor pointers in the
+     * display list that are no longer valid.
+     *
+     * TODO: Can we get webview off of this?
+     *
+     * @hide
+     */
+    public void stopDrawing() {
+        nStopDrawing(mNativeProxy);
+    }
+
+    /**
+     * Creates a new hardware layer. A hardware layer built by calling this
+     * method will be treated as a texture layer, instead of as a render target.
+     *
+     * @return A hardware layer
+     * @hide
+     */
+    public TextureLayer createTextureLayer() {
+        long layer = nCreateTextureLayer(mNativeProxy);
+        return TextureLayer.adoptTextureLayer(this, layer);
+    }
+
+    /**
+     * Detaches the layer's surface texture from the GL context and releases
+     * the texture id
+     *
+     * @hide
+     */
+    public void detachSurfaceTexture(long hardwareLayer) {
+        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
+    }
+
+
+    /** @hide */
+    public void buildLayer(RenderNode node) {
+        if (node.hasDisplayList()) {
+            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
+        }
+    }
+
+    /** @hide */
+    public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
+        return nCopyLayerInto(mNativeProxy,
+                layer.getDeferredLayerUpdater(), bitmap);
+    }
+
+    /**
+     * Indicates that the specified hardware layer needs to be updated
+     * as soon as possible.
+     *
+     * @param layer The hardware layer that needs an update
+     * @hide
+     */
+    public void pushLayerUpdate(TextureLayer layer) {
+        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+    }
+
+    /**
+     * Tells the HardwareRenderer that the layer is destroyed. The renderer
+     * should remove the layer from any update queues.
+     *
+     * @hide
+     */
+    public void onLayerDestroyed(TextureLayer layer) {
+        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+    }
+
+    /** @hide */
+    public void setFrameCallback(FrameDrawingCallback callback) {
+        nSetFrameCallback(mNativeProxy, callback);
+    }
+
+    /**
+     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+     * rendernode of the UI thread.
+     *
+     * @param node       The node to add.
+     * @param placeFront If true, the render node will be placed in front of the content node,
+     *                   otherwise behind the content node.
+     * @hide
+     */
+    public void addRenderNode(RenderNode node, boolean placeFront) {
+        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+    }
+
+    /**
+     * Only especially added render nodes can be removed.
+     *
+     * @param node The node which was added via addRenderNode which should get removed again.
+     * @hide
+     */
+    public void removeRenderNode(RenderNode node) {
+        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * Draws a particular render node. If the node is not the content node, only the additional
+     * nodes will get drawn and the content remains untouched.
+     *
+     * @param node The node to be drawn.
+     * @hide
+     */
+    public void drawRenderNode(RenderNode node) {
+        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * Loads system properties used by the renderer. This method is invoked
+     * whenever system properties are modified. Implementations can use this
+     * to trigger live updates of the renderer based on properties.
+     *
+     * @return True if a property has changed.
+     * @hide
+     */
+    public boolean loadSystemProperties() {
+        return nLoadSystemProperties(mNativeProxy);
+    }
+
+    /**
+     * @hide
+     */
+    public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
+        nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
+    }
+
+    /**
+     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+     * will be prevented to overdraw this area. It will be synchronized with the draw call.
+     * This should be updated in the content view's draw call.
+     *
+     * @param left   The left side of the protected bounds.
+     * @param top    The top side of the protected bounds.
+     * @param right  The right side of the protected bounds.
+     * @param bottom The bottom side of the protected bounds.
+     * @hide
+     */
+    public void setContentDrawBounds(int left, int top, int right, int bottom) {
+        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
+    }
+
+    /**
+     * Interface used to receive callbacks when a frame is being drawn.
+     *
+     * @hide
+     */
+    public interface FrameDrawingCallback {
+        /**
+         * Invoked during a frame drawing.
+         *
+         * @param frame The id of the frame being drawn.
+         */
+        void onFrameDraw(long frame);
+    }
+
+    /**
+     * Interface used to be notified when a frame has finished rendering
+     *
+     * @hide
+     */
+    public interface FrameCompleteCallback {
+        /**
+         * Invoked after a frame draw
+         *
+         * @param frameNr The id of the frame that was drawn.
+         */
+        void onFrameComplete(long frameNr);
+    }
+
+    private static void validateAlpha(float alpha, String argumentName) {
+        if (!(alpha >= 0.0f && alpha <= 1.0f)) {
+            throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
+                    + alpha + " is not in the range of 0.0f to 1.0f");
+        }
+    }
+
+    private static void validatePositive(float f, String argumentName) {
+        if (!(Float.isFinite(f) && f >= 0.0f)) {
+            throw new IllegalArgumentException(argumentName
+                    + " must be a finite positive, given=" + f);
+        }
+    }
+
+    private static void validateFinite(float f, String argumentName) {
+        if (!Float.isFinite(f)) {
+            throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
+        }
+    }
+
+    /** @hide */
+    public static void invokeFunctor(long functor, boolean waitForCompletion) {
+        nInvokeFunctor(functor, waitForCompletion);
+    }
+
+    /**
+     * b/68769804: For low FPS experiments.
+     *
+     * @hide
+     */
+    public static void setFPSDivisor(int divisor) {
+        nHackySetRTAnimationsEnabled(divisor <= 1);
+    }
+
+    /**
+     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
+     * called before any OpenGL context is created.
+     *
+     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
+     * @hide
+     */
+    public static void setContextPriority(int priority) {
+        nSetContextPriority(priority);
+    }
+
+    /**
+     * Sets whether or not high contrast text rendering is enabled. The setting is global
+     * but only affects content rendered after the change is made.
+     *
+     * @hide
+     */
+    public static void setHighContrastText(boolean highContrastText) {
+        nSetHighContrastText(highContrastText);
+    }
+
+    /**
+     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
+     *
+     * @hide
+     */
+    public static void setIsolatedProcess(boolean isIsolated) {
+        nSetIsolatedProcess(isIsolated);
+    }
+
+    /**
+     * If set extra graphics debugging abilities will be enabled such as dumping skp
+     *
+     * @hide
+     */
+    public static void setDebuggingEnabled(boolean enable) {
+        nSetDebuggingEnabled(enable);
+    }
+
+    /** @hide */
+    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
+        if (srcRect == null) {
+            // Empty rect means entire surface
+            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
+        } else {
+            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
+                    srcRect.right, srcRect.bottom, bitmap);
+        }
+    }
+
+    /**
+     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
+     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
+     * not the RenderNode from a View.
+     *
+     * @hide
+     **/
+    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
+        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
+    }
+
+    /**
+     * Invoke this method when the system is running out of memory. This
+     * method will attempt to recover as much memory as possible, based on
+     * the specified hint.
+     *
+     * @param level Hint about the amount of memory that should be trimmed,
+     *              see {@link android.content.ComponentCallbacks}
+     * @hide
+     */
+    public static void trimMemory(int level) {
+        nTrimMemory(level);
+    }
+
+    /** @hide */
+    public static void overrideProperty(@NonNull String name, @NonNull String value) {
+        if (name == null || value == null) {
+            throw new IllegalArgumentException("name and value must be non-null");
+        }
+        nOverrideProperty(name, value);
+    }
+
+    /**
+     * Sets the directory to use as a persistent storage for threaded rendering
+     * resources.
+     *
+     * @param cacheDir A directory the current process can write to
+     * @hide
+     */
+    public static void setupDiskCache(File cacheDir) {
+        setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
+                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
+    }
+
+    /** @hide */
+    public static void setPackageName(String packageName) {
+        ProcessInitializer.sInstance.setPackageName(packageName);
+    }
+
+    private static final class DestroyContextRunnable implements Runnable {
+        private final long mNativeInstance;
+
+        DestroyContextRunnable(long nativeInstance) {
+            mNativeInstance = nativeInstance;
+        }
+
+        @Override
+        public void run() {
+            nDeleteProxy(mNativeInstance);
+        }
+    }
+
+    private static class ProcessInitializer {
+        static ProcessInitializer sInstance = new ProcessInitializer();
+
+        private boolean mInitialized = false;
+
+        private String mPackageName;
+        private IGraphicsStats mGraphicsStatsService;
+        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+            @Override
+            public void onRotateGraphicsStatsBuffer() throws RemoteException {
+                rotateBuffer();
+            }
+        };
+
+        private ProcessInitializer() {
+        }
+
+        synchronized void setPackageName(String name) {
+            if (mInitialized) return;
+            mPackageName = name;
+        }
+
+        synchronized void init(long renderProxy) {
+            if (mInitialized) return;
+            mInitialized = true;
+
+            initSched(renderProxy);
+            initGraphicsStats();
+        }
+
+        private void initSched(long renderProxy) {
+            try {
+                int tid = nGetRenderThreadTid(renderProxy);
+                ActivityManager.getService().setRenderThread(tid);
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
+            }
+        }
+
+        private void initGraphicsStats() {
+            if (mPackageName == null) return;
+
+            try {
+                IBinder binder = ServiceManager.getService("graphicsstats");
+                if (binder == null) return;
+                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+                requestBuffer();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+
+        private void rotateBuffer() {
+            nRotateProcessStatsBuffer();
+            requestBuffer();
+        }
+
+        private void requestBuffer() {
+            try {
+                ParcelFileDescriptor pfd = mGraphicsStatsService
+                        .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
+                nSetProcessStatsBuffer(pfd.getFd());
+                pfd.close();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static native void disableVsync();
+
+    /** @hide */
+    protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
+
+    private static native void nRotateProcessStatsBuffer();
+
+    private static native void nSetProcessStatsBuffer(int fd);
+
+    private static native int nGetRenderThreadTid(long nativeProxy);
+
+    private static native long nCreateRootRenderNode();
+
+    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
+
+    private static native void nDeleteProxy(long nativeProxy);
+
+    private static native boolean nLoadSystemProperties(long nativeProxy);
+
+    private static native void nSetName(long nativeProxy, String name);
+
+    private static native void nSetSurface(long nativeProxy, Surface window);
+
+    private static native boolean nPause(long nativeProxy);
+
+    private static native void nSetStopped(long nativeProxy, boolean stopped);
+
+    private static native void nSetLightGeometry(long nativeProxy,
+            float lightX, float lightY, float lightZ, float lightRadius);
+
+    private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
+            float spotShadowAlpha);
+
+    private static native void nSetOpaque(long nativeProxy, boolean opaque);
+
+    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
+
+    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
+
+    private static native void nDestroy(long nativeProxy, long rootRenderNode);
+
+    private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
+            long animatingNode);
+
+    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
+
+    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
+
+    private static native long nCreateTextureLayer(long nativeProxy);
+
+    private static native void nBuildLayer(long nativeProxy, long node);
+
+    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
+
+    private static native void nPushLayerUpdate(long nativeProxy, long layer);
+
+    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
+
+    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
+
+    private static native void nDestroyHardwareResources(long nativeProxy);
+
+    private static native void nTrimMemory(int level);
+
+    private static native void nOverrideProperty(String name, String value);
+
+    private static native void nFence(long nativeProxy);
+
+    private static native void nStopDrawing(long nativeProxy);
+
+    private static native void nNotifyFramePending(long nativeProxy);
+
+    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+            @DumpFlags int dumpFlags);
+
+    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+            boolean placeFront);
+
+    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+
+    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+
+    private static native void nSetContentDrawBounds(long nativeProxy, int left,
+            int top, int right, int bottom);
+
+    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
+
+    private static native void nSetFrameCompleteCallback(long nativeProxy,
+            FrameCompleteCallback callback);
+
+    private static native long nAddFrameMetricsObserver(long nativeProxy,
+            FrameMetricsObserver observer);
+
+    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+
+    private static native int nCopySurfaceInto(Surface surface,
+            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
+
+    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
+
+    private static native void nSetHighContrastText(boolean enabled);
+
+    // For temporary experimentation b/66945974
+    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
+
+    private static native void nSetDebuggingEnabled(boolean enabled);
+
+    private static native void nSetIsolatedProcess(boolean enabled);
+
+    private static native void nSetContextPriority(int priority);
+
+    private static native void nAllocateBuffers(long nativeProxy);
+
+    private static native void nSetForceDark(long nativeProxy, boolean enabled);
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 0a4ac8c..c10e482 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -30,6 +30,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.security.KeyStoreException;
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
@@ -40,14 +41,21 @@
 import android.security.keystore.KeyExpiredException;
 import android.security.keystore.KeyNotYetValidException;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
 import android.security.keystore.StrongBoxUnavailableException;
 import android.security.keystore.UserNotAuthenticatedException;
 import android.util.Log;
-
+import com.android.org.bouncycastle.asn1.ASN1InputStream;
+import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 import java.math.BigInteger;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.security.InvalidKeyException;
 import java.util.List;
 import java.util.Locale;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
 
 /**
  * @hide This should not be made public in its present form because it
@@ -69,6 +77,7 @@
     public static final int VALUE_CORRUPTED = 8;
     public static final int UNDEFINED_ACTION = 9;
     public static final int WRONG_PASSWORD = 10;
+    public static final int KEY_ALREADY_EXISTS = 16;
     public static final int CANNOT_ATTEST_IDS = -66;
     public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
 
@@ -239,7 +248,12 @@
             if (value == null) {
                 value = new byte[0];
             }
-            return mBinder.insert(key, value, uid, flags);
+            int error = mBinder.insert(key, value, uid, flags);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(key, uid);
+                error = mBinder.insert(key, value, uid, flags);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
@@ -366,53 +380,6 @@
         return isEmpty(UserHandle.myUserId());
     }
 
-    public boolean generate(String key, int uid, int keyType, int keySize, int flags,
-            byte[][] args) {
-        try {
-            return mBinder.generate(key, uid, keyType, keySize, flags,
-                    new KeystoreArguments(args)) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public boolean importKey(String keyName, byte[] key, int uid, int flags) {
-        try {
-            return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public byte[] sign(String key, byte[] data) {
-        try {
-            return mBinder.sign(key, data);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
-            return null;
-        }
-
-    }
-
-    public boolean verify(String key, byte[] data, byte[] signature) {
-        try {
-            signature = signature != null ? signature : new byte[0];
-            return mBinder.verify(key, data, signature) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
-            return false;
-        }
-
-    }
-
     public String grant(String key, int uid) {
         try {
             String grantAlias =  mBinder.grant(key, uid);
@@ -496,7 +463,12 @@
         try {
             entropy = entropy != null ? entropy : new byte[0];
             args = args != null ? args : new KeymasterArguments();
-            return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+            int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(alias, uid);
+                error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
@@ -528,8 +500,14 @@
     public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
             int uid, int flags, KeyCharacteristics outCharacteristics) {
         try {
-            return mBinder.importKey(alias, args, format, keyData, uid, flags,
+            int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
                     outCharacteristics);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(alias, uid);
+                error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+                        outCharacteristics);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
@@ -541,13 +519,78 @@
         return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
     }
 
+    private String getAlgorithmFromPKCS8(byte[] keyData) {
+        try {
+            final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
+            final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+            final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            return new AlgorithmId(new ObjectIdentifier(algOid)).getName();
+        } catch (IOException e) {
+            Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data");
+            Log.e(TAG, Log.getStackTraceString(e));
+            return null;
+        }
+    }
+
+    private KeymasterArguments makeLegacyArguments(String algorithm) {
+        KeymasterArguments args = new KeymasterArguments();
+        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
+                KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm));
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN);
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY);
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
+        args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
+        if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) {
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS);
+        }
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+        args.addUnsignedLong(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                             KeymasterArguments.UINT64_MAX_VALUE);
+        args.addUnsignedLong(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                             KeymasterArguments.UINT64_MAX_VALUE);
+        args.addUnsignedLong(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, BigInteger.ZERO);
+        return args;
+    }
+
+    public boolean importKey(String alias, byte[] keyData, int uid, int flags) {
+        String algorithm = getAlgorithmFromPKCS8(keyData);
+        if (algorithm == null) return false;
+        KeymasterArguments args = makeLegacyArguments(algorithm);
+        KeyCharacteristics out = new KeyCharacteristics();
+        int result =  importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid,
+                                flags, out);
+        if (result != NO_ERROR) {
+            Log.e(TAG, Log.getStackTraceString(
+                    new KeyStoreException(result, "legacy key import failed")));
+            return false;
+        }
+        return true;
+    }
+
     public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
             String wrappingKeyAlias,
             byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
             KeyCharacteristics outCharacteristics) {
         try {
-            return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+            int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
                     maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(wrappedKeyAlias, -1);
+                error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                        maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
@@ -627,21 +670,6 @@
     }
 
     /**
-     * Check if the operation referenced by {@code token} is currently authorized.
-     *
-     * @param token An operation token returned by a call to
-     * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
-     */
-    public boolean isOperationAuthorized(IBinder token) {
-        try {
-            return mBinder.isOperationAuthorized(token);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    /**
      * Add an authentication record to the keystore authorization table.
      *
      * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 236a6b6..b04c774 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -66,6 +66,7 @@
 
 FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
     setDensity(1);
+    consumeProperties();
 }
 
 FrameInfoVisualizer::~FrameInfoVisualizer() {
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 05dc340..c58bcb3 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -139,7 +139,7 @@
 
 uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
     uint32_t flags = paint->getFlags();
-    SkFontHinting hinting = (SkFontHinting)paint->getHinting();
+    unsigned hinting = static_cast<unsigned>(paint->getHinting());
     // select only flags that might affect text layout
     flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
               SkPaint::kSubpixelText_Flag | SkPaint::kEmbeddedBitmapText_Flag |
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 92a749f..f1a522e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -180,14 +180,20 @@
     }
 }
 
-void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
-    mLightGeometry.radius = lightRadius;
+void CanvasContext::allocateBuffers() {
+    if (mNativeSurface) {
+        mNativeSurface->allocateBuffers();
+    }
+}
+
+void CanvasContext::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
     mLightInfo.spotShadowAlpha = spotShadowAlpha;
 }
 
-void CanvasContext::setLightCenter(const Vector3& lightCenter) {
+void CanvasContext::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
     mLightGeometry.center = lightCenter;
+    mLightGeometry.radius = lightRadius;
 }
 
 void CanvasContext::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2307ee4..70be4a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -113,9 +113,10 @@
     bool pauseSurface();
     void setStopped(bool stopped);
     bool hasSurface() { return mNativeSurface.get(); }
+    void allocateBuffers();
 
-    void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
-    void setLightCenter(const Vector3& lightCenter);
+    void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+    void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     void setOpaque(bool opaque);
     void setWideGamut(bool wideGamut);
     bool makeCurrent();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 54219b5..085812a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -80,22 +80,16 @@
     mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
 }
 
-void RenderProxy::initialize(const sp<Surface>& surface) {
+void RenderProxy::setSurface(const sp<Surface>& surface) {
     mRenderThread.queue().post(
             [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
 }
 
-void RenderProxy::allocateBuffers(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [ surf = surface ]() mutable { surf->allocateBuffers(); });
+void RenderProxy::allocateBuffers() {
+    mRenderThread.queue().post([=]() { mContext->allocateBuffers(); });
 }
 
-void RenderProxy::updateSurface(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
-}
-
-bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
+bool RenderProxy::pause() {
     return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
 }
 
@@ -103,13 +97,13 @@
     mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
 }
 
-void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void RenderProxy::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     mRenderThread.queue().post(
-            [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
+            [=]() { mContext->setLightAlpha(ambientShadowAlpha, spotShadowAlpha); });
 }
 
-void RenderProxy::setLightCenter(const Vector3& lightCenter) {
-    mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
+void RenderProxy::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
+    mRenderThread.queue().post([=]() { mContext->setLightGeometry(lightCenter, lightRadius); });
 }
 
 void RenderProxy::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d29fcc4..6668c58 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,13 +69,12 @@
     ANDROID_API bool loadSystemProperties();
     ANDROID_API void setName(const char* name);
 
-    ANDROID_API void initialize(const sp<Surface>& surface);
-    ANDROID_API void allocateBuffers(const sp<Surface>& surface);
-    ANDROID_API void updateSurface(const sp<Surface>& surface);
-    ANDROID_API bool pauseSurface(const sp<Surface>& surface);
+    ANDROID_API void setSurface(const sp<Surface>& surface);
+    ANDROID_API void allocateBuffers();
+    ANDROID_API bool pause();
     ANDROID_API void setStopped(bool stopped);
-    ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
-    ANDROID_API void setLightCenter(const Vector3& lightCenter);
+    ANDROID_API void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+    ANDROID_API void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API void setWideGamut(bool wideGamut);
     ANDROID_API int64_t* frameInfo();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 62f704b..2384f95 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -74,7 +74,7 @@
     PREVENT_COPY_AND_ASSIGN(RenderThread);
 
 public:
-    // Sets a callback that fires before any RenderThread setup has occured.
+    // Sets a callback that fires before any RenderThread setup has occurred.
     ANDROID_API static void setOnStartHook(void (*onStartHook)());
 
     WorkQueue& queue() { return ThreadBase::queue(); }
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5f5a92e..5fa008b 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -132,10 +132,10 @@
     ContextFactory factory;
     std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
     proxy->loadSystemProperties();
-    proxy->initialize(surface);
+    proxy->setSurface(surface);
     float lightX = width / 2.0;
-    proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15);
-    proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
+    proxy->setLightAlpha(255 * 0.075, 255 * 0.15);
+    proxy->setLightGeometry((Vector3){lightX, dp(-200.0f), dp(800.0f)}, dp(800.0f));
 
     // Do a few cold runs then reset the stats so that the caches are all hot
     int warmupFrameCount = 5;
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 1276881..b5d835a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -120,4 +120,18 @@
 
     // used by gts tests to verify throttling whitelist
     String[] getBackgroundThrottlingWhitelist();
+
+    /**
+     * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
+     * provider} to start the UI to modify the location permission for a package.
+     *
+     * <p>Can only be called by the location provider.
+     *
+     * @param packageName The package the permission belongs to
+     * @param permission The (individual) permission to switch
+     *
+     * @return A pending intent that starts the permission management UI or {@code null} if the
+     *         intent cannot be created
+     */
+    PendingIntent createManageLocationPermissionIntent(in String packageName, in String permission);
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b1968ba..02680ab 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,6 +22,7 @@
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -43,7 +44,9 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
+
 import com.android.internal.location.ProviderProperties;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -2393,4 +2396,29 @@
             return null;
         }
     }
+
+    /**
+     * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
+     * provider} to start the UI to modify the location permission for a package.
+     *
+     * <p>Can only be called by the location provider.
+     *
+     * @param packageName The package the permission belongs to
+     * @param permission The (individual) location permission to switch
+     *
+     * @return A one-shot pending intent that starts the permission management UI or {@code null} if
+     *         the intent cannot be created
+     *
+     * @hide
+     */
+    @SystemApi
+    public @Nullable PendingIntent createManageLocationPermissionIntent(@NonNull String packageName,
+            @NonNull String permission) {
+        try {
+            return mService.createManageLocationPermissionIntent(packageName, permission);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index e1f9111..69c267e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -65,6 +65,15 @@
         }
     }
 
+    /**
+     * Logs a generic Settings event.
+     */
+    public void action(int attribution, int action, int pageId, String key, int value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(attribution, action, pageId, key, value);
+        }
+    }
+
     public void action(Context context, int category, int value) {
         for (LogWriter writer : mLoggerWriters) {
             writer.action(context, category, value);
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
index a28e45c..71f3789 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -116,8 +116,6 @@
             mPreferenceKeySet.add(prefKey);
             return;
         }
-        // TODO: Remove count logging to save some resource.
-        mMetricsFeature.count(mContext, buildCountName(prefKey, value), 1);
 
         final Pair<Integer, Object> valueData;
         if (value instanceof Long) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index ca0267c..f1295e03 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -481,6 +481,9 @@
         dumpSetting(s, p,
                 Settings.Global.EMULATE_DISPLAY_CUTOUT,
                 GlobalSettingsProto.Development.EMULATE_DISPLAY_CUTOUT);
+        dumpSetting(s, p,
+                Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
+                GlobalSettingsProto.Development.FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS);
         p.end(developmentToken);
 
         final long deviceToken = p.start(GlobalSettingsProto.DEVICE);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index b4fc820..887ea59 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -13,11 +13,11 @@
  */
 package com.android.systemui.plugins;
 
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
 import android.graphics.Paint.Style;
 import android.view.View;
 
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
 /**
  * This plugin is used to replace main clock in keyguard.
  */
@@ -44,4 +44,9 @@
      * @param color A color value.
      */
     void setTextColor(int color);
+
+    /**
+     * Notifies that time tick alarm from doze service fired.
+     */
+    default void dozeTimeTick() { }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 013745a..8881f8a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -143,6 +143,15 @@
     }
 
     /**
+     * Notifies that time tick alarm from doze service fired.
+     */
+    public void dozeTimeTick() {
+        if (mClockPlugin != null) {
+            mClockPlugin.dozeTimeTick();
+        }
+    }
+
+    /**
      * When plugin changes, set all kept parameters into newer plugin.
      */
     private void initPluginParams() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index a403b75..f701e22 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -47,7 +47,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
 
 import com.google.android.collect.Sets;
 
@@ -276,6 +275,7 @@
     public void dozeTimeTick() {
         refreshTime();
         mKeyguardSlice.refresh();
+        mClockView.dozeTimeTick();
     }
 
     private void refreshTime() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index c3bf16e..a315bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1124,7 +1124,7 @@
      */
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getExpandTranslationStart() {
-        return -mTopPadding + getMinExpansionHeight();
+        return -mTopPadding + getMinExpansionHeight() - mShelf.getIntrinsicHeight();
     }
 
     /**
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 90ad09e..046442a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -83,6 +84,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
 import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
@@ -111,6 +113,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -3420,6 +3423,48 @@
         }
     }
 
+    @Override
+    public PendingIntent createManageLocationPermissionIntent(String packageName,
+            String permission) {
+        Preconditions.checkNotNull(packageName);
+        Preconditions.checkArgument(permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)
+                || permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)
+                || permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION));
+
+        int callingUid = Binder.getCallingUid();
+        long token = Binder.clearCallingIdentity();
+        try {
+            String locProvider = getNetworkProviderPackage();
+            if (locProvider == null) {
+                return null;
+            }
+
+            PackageInfo locProviderInfo;
+            try {
+                locProviderInfo = mContext.getPackageManager().getPackageInfo(
+                        locProvider, PackageManager.MATCH_DIRECT_BOOT_AUTO);
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Could not resolve " + locProvider, e);
+                return null;
+            }
+
+            if (locProviderInfo.applicationInfo.uid != callingUid) {
+                throw new SecurityException("Only " + locProvider + " can call this API");
+            }
+
+            Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+            intent.putExtra(Intent.EXTRA_PERMISSION_NAME, permission);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            return PendingIntent.getActivity(mContext,
+                    Objects.hash(packageName, permission), intent,
+                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private void log(String log) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Slog.d(TAG, log);
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 968c17f..8ac19d5 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -61,6 +61,7 @@
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
+        sGlobalSettingToTypeMap.put(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, int.class);
         // add other global settings here...
     }
 
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 0ee55ed..527539d 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -21,6 +21,7 @@
 import android.content.IntentFilter;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceProxy;
+import android.media.AudioManager;
 import android.metrics.LogMaker;
 import android.nfc.INfcAdapter;
 import android.os.Binder;
@@ -393,6 +394,19 @@
             boolean wasEmpty = mActiveCameraUsage.isEmpty();
             switch (newCameraState) {
                 case ICameraServiceProxy.CAMERA_STATE_OPEN:
+                    // Notify the audio subsystem about the facing of the most-recently opened
+                    // camera This can be used to select the best audio tuning in case video
+                    // recording with that camera will happen.  Since only open events are used, if
+                    // multiple cameras are opened at once, the one opened last will be used to
+                    // select audio tuning.
+                    AudioManager audioManager = getContext().getSystemService(AudioManager.class);
+                    if (audioManager != null) {
+                        // Map external to front for audio tuning purposes
+                        String facingStr = (facing == ICameraServiceProxy.CAMERA_FACING_BACK) ?
+                                "back" : "front";
+                        String facingParameter = "cameraFacing=" + facingStr;
+                        audioManager.setParameters(facingParameter);
+                    }
                     break;
                 case ICameraServiceProxy.CAMERA_STATE_ACTIVE:
                     CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4c93441..13bb817 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2777,13 +2777,13 @@
                 // dataPath   - path to package's data path
                 // seinfo     - seinfo label for the app (assigned at install time)
                 // gids       - supplementary gids this app launches with
+                // profileableFromShellFlag  - 0 or 1 if the package is profileable from shell.
                 //
                 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
                 //
                 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
                 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
-                //   frameworks/base/libs/packagelistparser
-                //   system/core/run-as/run-as.c
+                //   system/core/libpackagelistparser
                 //
                 sb.setLength(0);
                 sb.append(ai.packageName);
@@ -2803,6 +2803,8 @@
                 } else {
                     sb.append("none");
                 }
+                sb.append(" ");
+                sb.append(ai.isProfileableByShell() ? "1" : "0");
                 sb.append("\n");
                 writer.append(sb);
             }
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 478a11a..751ae0d 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1103,13 +1103,12 @@
     }
 
     /**
+     * Checks if system decorations should be shown on this display.
+     *
      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      */
     boolean supportsSystemDecorations() {
-        return mDisplay.supportsSystemDecorations()
-                // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
-                // (b/114338689) whenever vr 2d display id is set.
-                || mDisplayId == mSupervisor.mService.mVr2dDisplayId;
+        return mWindowContainerController.supportsSystemDecorations();
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 9b01dfd..61e1414 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -72,12 +72,12 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
 
 import android.app.WindowConfiguration.WindowingMode;
@@ -495,7 +495,9 @@
             foundInfo = info;
         }
         if (allWindowsDrawn()) {
-            reset(false /* abort */, foundInfo, "notifyTransitionStarting - all windows drawn");
+            // abort metrics collection if we cannot find a matching transition.
+            final boolean abortMetrics = foundInfo == null;
+            reset(abortMetrics, foundInfo, "notifyTransitionStarting - all windows drawn");
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 433c05a..f55bcce 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -56,7 +56,6 @@
 import static android.os.Process.FIRST_APPLICATION_UID;
 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;
@@ -658,8 +657,6 @@
                 ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
         final boolean supportsMultiDisplay = mContext.getPackageManager()
                 .hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
-        final boolean alwaysFinishActivities =
-                Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
         final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
         final boolean forceResizable = Settings.Global.getInt(
                 resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fece980..e20793e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4666,4 +4666,16 @@
 
         pendingLayoutChanges |= changes;
     }
+
+    /**
+     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+     */
+    boolean supportsSystemDecorations() {
+        // TODO(b/114338689): Read the setting from DisplaySettings.
+        return mDisplay.supportsSystemDecorations()
+                // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
+                // (b/114338689) whenever vr 2d display id is set.
+                || mDisplayId == mService.mVr2dDisplayId
+                || mService.mForceDesktopModeOnExternalDisplays;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 44956ab..624fbc7 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -185,15 +185,12 @@
         }
         // No record is present so use default windowing mode policy.
         if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                windowingMode = (mService.mIsPc && mService.mSupportsFreeformWindowManagement)
-                        ? WindowConfiguration.WINDOWING_MODE_FREEFORM
-                        : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-            } else {
-                windowingMode = mService.mSupportsFreeformWindowManagement
-                        ? WindowConfiguration.WINDOWING_MODE_FREEFORM
-                        : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-            }
+            final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
+                    && displayId != Display.DEFAULT_DISPLAY;
+            windowingMode = mService.mSupportsFreeformWindowManagement
+                    && (mService.mIsPc || forceDesktopMode)
+                    ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+                    : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
         }
         return windowingMode;
     }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index 632494b..864f7e1 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -339,6 +339,17 @@
                 || transit == TRANSIT_TASK_TO_FRONT;
     }
 
+    /**
+     * Checks if system decorations should be shown on this display.
+     *
+     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+     */
+    public boolean supportsSystemDecorations() {
+        synchronized (mGlobalLock) {
+            return mContainer.supportsSystemDecorations();
+        }
+    }
+
     @Override
     public String toString() {
         return "{DisplayWindowController displayId=" + mDisplayId + "}";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ec68f76..e4444e2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -29,6 +29,7 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.myPid;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -538,12 +539,21 @@
     int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
     Rect mDockedStackCreateBounds;
 
-    boolean mForceResizableTasks = false;
-    boolean mSupportsPictureInPicture = false;
-    boolean mSupportsFreeformWindowManagement = false;
-    boolean mIsPc = false;
+    boolean mForceResizableTasks;
+    boolean mSupportsPictureInPicture;
+    boolean mSupportsFreeformWindowManagement;
+    boolean mIsPc;
+    /**
+     * Flag that indicates that desktop mode is forced for public secondary screens.
+     *
+     * This includes several settings:
+     * - Set freeform windowing mode on external screen if it's supported and enabled.
+     * - Enable system decorations and IME on external screen.
+     * - TODO: Show mouse pointer on external screen.
+     */
+    boolean mForceDesktopModeOnExternalDisplays;
 
-    boolean mDisableTransitionAnimation = false;
+    boolean mDisableTransitionAnimation;
 
     int getDragLayerLocked() {
         return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
@@ -980,17 +990,21 @@
             }
         }, UserHandle.ALL, suspendPackagesFilter, null, null);
 
+        final ContentResolver resolver = context.getContentResolver();
         // Get persisted window scale setting
-        mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
+        mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
-        mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
+        mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
                 Settings.Global.TRANSITION_ANIMATION_SCALE,
                 context.getResources().getFloat(
                         R.dimen.config_appTransitionAnimationDurationScaleDefault));
 
-        setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
+        setAnimatorDurationScale(Settings.Global.getFloat(resolver,
                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
 
+        mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
+                DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
+
         IntentFilter filter = new IntentFilter();
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -6398,6 +6412,12 @@
         }
     }
 
+    void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
+        synchronized (mWindowMap) {
+            mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
+        }
+    }
+
     public void setIsPc(boolean isPc) {
         synchronized (mGlobalLock) {
             mIsPc = isPc;
@@ -6576,10 +6596,10 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                final DisplayContent dc = getDisplayContentOrCreate(displayId, null);
+                final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
                 if (dc == null) {
                     throw new IllegalArgumentException(
-                            "Trying to register a non existent display.");
+                            "Trying to configure a non existent display.");
                 }
                 // We usually set the override info in DisplayManager so that we get consistent
                 // values when displays are changing. However, we don't do this for displays that
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
index f0c49c8..5808bc9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
@@ -64,6 +64,7 @@
 
         mWm.setSupportsFreeformWindowManagement(false);
         mWm.setIsPc(false);
+        mWm.setForceDesktopModeOnExternalDisplays(false);
 
         mTarget = new DisplaySettings(mWm, TEST_FOLDER);
 
@@ -78,7 +79,7 @@
     }
 
     @Test
-    public void testPrimaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+    public void testPrimaryDisplayDefaultToFullscreen_NoFreeformSupport() {
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
 
         assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
@@ -86,7 +87,7 @@
     }
 
     @Test
-    public void testPrimaryDisplayDefaultToFullscreenWithFreeformSupportNonPc() {
+    public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_NoDesktopMode() {
         mWm.setSupportsFreeformWindowManagement(true);
 
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -96,7 +97,18 @@
     }
 
     @Test
-    public void testPrimaryDisplayDefaultToFreeformWithFreeformIsPc() {
+    public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_HasDesktopMode() {
+        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.setForceDesktopModeOnExternalDisplays(true);
+
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mPrimaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testPrimaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
         mWm.setSupportsFreeformWindowManagement(true);
         mWm.setIsPc(true);
 
@@ -107,7 +119,7 @@
     }
 
     @Test
-    public void testSecondaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+    public void testSecondaryDisplayDefaultToFullscreen_NoFreeformSupport() {
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
 
         assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
@@ -115,17 +127,28 @@
     }
 
     @Test
-    public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportNonPc() {
+    public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_NoDesktopMode() {
         mWm.setSupportsFreeformWindowManagement(true);
 
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
 
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mSecondaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_HasDesktopMode() {
+        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.setForceDesktopModeOnExternalDisplays(true);
+
+        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
         assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
                 mSecondaryDisplay.getWindowingMode());
     }
 
     @Test
-    public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportIsPc() {
+    public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
         mWm.setSupportsFreeformWindowManagement(true);
         mWm.setIsPc(true);
 
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 27b8cdf..60cb08f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -153,6 +153,7 @@
     private static final int MSG_SET_FUNCTIONS_TIMEOUT = 15;
     private static final int MSG_GET_CURRENT_USB_FUNCTIONS = 16;
     private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17;
+    private static final int MSG_GADGET_HAL_REGISTERED = 18;
 
     private static final int AUDIO_MODE_SOURCE = 1;
 
@@ -1708,10 +1709,16 @@
         protected static final String CTL_STOP = "ctl.stop";
 
         /**
-         * Adb natvie daemon
+         * Adb native daemon.
          */
         protected static final String ADBD = "adbd";
 
+        /**
+         * Gadget HAL fully qualified instance name for registering for ServiceNotification.
+         */
+        protected static final String GADGET_HAL_FQ_NAME =
+                "android.hardware.usb.gadget@1.0::IUsbGadget";
+
         protected boolean mCurrentUsbFunctionsRequested;
 
         UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager,
@@ -1721,8 +1728,7 @@
                 ServiceNotification serviceNotification = new ServiceNotification();
 
                 boolean ret = IServiceManager.getService()
-                        .registerForNotifications("android.hardware.usb.gadget@1.0::IUsbGadget",
-                                "", serviceNotification);
+                        .registerForNotifications(GADGET_HAL_FQ_NAME, "", serviceNotification);
                 if (!ret) {
                     Slog.e(TAG, "Failed to register usb gadget service start notification");
                     return;
@@ -1764,20 +1770,12 @@
             @Override
             public void onRegistration(String fqName, String name, boolean preexisting) {
                 Slog.i(TAG, "Usb gadget hal service started " + fqName + " " + name);
-                synchronized (mGadgetProxyLock) {
-                    try {
-                        mGadgetProxy = IUsbGadget.getService();
-                        mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
-                                USB_GADGET_HAL_DEATH_COOKIE);
-                        if (!mCurrentFunctionsApplied && !mCurrentUsbFunctionsRequested) {
-                            setEnabledFunctions(mCurrentFunctions, false);
-                        }
-                    } catch (NoSuchElementException e) {
-                        Slog.e(TAG, "Usb gadget hal not found", e);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Usb Gadget hal not responding", e);
-                    }
+                if (!fqName.equals(GADGET_HAL_FQ_NAME)) {
+                    Slog.e(TAG, "fqName does not match");
+                    return;
                 }
+
+                sendMessage(MSG_GADGET_HAL_REGISTERED, preexisting);
             }
         }
 
@@ -1815,6 +1813,23 @@
                         setEnabledFunctions(UsbManager.FUNCTION_NONE, !isAdbEnabled());
                     }
                     break;
+                case MSG_GADGET_HAL_REGISTERED:
+                    boolean preexisting = msg.arg1 == 1;
+                    synchronized (mGadgetProxyLock) {
+                        try {
+                            mGadgetProxy = IUsbGadget.getService();
+                            mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
+                                    USB_GADGET_HAL_DEATH_COOKIE);
+                            if (!mCurrentFunctionsApplied && !preexisting) {
+                                setEnabledFunctions(mCurrentFunctions, false);
+                            }
+                        } catch (NoSuchElementException e) {
+                            Slog.e(TAG, "Usb gadget hal not found", e);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Usb Gadget hal not responding", e);
+                        }
+                    }
+                    break;
                 default:
                     super.handleMessage(msg);
             }
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index c39688c..0c40a6b 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -62,3 +62,22 @@
     ],
     test_suites: ["general-tests"],
 }
+
+cc_binary_host {
+    name: "dex_testcase_generator",
+    defaults: ["viewcompiler_defaults"],
+    srcs: ["dex_testcase_generator.cc"],
+    static_libs: [
+        "libviewcompiler",
+    ],
+}
+
+genrule {
+    name: "generate_dex_testcases",
+    tools: [":dex_testcase_generator"],
+    cmd: "$(location :dex_testcase_generator) $(genDir)",
+    out: [
+        "simple.dex",
+        "trivial.dex",
+    ],
+}
diff --git a/startop/view_compiler/README.md b/startop/view_compiler/README.md
index 5659501..f8da02b 100644
--- a/startop/view_compiler/README.md
+++ b/startop/view_compiler/README.md
@@ -23,3 +23,31 @@
   application.
 * This only works for apps that do not use a custom layout inflater.
 * Other limitations yet to be discovered.
+
+## DexBuilder Tests
+
+The DexBuilder has several low-level end to end tests to verify generated DEX
+code validates, runs, and has the correct behavior. There are, unfortunately, a
+number of pieces that must be added to generate new tests. Here are the
+components:
+
+* `dex_testcase_generator` - Written in C++ using `DexBuilder`. This runs as a
+  build step produce the DEX files that will be tested on device. See the
+  `genrule` named `generate_dex_testcases` in `Android.bp`. These files are then
+  copied over to the device by TradeFed when running tests.
+* `DexBuilderTest` - This is a Java Language test harness that loads the
+  generated DEX files and exercises methods in the file.
+
+To add a new DEX file test, follow these steps:
+1. Modify `dex_testcase_generator` to produce the DEX file.
+2. Add the filename to the `out` list of the `generate_dex_testcases` rule in
+   `Android.bp`.
+3. Add a new `push` option to `AndroidTest.xml` to copy the DEX file to the
+   device.
+4. Modify `DexBuilderTest.java` to load and exercise the new test.
+
+In each case, you should be able to cargo-cult the existing test cases.
+
+In general, you can probably get by without adding a new generated DEX file, and
+instead add more methods to the files that are already generated. In this case,
+you can skip all of steps 2 and 3 above, and simplify steps 1 and 4.
diff --git a/startop/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
new file mode 100644
index 0000000..5d675b7
--- /dev/null
+++ b/startop/view_compiler/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "dex-builder-test"
+    }
+  ]
+}
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
new file mode 100644
index 0000000..4449ea0
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+android_test {
+    name: "dex-builder-test",
+    srcs: ["src/android/startop/test/DexBuilderTest.java"],
+    sdk_version: "current",
+    data: [":generate_dex_testcases"],
+    static_libs: [
+        "android-support-test",
+        "guava",
+    ],
+    manifest: "AndroidManifest.xml",
+    test_config: "AndroidTest.xml",
+    test_suites: ["general-tests"],
+}
diff --git a/startop/view_compiler/dex_builder_test/AndroidManifest.xml b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
new file mode 100644
index 0000000..6ac5fc5
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.startop.test" >
+
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.startop.test"
+                     android:label="DexBuilder Tests"/>
+
+</manifest>
diff --git a/startop/view_compiler/dex_builder_test/AndroidTest.xml b/startop/view_compiler/dex_builder_test/AndroidTest.xml
new file mode 100644
index 0000000..6f90cf3
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs DexBuilder Tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="dex-builder-test.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="trivial.dex->/data/local/tmp/dex-builder-test/trivial.dex" />
+        <option name="push" value="simple.dex->/data/local/tmp/dex-builder-test/simple.dex" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.startop.test" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
new file mode 100644
index 0000000..87b2578
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.startop.test;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import com.google.common.io.ByteStreams;
+import dalvik.system.InMemoryDexClassLoader;
+import dalvik.system.PathClassLoader;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+public class DexBuilderTest {
+  static ClassLoader loadDexFile(String filename) throws Exception {
+    return new PathClassLoader("/data/local/tmp/dex-builder-test/" + filename,
+        ClassLoader.getSystemClassLoader());
+  }
+
+  public void hello() {}
+
+  @Test
+  public void loadTrivialDex() throws Exception {
+    ClassLoader loader = loadDexFile("trivial.dex");
+    loader.loadClass("android.startop.test.testcases.Trivial");
+  }
+
+  @Test
+  public void return5() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("return5");
+    Assert.assertEquals(5, method.invoke(null));
+  }
+
+  @Test
+  public void returnParam() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnParam", int.class);
+    Assert.assertEquals(5, method.invoke(null, 5));
+    Assert.assertEquals(42, method.invoke(null, 42));
+  }
+
+  @Test
+  public void returnStringLength() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringLength", String.class);
+    Assert.assertEquals(13, method.invoke(null, "Hello, World!"));
+  }
+}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
new file mode 100644
index 0000000..898817b
--- /dev/null
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "android-base/logging.h"
+#include "dex_builder.h"
+
+#include <fstream>
+#include <string>
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+
+using namespace startop::dex;
+using namespace std;
+
+void GenerateTrivialDexFile(const string& outdir) {
+  DexBuilder dex_file;
+
+  ClassBuilder cbuilder{dex_file.MakeClass("android.startop.test.testcases.Trivial")};
+  cbuilder.set_source_file("dex_testcase_generator.cc#GenerateTrivialDexFile");
+
+  slicer::MemView image{dex_file.CreateImage()};
+  std::ofstream out_file(outdir + "/trivial.dex");
+  out_file.write(image.ptr<const char>(), image.size());
+}
+
+// Generates test cases that test around 1 instruction.
+void GenerateSimpleTestCases(const string& outdir) {
+  DexBuilder dex_file;
+
+  ClassBuilder cbuilder{dex_file.MakeClass("android.startop.test.testcases.SimpleTests")};
+  cbuilder.set_source_file("dex_testcase_generator.cc#GenerateSimpleTestCases");
+
+  // int return5() { return 5; }
+  auto return5{cbuilder.CreateMethod("return5", Prototype{TypeDescriptor::Int()})};
+  Value r{return5.MakeRegister()};
+  return5.BuildConst4(r, 5);
+  return5.BuildReturn(r);
+  return5.Encode();
+
+  // // int returnParam(int x) { return x; }
+  auto returnParam{cbuilder.CreateMethod("returnParam",
+                                         Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+  returnParam.BuildReturn(Value::Parameter(0));
+  returnParam.Encode();
+
+  // int returnStringLength(String x) { return x.length(); }
+  auto string_type{TypeDescriptor::FromClassname("java.lang.String")};
+  MethodDeclData string_length{
+      dex_file.GetOrDeclareMethod(string_type, "length", Prototype{TypeDescriptor::Int()})};
+
+  auto returnStringLength{
+      cbuilder.CreateMethod("returnStringLength", Prototype{TypeDescriptor::Int(), string_type})};
+  Value result = returnStringLength.MakeRegister();
+  returnStringLength.AddInstruction(
+      Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+  returnStringLength.BuildReturn(result);
+  returnStringLength.Encode();
+
+  slicer::MemView image{dex_file.CreateImage()};
+  std::ofstream out_file(outdir + "/simple.dex");
+  out_file.write(image.ptr<const char>(), image.size());
+}
+
+int main(int argc, char** argv) {
+  CHECK_EQ(argc, 2);
+
+  string outdir = argv[1];
+
+  GenerateTrivialDexFile(outdir);
+  GenerateSimpleTestCases(outdir);
+}
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 2bda648..1342038 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -180,7 +180,7 @@
             }
         }
 
-        private final List<Event> mEvents = new LinkedList<>();
+        private final List<Event> mEvents = Collections.synchronizedList(new LinkedList<>());
         private final Loggable mRecordEntry;
 
         public EventRecord(Loggable recordEntry) {
@@ -197,7 +197,7 @@
         }
 
         public List<Event> getEvents() {
-            return mEvents;
+            return new LinkedList<>(mEvents);
         }
 
         public List<EventTiming> extractEventTimings() {
@@ -207,21 +207,24 @@
 
             LinkedList<EventTiming> result = new LinkedList<>();
             Map<String, PendingResponse> pendingResponses = new HashMap<>();
-            for (Event event : mEvents) {
-                if (requestResponsePairs.containsKey(event.eventId)) {
-                    // This event expects a response, so add that expected response to the maps
-                    // of pending events.
-                    for (EventManager.TimedEventPair p : requestResponsePairs.get(event.eventId)) {
-                        pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
-                                event.time, p.mTimeoutMillis, p.mName));
+            synchronized (mEvents) {
+                for (Event event : mEvents) {
+                    if (requestResponsePairs.containsKey(event.eventId)) {
+                        // This event expects a response, so add that expected response to the maps
+                        // of pending events.
+                        for (EventManager.TimedEventPair p : requestResponsePairs.get(
+                                event.eventId)) {
+                            pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
+                                    event.time, p.mTimeoutMillis, p.mName));
+                        }
                     }
-                }
 
-                PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
-                if (pendingResponse != null) {
-                    long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
-                    if (elapsedTime < pendingResponse.timeoutMillis) {
-                        result.add(new EventTiming(pendingResponse.name, elapsedTime));
+                    PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
+                    if (pendingResponse != null) {
+                        long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
+                        if (elapsedTime < pendingResponse.timeoutMillis) {
+                            result.add(new EventTiming(pendingResponse.name, elapsedTime));
+                        }
                     }
                 }
             }
@@ -233,7 +236,8 @@
             pw.print(mRecordEntry.getDescription());
 
             pw.increaseIndent();
-            for (Event event : mEvents) {
+            // Iterate over copy of events so that this doesn't hold the lock for too long.
+            for (Event event : getEvents()) {
                 pw.print(event.timestampString);
                 pw.print(" - ");
                 pw.print(event.eventId);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3f9a533..fbc54ae6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1079,24 +1079,44 @@
             "wfc_operator_error_codes_string_array";
 
     /**
-     * Indexes of SPN format strings in wfcSpnFormats and wfcDataSpnFormats.
+     * Indexes of SPN format strings in wfcSpnFormats.
      *
      * <p>Available options are:
      * <ul>
-     * <li> 0: %s</li>
-     * <li> 1: %s Wi-Fi Calling</li>
-     * <li> 2: WLAN Call</li>
-     * <li> 3: %s WLAN Call</li>
-     * <li> 4: %s Wi-Fi</li>
-     * <li> 5: WiFi Calling | %s</li>
-     * <li> 6: %s VoWifi</li>
+     * <li>  0: %s</li>
+     * <li>  1: %s Wi-Fi Calling</li>
+     * <li>  2: WLAN Call</li>
+     * <li>  3: %s WLAN Call</li>
+     * <li>  4: %s Wi-Fi</li>
+     * <li>  5: WiFi Calling | %s</li>
+     * <li>  6: %s VoWifi</li>
+     * <li>  7: Wi-Fi Calling</li>
+     * <li>  8: Wi-Fi</li>
+     * <li>  9: WiFi Calling</li>
+     * <li> 10: VoWifi</li>
      * @hide
      */
     public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
-    /** @hide */
+
+    /**
+     * Indexes of data SPN format strings in wfcSpnFormats.
+     *
+     * @see KEY_WFC_SPN_FORMAT_IDX_INT for available options.
+     * @hide
+     */
     public static final String KEY_WFC_DATA_SPN_FORMAT_IDX_INT = "wfc_data_spn_format_idx_int";
 
     /**
+     * Indexes of SPN format strings in wfcSpnFormats used during flight mode.
+     *
+     * Set to -1 to use the value from KEY_WFC_SPN_FORMAT_IDX_INT also in this case.
+     * @see KEY_WFC_SPN_FORMAT_IDX_INT for other available options.
+     * @hide
+     */
+    public static final String KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT =
+            "wfc_flight_mode_spn_format_idx_int";
+
+    /**
      * Use root locale when reading wfcSpnFormats.
      *
      * If true, then the root locale will always be used when reading wfcSpnFormats. This means the
@@ -2456,6 +2476,7 @@
         sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null);
         sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0);
         sDefaults.putInt(KEY_WFC_DATA_SPN_FORMAT_IDX_INT, 0);
+        sDefaults.putInt(KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT, -1);
         sDefaults.putBoolean(KEY_WFC_SPN_USE_ROOT_LOCALE, false);
         sDefaults.putString(KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING, "");
         sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);