Dispatch refresh rate callbacks from DMS

AChoreographer will consume these callbacks in lieu of going through SF
for the callbacks. This is so that DMS can update its view of display
configs before apps receive the refresh rate callback so that apps can
get consistent information.

Bug: 154874011
Test: ChoreographerNativeTest
Test: Manually verify that HWUI is receiving callbacks
Change-Id: I992c247fd16ef414f94a259bbd300bea3e4c9467
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 4d645e6..0f9c708 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -34,7 +34,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
@@ -74,6 +73,8 @@
     @UnsupportedAppUsage
     private static DisplayManagerGlobal sInstance;
 
+    // Guarded by mLock
+    private boolean mDispatchNativeCallbacks = false;
     private final Object mLock = new Object();
 
     @UnsupportedAppUsage
@@ -143,30 +144,38 @@
     @UnsupportedAppUsage
     public DisplayInfo getDisplayInfo(int displayId) {
         synchronized (mLock) {
-            DisplayInfo info = null;
-            if (mDisplayCache != null) {
-                info = mDisplayCache.query(displayId);
-            } else {
-                try {
-                    info = mDm.getDisplayInfo(displayId);
-                } catch (RemoteException ex) {
-                    ex.rethrowFromSystemServer();
-                }
-            }
-            if (info == null) {
-                return null;
-            }
-
-            registerCallbackIfNeededLocked();
-
-            if (DEBUG) {
-                Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
-            }
-            return info;
+            return getDisplayInfoLocked(displayId);
         }
     }
 
     /**
+     * Gets information about a particular logical display
+     * See {@link getDisplayInfo}, but assumes that {@link mLock} is held
+     */
+    private @Nullable DisplayInfo getDisplayInfoLocked(int displayId) {
+        DisplayInfo info = null;
+        if (mDisplayCache != null) {
+            info = mDisplayCache.query(displayId);
+        } else {
+            try {
+                info = mDm.getDisplayInfo(displayId);
+            } catch (RemoteException ex) {
+                ex.rethrowFromSystemServer();
+            }
+        }
+        if (info == null) {
+            return null;
+        }
+
+        registerCallbackIfNeededLocked();
+
+        if (DEBUG) {
+            Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
+        }
+        return info;
+    }
+
+    /**
      * Gets all currently valid logical display ids.
      *
      * @return An array containing all display ids.
@@ -341,6 +350,20 @@
             for (int i = 0; i < numListeners; i++) {
                 mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
             }
+            if (event == EVENT_DISPLAY_CHANGED && mDispatchNativeCallbacks) {
+                // Choreographer only supports a single display, so only dispatch refresh rate
+                // changes for the default display.
+                if (displayId == Display.DEFAULT_DISPLAY) {
+                    // We can likely save a binder hop if we attach the refresh rate onto the
+                    // listener.
+                    DisplayInfo display = getDisplayInfoLocked(displayId);
+                    if (display != null) {
+                        float refreshRate = display.getMode().getRefreshRate();
+                        // Signal native callbacks if we ever set a refresh rate.
+                        nSignalNativeCallbacks(refreshRate);
+                    }
+                }
+            }
         }
     }
 
@@ -800,4 +823,30 @@
     public void disableLocalDisplayInfoCaches() {
         mDisplayCache = null;
     }
+
+    private static native void nSignalNativeCallbacks(float refreshRate);
+
+    // Called from AChoreographer via JNI.
+    // Registers AChoreographer so that refresh rate callbacks can be dispatched from DMS.
+    private void registerNativeChoreographerForRefreshRateCallbacks() {
+        synchronized (mLock) {
+            registerCallbackIfNeededLocked();
+            mDispatchNativeCallbacks = true;
+            DisplayInfo display = getDisplayInfoLocked(Display.DEFAULT_DISPLAY);
+            if (display != null) {
+                // We need to tell AChoreographer instances the current refresh rate so that apps
+                // can get it for free once a callback first registers.
+                float refreshRate = display.getMode().getRefreshRate();
+                nSignalNativeCallbacks(refreshRate);
+            }
+        }
+    }
+
+    // Called from AChoreographer via JNI.
+    // Unregisters AChoreographer from receiving refresh rate callbacks.
+    private void unregisterNativeChoreographerForRefreshRateCallbacks() {
+        synchronized (mLock) {
+            mDispatchNativeCallbacks = false;
+        }
+    }
 }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index bd7bc4c..5a66f43 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -158,6 +158,7 @@
                 "android_hardware_camera2_legacy_LegacyCameraDevice.cpp",
                 "android_hardware_camera2_legacy_PerfMeasurement.cpp",
                 "android_hardware_camera2_DngCreator.cpp",
+                "android_hardware_display_DisplayManagerGlobal.cpp",
                 "android_hardware_display_DisplayViewport.cpp",
                 "android_hardware_HardwareBuffer.cpp",
                 "android_hardware_SensorManager.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6fcaddf..a420ba6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -18,39 +18,37 @@
 #define LOG_TAG "AndroidRuntime"
 #define LOG_NDEBUG 1
 
-#include <android_runtime/AndroidRuntime.h>
-
 #include <android-base/macros.h>
 #include <android-base/properties.h>
 #include <android/graphics/jni_runtime.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <assert.h>
 #include <binder/IBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-#include <utils/Trace.h>
 #include <binder/Parcel.h>
-#include <utils/threads.h>
+#include <bionic/malloc.h>
 #include <cutils/properties.h>
-#include <server_configurable_flags/get_flags.h>
-
-#include "jni.h"
+#include <dirent.h>
+#include <dlfcn.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/JniInvocation.h>
-#include "android_util_Binder.h"
-
-#include <stdio.h>
+#include <server_configurable_flags/get_flags.h>
 #include <signal.h>
+#include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <signal.h>
-#include <dirent.h>
-#include <assert.h>
-#include <bionic/malloc.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <utils/misc.h>
+#include <utils/threads.h>
 
 #include <string>
 #include <vector>
 
+#include "android_util_Binder.h"
+#include "jni.h"
+
 using namespace android;
 using android::base::GetProperty;
 
@@ -78,6 +76,7 @@
 extern int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv *env);
 extern int register_android_hardware_camera2_legacy_PerfMeasurement(JNIEnv *env);
 extern int register_android_hardware_camera2_DngCreator(JNIEnv *env);
+extern int register_android_hardware_display_DisplayManagerGlobal(JNIEnv* env);
 extern int register_android_hardware_HardwareBuffer(JNIEnv *env);
 extern int register_android_hardware_SensorManager(JNIEnv *env);
 extern int register_android_hardware_SerialPort(JNIEnv *env);
@@ -1519,6 +1518,7 @@
         REG_JNI(register_android_hardware_camera2_legacy_LegacyCameraDevice),
         REG_JNI(register_android_hardware_camera2_legacy_PerfMeasurement),
         REG_JNI(register_android_hardware_camera2_DngCreator),
+        REG_JNI(register_android_hardware_display_DisplayManagerGlobal),
         REG_JNI(register_android_hardware_HardwareBuffer),
         REG_JNI(register_android_hardware_SensorManager),
         REG_JNI(register_android_hardware_SerialPort),
diff --git a/core/jni/android_hardware_display_DisplayManagerGlobal.cpp b/core/jni/android_hardware_display_DisplayManagerGlobal.cpp
new file mode 100644
index 0000000..9f31671
--- /dev/null
+++ b/core/jni/android_hardware_display_DisplayManagerGlobal.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#define LOG_TAG "DisplayManagerGlobal-JNI"
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <private/android/choreographer.h>
+
+#include <vector>
+
+#include "core_jni_helpers.h"
+
+using namespace android;
+
+namespace android {
+
+// Dispatches the current refresh rate for the default display to all
+// choreographer instances
+void android_hardware_display_DisplayManagerGlobal_signalNativeCallbacks(JNIEnv* env, jobject,
+                                                                         jfloat refreshRate) {
+    const constexpr int64_t kNanosPerSecond = 1000 * 1000 * 1000;
+    const nsecs_t vsyncPeriod = kNanosPerSecond / refreshRate;
+
+    AChoreographer_signalRefreshRateCallbacks(vsyncPeriod);
+}
+
+} // namespace android
+
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/hardware/display/DisplayManagerGlobal";
+
+static const JNINativeMethod gMethods[] = {
+        {"nSignalNativeCallbacks", "(F)V",
+         (void*)android_hardware_display_DisplayManagerGlobal_signalNativeCallbacks},
+};
+
+int register_android_hardware_display_DisplayManagerGlobal(JNIEnv* env) {
+    AChoreographer_initJVM(env);
+    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+}
diff --git a/core/jni/include/android_runtime/AndroidRuntime.h b/core/jni/include/android_runtime/AndroidRuntime.h
index 2351272..d86d934 100644
--- a/core/jni/include/android_runtime/AndroidRuntime.h
+++ b/core/jni/include/android_runtime/AndroidRuntime.h
@@ -19,15 +19,14 @@
 #ifndef _RUNTIME_ANDROID_RUNTIME_H
 #define _RUNTIME_ANDROID_RUNTIME_H
 
-#include <utils/Errors.h>
 #include <binder/IBinder.h>
-#include <utils/String8.h>
+#include <jni.h>
+#include <pthread.h>
+#include <utils/Errors.h>
 #include <utils/String16.h>
+#include <utils/String8.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
-#include <pthread.h>
-#include <jni.h>
-
 
 namespace android {
 
@@ -154,6 +153,6 @@
     static int javaThreadShell(void* args);
 };
 
-}
+} // namespace android
 
 #endif
diff --git a/native/android/Android.bp b/native/android/Android.bp
index ed73f39..797d3fd 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -37,6 +37,7 @@
 
     srcs: [
         "asset_manager.cpp",
+        "choreographer.cpp",
         "configuration.cpp",
         "hardware_buffer_jni.cpp",
         "input.cpp",
@@ -49,6 +50,7 @@
         "sharedmem.cpp",
         "storage_manager.cpp",
         "surface_control.cpp",
+        "surface_texture.cpp",
         "system_fonts.cpp",
         "trace.cpp",
         "thermal.cpp"
@@ -76,6 +78,7 @@
         "libpowermanager",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore-utils",
+        "libnativedisplay",
     ],
 
     static_libs: [
@@ -83,9 +86,9 @@
         "libarect",
     ],
 
-    header_libs: [ "libhwui_internal_headers" ],
+    header_libs: [ "libhwui_internal_headers",],
 
-    whole_static_libs: ["libnativedisplay", "libnativewindow"],
+    whole_static_libs: ["libnativewindow"],
 
     export_static_lib_headers: ["libarect"],
 
diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp
new file mode 100644
index 0000000..38641de
--- /dev/null
+++ b/native/android/choreographer.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 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 <private/android/choreographer.h>
+
+using namespace android;
+
+AChoreographer* AChoreographer_getInstance() {
+    return AChoreographer_routeGetInstance();
+}
+void AChoreographer_postFrameCallback(AChoreographer* choreographer,
+                                      AChoreographer_frameCallback callback, void* data) {
+    return AChoreographer_routePostFrameCallback(choreographer, callback, data);
+}
+void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
+                                             AChoreographer_frameCallback callback, void* data,
+                                             long delayMillis) {
+    return AChoreographer_routePostFrameCallbackDelayed(choreographer, callback, data, delayMillis);
+}
+void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
+                                        AChoreographer_frameCallback64 callback, void* data) {
+    return AChoreographer_routePostFrameCallback64(choreographer, callback, data);
+}
+void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
+                                               AChoreographer_frameCallback64 callback, void* data,
+                                               uint32_t delayMillis) {
+    return AChoreographer_routePostFrameCallbackDelayed64(choreographer, callback, data,
+                                                          delayMillis);
+}
+void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
+                                                AChoreographer_refreshRateCallback callback,
+                                                void* data) {
+    return AChoreographer_routeRegisterRefreshRateCallback(choreographer, callback, data);
+}
+void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
+                                                  AChoreographer_refreshRateCallback callback,
+                                                  void* data) {
+    return AChoreographer_routeUnregisterRefreshRateCallback(choreographer, callback, data);
+}
diff --git a/native/android/surface_texture.cpp b/native/android/surface_texture.cpp
new file mode 100644
index 0000000..ff35204
--- /dev/null
+++ b/native/android/surface_texture.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 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/surface_texture_jni.h>
+#include <surfacetexture/surface_texture_platform.h>
+
+using namespace android;
+
+ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) {
+    return ASurfaceTexture_routeAcquireANativeWindow(st);
+}
+
+int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName) {
+    return ASurfaceTexture_routeAttachToGLContext(st, texName);
+}
+
+int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) {
+    return ASurfaceTexture_routeDetachFromGLContext(st);
+}
+
+void ASurfaceTexture_release(ASurfaceTexture* st) {
+    return ASurfaceTexture_routeRelease(st);
+}
+
+int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) {
+    return ASurfaceTexture_routeUpdateTexImage(st);
+}
+
+void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) {
+    return ASurfaceTexture_routeGetTransformMatrix(st, mtx);
+}
+
+int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) {
+    return ASurfaceTexture_routeGetTimestamp(st);
+}
+
+ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) {
+    return ASurfaceTexture_routeFromSurfaceTexture(env, surfacetexture);
+}