Merge "Fix null drawable for Mobile signal data edit QS tile" into oc-dev
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 7cec957..a140f28 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -970,6 +970,9 @@
         observer.mNative = null;
     }
 
+    /** Not actually public - internal use only. This doc to make lint happy */
+    public static native void disableVsync();
+
     static native void setupShadersDiskCache(String cacheFile);
 
     private static native void nRotateProcessStatsBuffer();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7117137..aa6ffce 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2342,24 +2342,26 @@
     }
 
 
-    public synchronized RemoteViews clone() {
-        Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
-                + "May only clone the root of a RemoteView hierarchy.");
+    public RemoteViews clone() {
+        synchronized (this) {
+            Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
+                    + "May only clone the root of a RemoteView hierarchy.");
 
-        Parcel p = Parcel.obtain();
+            Parcel p = Parcel.obtain();
 
-        // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
-        // Instead pretend we're not owning the cache while parceling.
-        mIsRoot = false;
-        writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
-        p.setDataPosition(0);
-        mIsRoot = true;
+            // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
+            // Instead pretend we're not owning the cache while parceling.
+            mIsRoot = false;
+            writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
+            p.setDataPosition(0);
+            mIsRoot = true;
 
-        RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication, 0);
-        rv.mIsRoot = true;
+            RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication, 0);
+            rv.mIsRoot = true;
 
-        p.recycle();
-        return rv;
+            p.recycle();
+            return rv;
+        }
     }
 
     public String getPackage() {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 438b123..c9251bc 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -932,6 +932,10 @@
     return createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Mutable);
 }
 
+static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
+    RenderProxy::disableVsync();
+}
+
 // ----------------------------------------------------------------------------
 // FrameMetricsObserver
 // ----------------------------------------------------------------------------
@@ -1030,6 +1034,7 @@
                 (void*)android_view_ThreadedRenderer_copySurfaceInto },
     { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
             (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode },
+    { "disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync },
 };
 
 int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index aad81df..b587248 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -69,6 +69,7 @@
 bool Properties::forceDrawFrame = false;
 
 bool Properties::filterOutTestOverhead = false;
+bool Properties::disableVsync = false;
 
 static int property_get_int(const char* key, int defaultValue) {
     char buf[PROPERTY_VALUE_MAX] = {'\0',};
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 9db6449..91b4a2d 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -318,6 +318,12 @@
     // any overhead they add
     static bool filterOutTestOverhead;
 
+    // Workaround a device lockup in edge cases by switching to async mode
+    // instead of the default vsync (b/38372997). Only system_server should hit this.
+    // Any existing RenderProxy & Surface combination will be unaffected, only things
+    // created after changing this.
+    static bool disableVsync;
+
     // Used for testing only to change the render pipeline.
 #ifdef HWUI_GLES_WRAP_ENABLED
     static void overrideRenderPipelineType(RenderPipelineType);
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 44af5fd..ed30708 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -279,6 +279,9 @@
         }
     }
     mCurrentSurface = surface;
+    if (Properties::disableVsync) {
+        eglSwapInterval(mEglDisplay, 0);
+    }
     return true;
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index eed5238..d842be9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -18,6 +18,7 @@
 
 #include "DeferredLayerUpdater.h"
 #include "DisplayList.h"
+#include "Properties.h"
 #include "Readback.h"
 #include "Rect.h"
 #include "renderthread/CanvasContext.h"
@@ -708,6 +709,10 @@
     thread.queue(task);
 }
 
+void RenderProxy::disableVsync() {
+    Properties::disableVsync = true;
+}
+
 void RenderProxy::post(RenderTask* task) {
     mRenderThread.queue(task);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index b21772c..6f4e8ce 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -137,6 +137,8 @@
     static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
 
     static void onBitmapDestroyed(uint32_t pixelRefId);
+
+    ANDROID_API static void disableVsync();
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index f23caf2..0fdf2da 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -30,6 +30,7 @@
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.TextureView;
+import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.TextureView.SurfaceTextureListener;
@@ -95,6 +96,8 @@
     public OverlayDisplayWindow(Context context, String name,
             int width, int height, int densityDpi, int gravity, boolean secure,
             Listener listener) {
+        // Workaround device freeze (b/38372997)
+        ThreadedRenderer.disableVsync();
         mContext = context;
         mName = name;
         mGravity = gravity;