Apply dev. settings at runtime
Bug #7434649

Change-Id: I16f00eaa8a5eefd9f9849e196cf2cb1659215390
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 8cd24be..0f175dbb 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -313,6 +313,20 @@
     abstract long getFrameCount();
 
     /**
+     * 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.
+     *
+     * @param surface The surface to update with the new properties.
+     *                Can be null.
+     *
+     * @return True if a property has changed.
+     */
+    abstract boolean loadSystemProperties(Surface surface);
+
+    private static native boolean nLoadProperties();
+
+    /**
      * Sets the directory to use as a persistent storage for hardware rendering
      * resources.
      * 
@@ -633,13 +647,13 @@
         boolean mDirtyRegionsEnabled;
         boolean mUpdateDirtyRegions;
 
-        final boolean mProfileEnabled;
-        final float[] mProfileData;
-        final ReentrantLock mProfileLock;
+        boolean mProfileEnabled;
+        float[] mProfileData;
+        ReentrantLock mProfileLock;
         int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
         
-        final boolean mDebugDirtyRegions;
-        final boolean mShowOverdraw;
+        boolean mDebugDirtyRegions;
+        boolean mShowOverdraw;
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -654,38 +668,67 @@
         GlRenderer(int glVersion, boolean translucent) {
             mGlVersion = glVersion;
             mTranslucent = translucent;
-            
-            String property;
 
-            property = SystemProperties.get(PROFILE_PROPERTY, "false");
-            mProfileEnabled = "true".equalsIgnoreCase(property);
-            if (mProfileEnabled) {
-                Log.d(LOG_TAG, "Profiling hardware renderer");
-            }
+            loadSystemProperties(null);
+        }
 
-            if (mProfileEnabled) {
-                property = SystemProperties.get(PROFILE_MAXFRAMES_PROPERTY,
-                        Integer.toString(PROFILE_MAX_FRAMES));
-                int maxProfileFrames = Integer.valueOf(property);
-                mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT];
-                for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
-                    mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
+        @Override
+        boolean loadSystemProperties(Surface surface) {
+            boolean changed = false;
+
+            boolean value = SystemProperties.getBoolean(PROFILE_PROPERTY, false);
+            if (value != mProfileEnabled) {
+                changed = true;
+                mProfileEnabled = value;
+
+                if (mProfileEnabled) {
+                    Log.d(LOG_TAG, "Profiling hardware renderer");
                 }
 
-                mProfileLock = new ReentrantLock();
-            } else {
-                mProfileData = null;
-                mProfileLock = null;
+                if (mProfileEnabled) {
+                    int maxProfileFrames = SystemProperties.getInt(PROFILE_MAXFRAMES_PROPERTY,
+                            PROFILE_MAX_FRAMES);
+                    mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT];
+                    for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
+                        mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
+                    }
+
+                    mProfileLock = new ReentrantLock();
+                } else {
+                    mProfileData = null;
+                    mProfileLock = null;
+                }
             }
 
-            property = SystemProperties.get(DEBUG_DIRTY_REGIONS_PROPERTY, "false");
-            mDebugDirtyRegions = "true".equalsIgnoreCase(property);
-            if (mDebugDirtyRegions) {
-                Log.d(LOG_TAG, "Debugging dirty regions");
+            value = SystemProperties.getBoolean(DEBUG_DIRTY_REGIONS_PROPERTY, false);
+            if (value != mDebugDirtyRegions) {
+                changed = true;
+                mDebugDirtyRegions = value;
+
+                if (mDebugDirtyRegions) {
+                    Log.d(LOG_TAG, "Debugging dirty regions");
+                }
             }
 
-            mShowOverdraw = SystemProperties.getBoolean(
+            value = SystemProperties.getBoolean(
                     HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY, false);
+            if (value != mShowOverdraw) {
+                changed = true;
+                mShowOverdraw = value;
+
+                if (surface != null && isEnabled()) {
+                    if (validate()) {
+                        sEglConfig = loadEglConfig();
+                        invalidate(surface);
+                    }
+                }
+            }
+
+            if (nLoadProperties()) {
+                changed = true;
+            }
+
+            return changed;
         }
 
         @Override
@@ -815,19 +858,7 @@
 
                     checkEglErrorsForced();
 
-                    sEglConfig = chooseEglConfig();
-                    if (sEglConfig == null) {
-                        // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
-                        if (sDirtyRegions) {
-                            sDirtyRegions = false;
-                            sEglConfig = chooseEglConfig();
-                            if (sEglConfig == null) {
-                                throw new RuntimeException("eglConfig not initialized");
-                            }
-                        } else {
-                            throw new RuntimeException("eglConfig not initialized");
-                        }
-                    }
+                    sEglConfig = loadEglConfig();
                 }
             }
 
@@ -841,6 +872,23 @@
             }
         }
 
+        private EGLConfig loadEglConfig() {
+            EGLConfig eglConfig = chooseEglConfig();
+            if (eglConfig == null) {
+                // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
+                if (sDirtyRegions) {
+                    sDirtyRegions = false;
+                    eglConfig = chooseEglConfig();
+                    if (eglConfig == null) {
+                        throw new RuntimeException("eglConfig not initialized");
+                    }
+                } else {
+                    throw new RuntimeException("eglConfig not initialized");
+                }
+            }
+            return eglConfig;
+        }
+
         abstract ManagedEGLContext createManagedContext(EGLContext eglContext);
 
         private EGLConfig chooseEglConfig() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c9b4fec..e66e30f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -382,8 +382,6 @@
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
         mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
-        mProfileRendering = Boolean.parseBoolean(
-                SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
         mChoreographer = Choreographer.getInstance();
 
         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -2043,13 +2041,13 @@
                         mDirty.set(0, 0, mWidth, mHeight);
                         scheduleTraversals();
                         if (mRenderProfilingEnabled) {
-                            Choreographer.getInstance().postFrameCallback(mRenderProfiler);
+                            mChoreographer.postFrameCallback(mRenderProfiler);
                         }
                     }
                 };
-                Choreographer.getInstance().postFrameCallback(mRenderProfiler);
+                mChoreographer.postFrameCallback(mRenderProfiler);
             } else {
-                Choreographer.getInstance().removeFrameCallback(mRenderProfiler);
+                mChoreographer.removeFrameCallback(mRenderProfiler);
                 mRenderProfiler = null;
             }
         }
@@ -4182,14 +4180,30 @@
     }
 
     public void loadSystemProperties() {
-        boolean layout = SystemProperties.getBoolean(
-                View.DEBUG_LAYOUT_PROPERTY, false);
-        if (layout != mAttachInfo.mDebugLayout) {
-            mAttachInfo.mDebugLayout = layout;
-            if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) {
-                mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_WORLD, 200);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                // Profiling
+                mProfileRendering = SystemProperties.getBoolean(PROPERTY_PROFILE_RENDERING, false);
+                profileRendering(mAttachInfo.mHasWindowFocus);
+
+                // Hardware rendering
+                if (mAttachInfo.mHardwareRenderer != null) {
+                    if (mAttachInfo.mHardwareRenderer.loadSystemProperties(mHolder.getSurface())) {
+                        invalidate();
+                    }
+                }
+
+                // Layout debugging
+                boolean layout = SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false);
+                if (layout != mAttachInfo.mDebugLayout) {
+                    mAttachInfo.mDebugLayout = layout;
+                    if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) {
+                        mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_WORLD, 200);
+                    }
+                }
             }
-        }
+        });
     }
 
     private void destroyHardwareRenderer() {
diff --git a/core/jni/android_view_HardwareRenderer.cpp b/core/jni/android_view_HardwareRenderer.cpp
index 3e2de73..948a966 100644
--- a/core/jni/android_view_HardwareRenderer.cpp
+++ b/core/jni/android_view_HardwareRenderer.cpp
@@ -22,6 +22,8 @@
 
 #include <EGL/egl_cache.h>
 
+#include <Caches.h>
+
 #ifdef USE_OPENGL_RENDERER
     EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
 #endif
@@ -88,6 +90,13 @@
 // Tracing and debugging
 // ----------------------------------------------------------------------------
 
+static bool android_view_HardwareRenderer_loadProperties(JNIEnv* env, jobject clazz) {
+    if (uirenderer::Caches::hasInstance()) {
+        return uirenderer::Caches::getInstance().initProperties();
+    }
+    return false;
+}
+
 static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz,
         jintArray size) {
 
@@ -134,6 +143,7 @@
 #ifdef USE_OPENGL_RENDERER
     { "nIsBackBufferPreserved", "()Z",   (void*) android_view_HardwareRenderer_isBackBufferPreserved },
     { "nPreserveBackBuffer",    "()Z",   (void*) android_view_HardwareRenderer_preserveBackBuffer },
+    { "nLoadProperties",        "()Z",   (void*) android_view_HardwareRenderer_loadProperties },
 
     { "nBeginFrame",            "([I)V", (void*) android_view_HardwareRenderer_beginFrame },
 #endif
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index e7085b0..5c2b388 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -126,7 +126,10 @@
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
 }
 
-void Caches::initProperties() {
+bool Caches::initProperties() {
+    bool prevDebugLayersUpdates = debugLayersUpdates;
+    bool prevDebugOverdraw = debugOverdraw;
+
     char property[PROPERTY_VALUE_MAX];
     if (property_get(PROPERTY_DEBUG_LAYERS_UPDATES, property, NULL) > 0) {
         INIT_LOGD("  Layers updates debug enabled: %s", property);
@@ -141,6 +144,9 @@
     } else {
         debugOverdraw = false;
     }
+
+    return (prevDebugLayersUpdates != debugLayersUpdates) ||
+            (prevDebugOverdraw != debugOverdraw);
 }
 
 void Caches::terminate() {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ad1ff6f..628d8a0 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -115,6 +115,11 @@
     void init();
 
     /**
+     * Initialize global system properties.
+     */
+    bool initProperties();
+
+    /**
      * Flush the cache.
      *
      * @param mode Indicates how much of the cache should be flushed
@@ -281,7 +286,6 @@
     void initFont();
     void initExtensions();
     void initConstraints();
-    void initProperties();
 
     static void eventMarkNull(GLsizei length, const GLchar* marker) { }
     static void startMarkNull(GLsizei length, const GLchar* marker) { }
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 1cdc063..ee1d391 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -41,6 +41,7 @@
     renderer = NULL;
     displayList = NULL;
     fbo = 0;
+    debugDrawUpdate = false;
     Caches::getInstance().resourceCache.incrementRefcount(this);
 }
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index e1f6a70..181eb6c 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -265,6 +265,7 @@
     OpenGLRenderer* renderer;
     DisplayList* displayList;
     Rect dirtyRect;
+    bool debugDrawUpdate;
 
 private:
     /**
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index bc30738..c7a2014 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -489,6 +489,7 @@
         layer->deferredUpdateScheduled = false;
         layer->renderer = NULL;
         layer->displayList = NULL;
+        layer->debugDrawUpdate = mCaches.debugLayersUpdates;
 
         return true;
     }
@@ -2806,10 +2807,7 @@
         return DrawGlInfo::kStatusDone;
     }
 
-    bool debugLayerUpdate = false;
-    if (updateLayer(layer, true)) {
-        debugLayerUpdate = mCaches.debugLayersUpdates;
-    }
+    updateLayer(layer, true);
 
     mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clip.contains(transformed));
     mCaches.activeTexture(0);
@@ -2857,7 +2855,8 @@
 
         mColorFilter = oldFilter;
 
-        if (debugLayerUpdate) {
+        if (layer->debugDrawUpdate) {
+            layer->debugDrawUpdate = false;
             drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(),
                     0x7f00ff00, SkXfermode::kSrcOver_Mode);
         }