Merge "Fix include paths" into jb-mr2-dev
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 77da0bf..81d1ec0 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -1,4 +1,4 @@
- /*
+/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -71,17 +71,17 @@
public:
enum EventType {
kDrmPluginEventProvisionRequired,
- kDrmPluginEventLicenseNeeded,
- kDrmPluginEventLicenseExpired,
+ kDrmPluginEventKeyNeeded,
+ kDrmPluginEventKeyExpired,
kDrmPluginEventVendorDefined
};
- // A license can be for offline content or for online streaming.
- // Offline licenses are persisted on the device and may be used when the device
+ // Drm keys can be for offline content or for online streaming.
+ // Offline keys are persisted on the device and may be used when the device
// is disconnected from the network.
- enum LicenseType {
- kLicenseType_Offline,
- kLicenseType_Streaming
+ enum KeyType {
+ kKeyType_Offline,
+ kKeyType_Streaming
};
DrmPlugin() {}
@@ -94,38 +94,45 @@
// Close a session on the DrmPlugin object.
virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
- // A license request/response exchange occurs between the app and a License
- // Server to obtain the keys required to decrypt the content. getLicenseRequest()
- // is used to obtain an opaque license request blob that is delivered to the
+ // A key request/response exchange occurs between the app and a License
+ // Server to obtain the keys required to decrypt the content. getKeyRequest()
+ // is used to obtain an opaque key request blob that is delivered to the
// license server.
//
- // The init data passed to getLicenseRequest is container-specific and its
+ // The init data passed to getKeyRequest is container-specific and its
// meaning is interpreted based on the mime type provided in the mimeType
- // parameter to getLicenseRequest. It could contain, for example, the content
+ // parameter to getKeyRequest. It could contain, for example, the content
// ID, key ID or other data obtained from the content metadata that is required
- // in generating the license request.
+ // in generating the key request.
//
- // licenseType specifes if the license is for streaming or offline content
+ // keyType specifes if the keys are to be used for streaming or offline content
//
- // optionalParameters are included in the license server request message to
- // allow a client application to provide additional message parameters to the
- // server.
+ // optionalParameters are included in the key request message to allow a
+ // client application to provide additional message parameters to the server.
//
- // If successful, the opaque license request blob is returned to the caller.
+ // If successful, the opaque key request blob is returned to the caller.
virtual status_t
- getLicenseRequest(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &initData,
- String8 const &mimeType, LicenseType licenseType,
- KeyedVector<String8, String8> const &optionalParameters,
- Vector<uint8_t> &request, String8 &defaultUrl) = 0;
+ getKeyRequest(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &initData,
+ String8 const &mimeType, KeyType keyType,
+ KeyedVector<String8, String8> const &optionalParameters,
+ Vector<uint8_t> &request, String8 &defaultUrl) = 0;
- // After a license response is received by the app, it is provided to the
- // Drm plugin using provideLicenseResponse.
- virtual status_t provideLicenseResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response) = 0;
+ // After a key response is received by the app, it is provided to the
+ // Drm plugin using provideKeyResponse. Returns the id of the key set
+ // in keySetId. The keySetId can be used by removeKeys or restoreKeys
+ // when the keys are used for offline content.
+ virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId) = 0;
- // Remove the keys associated with a license.
- virtual status_t removeLicense(Vector<uint8_t> const &sessionId) = 0;
+ // Remove the persisted keys associated with an offline license for a session.
+ virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0;
+
+ // Restore persisted offline keys into a new session. keySetId identifies
+ // the keys to load, obtained from a prior call to provideKeyResponse().
+ virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId) = 0;
// Request an informative description of the license for the session. The status
// is in the form of {name, value} pairs. Since DRM license policies vary by
@@ -133,12 +140,12 @@
// Refer to your DRM provider documentation for definitions of the field names
// for a particular DrmEngine.
virtual status_t
- queryLicenseStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const = 0;
+ queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const = 0;
// A provision request/response exchange occurs between the app and a
// provisioning server to retrieve a device certificate. getProvisionRequest
- // is used to obtain an opaque license request blob that is delivered to the
+ // is used to obtain an opaque key request blob that is delivered to the
// provisioning server.
//
// If successful, the opaque provision request blob is returned to the caller.
@@ -195,6 +202,66 @@
virtual status_t setPropertyByteArray(String8 const &name,
Vector<uint8_t> const &value ) = 0;
+ // The following methods implement operations on a CryptoSession to support
+ // encrypt, decrypt, sign verify operations on operator-provided
+ // session keys.
+
+ //
+ // The algorithm string conforms to JCA Standard Names for Cipher
+ // Transforms and is case insensitive. For example "AES/CBC/PKCS5Padding".
+ //
+ // Return OK if the algorithm is supported, otherwise return BAD_VALUE
+ //
+ virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) = 0;
+
+ //
+ // The algorithm string conforms to JCA Standard Names for Mac
+ // Algorithms and is case insensitive. For example "HmacSHA256".
+ //
+ // Return OK if the algorithm is supported, otherwise return BAD_VALUE
+ //
+ virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) = 0;
+
+ // Encrypt the provided input buffer with the cipher algorithm
+ // specified by setCipherAlgorithm and the key selected by keyId,
+ // and return the encrypted data.
+ virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output) = 0;
+
+ // Decrypt the provided input buffer with the cipher algorithm
+ // specified by setCipherAlgorithm and the key selected by keyId,
+ // and return the decrypted data.
+ virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output) = 0;
+
+ // Compute a signature on the provided message using the mac algorithm
+ // specified by setMacAlgorithm and the key selected by keyId,
+ // and return the signature.
+ virtual status_t sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature) = 0;
+
+ // Compute a signature on the provided message using the mac algorithm
+ // specified by setMacAlgorithm and the key selected by keyId,
+ // and compare with the expected result. Set result to true or
+ // false depending on the outcome.
+ virtual status_t verify(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &signature,
+ bool &match) = 0;
+
+
+
// TODO: provide way to send an event
private:
DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 1b3d6ed..9b8d3fe 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -34,6 +34,13 @@
LOCAL_CFLAGS += -fstrict-aliasing
endif
+ifeq ($(TARGET_ARCH),mips)
+ LOCAL_SRC_FILES += arch-$(TARGET_ARCH)/fixed_asm.S
+ LOCAL_CFLAGS += -fstrict-aliasing
+ # The graphics code can generate division by zero
+ LOCAL_CFLAGS += -mno-check-zero-division
+endif
+
# we need to access the private Bionic header <bionic_tls.h>
LOCAL_C_INCLUDES += bionic/libc/private
diff --git a/opengl/libagl/arch-mips/fixed_asm.S b/opengl/libagl/arch-mips/fixed_asm.S
new file mode 100644
index 0000000..e1a53bc
--- /dev/null
+++ b/opengl/libagl/arch-mips/fixed_asm.S
@@ -0,0 +1,61 @@
+/* libs/opengles/arch-mips/fixed_asm.S
+**
+** Copyright 2012, 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.
+*/
+
+
+ .text
+ .align
+
+/*
+ * this version rounds-to-nearest and saturates numbers
+ * outside the range (but not NaNs).
+ */
+
+ .global gglFloatToFixed
+ .ent gglFloatToFixed
+ .type gglFloatToFixed, @function
+gglFloatToFixed:
+#if !defined(__mips_soft_float)
+ mfc1 $a0,$f12
+#endif
+ srl $t0,$a0,31 /* t0 <- sign bit */
+ srl $t1,$a0,23
+ andi $t1,$t1,0xff /* get the e */
+ li $t2,0x8e
+ subu $t1,$t2,$t1 /* t1=127+15-e */
+ blez $t1,0f /* t1<=0? */
+ sll $t2,$a0,8 /* mantissa<<8 */
+ lui $t3,0x8000
+ or $t2,$t2,$t3 /* add the missing 1 */
+ subu $t1,$t1,1
+ srl $v0,$t2,$t1
+ sltiu $t3,$t1,32 /* t3=1 if t1<32, else t3=0. t1>=32 means the float value is too small. */
+ andi $t4,$v0,0x1
+ srl $v0,$v0,1 /* scale to 16.16 */
+ addu $v0,$v0,$t4 /* round-to-nearest */
+ subu $t2,$zero,$v0
+ movn $v0,$t2,$t0 /* if negative? */
+ or $t1,$a0,$zero /* a0=0? */
+ movz $v0,$zero,$t1
+ movz $v0,$zero,$t3 /* t3=0 then res=0 */
+ jr $ra
+0:
+ lui $t1,0x8000
+ and $v0,$a0,$t1 /* keep only the sign bit */
+ li $t1,0x7fffffff
+ movz $v0,$t1,$t0 /* positive, maximum value */
+ jr $ra
+ .end gglFloatToFixed
diff --git a/opengl/libagl/fp.cpp b/opengl/libagl/fp.cpp
index ae5f1fe..aea4449 100644
--- a/opengl/libagl/fp.cpp
+++ b/opengl/libagl/fp.cpp
@@ -19,7 +19,7 @@
// ----------------------------------------------------------------------------
-#if !defined(__arm__)
+#if !defined(__arm__) && !defined(__mips__)
GGLfixed gglFloatToFixed(float v) {
return GGLfixed(floorf(v * 65536.0f + 0.5f));
}
diff --git a/opengl/libagl/matrix.h b/opengl/libagl/matrix.h
index c9a38a9..5bd717a 100644
--- a/opengl/libagl/matrix.h
+++ b/opengl/libagl/matrix.h
@@ -74,6 +74,30 @@
);
return r;
+#elif defined(__mips__)
+
+ GLfixed res;
+ int32_t t1,t2,t3;
+ asm(
+ "mult %[a], %[a] \r\n"
+ "li %[res],0x8000 \r\n"
+ "madd %[b],%[b] \r\n"
+ "move %[t3],$zero \r\n"
+ "madd %[c],%[c] \r\n"
+ "mflo %[t1]\r\n"
+ "mfhi %[t2]\r\n"
+ "addu %[t1],%[res],%[t1]\r\n" /*add 0x8000*/
+ "sltu %[t3],%[t1],%[res]\r\n"
+ "addu %[t2],%[t2],%[t3]\r\n"
+ "srl %[res],%[t1],16\r\n"
+ "sll %[t2],%[t2],16\r\n"
+ "or %[res],%[res],%[t2]\r\n"
+ : [res]"=&r"(res),[t1]"=&r"(t1),[t2]"=&r"(t2),[t3]"=&r"(t3)
+ : [a] "r" (a),[b] "r" (b),[c] "r" (c)
+ : "%hi","%lo"
+ );
+ return res;
+
#else
return (( int64_t(a)*a +
@@ -136,6 +160,26 @@
);
return r;
+#elif defined(__mips__)
+
+ GLfixed res;
+ int32_t t1,t2;
+ asm(
+ "mult %[a0],%[b0] \r\n"
+ "madd %[a1],%[b1] \r\n"
+ "madd %[a2],%[b2] \r\n"
+ "mflo %[t2]\r\n"
+ "mfhi %[t1]\r\n"
+ "srl %[t2],%[t2],16\r\n"
+ "sll %[t1],%[t1],16\r\n"
+ "or %[t2],%[t2],%[t1]\r\n"
+ "addu %[res],%[t2],%[c]"
+ : [res]"=&r"(res),[t1]"=&r"(t1),[t2]"=&r"(t2)
+ : [a0] "r" (a0),[b0] "r" (b0),[a1] "r" (a1),[b1] "r" (b1),[a2] "r" (a2),[b2] "r" (b2),[c] "r" (c)
+ : "%hi","%lo"
+ );
+ return res;
+
#else
return (( int64_t(a0)*b0 +
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index f453176..1909232 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -37,6 +37,8 @@
#if USE_FAST_TLS_KEY
+ #if defined(__arm__)
+
#define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
@@ -57,6 +59,41 @@
: \
);
+ #elif defined(__mips__)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_EXTENSION_API(_api, ...) \
+ register unsigned int _t0 asm("t0"); \
+ register unsigned int _fn asm("t1"); \
+ register unsigned int _tls asm("v1"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ ".set mips32r2\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "lw %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn], $ra\n\t" \
+ "lw %[fn], %[API](%[t0])\n\t" \
+ "movz %[fn], $ra, %[fn]\n\t" \
+ "1:\n\t" \
+ "j %[fn]\n\t" \
+ " nop\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(_fn), \
+ [tls] "=&r"(_tls), \
+ [t0] "=&r"(_t0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4), \
+ [API] "I"(__builtin_offsetof(gl_hooks_t, \
+ ext.extensions[_api])) \
+ : \
+ );
+
+ #else
+ #error Unsupported architecture
+ #endif
+
#define GL_EXTENSION_NAME(_n) __glExtFwd##_n
#define GL_EXTENSION(_n) \
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index a01da65..dd454bd 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -42,6 +42,8 @@
#if USE_FAST_TLS_KEY
+ #if defined(__arm__)
+
#define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
@@ -60,6 +62,44 @@
: \
);
+ #elif defined(__mips__)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_API(_api, ...) \
+ register unsigned int _t0 asm("t0"); \
+ register unsigned int _fn asm("t1"); \
+ register unsigned int _tls asm("v1"); \
+ register unsigned int _v0 asm("v0"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ ".set mips32r2\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "lw %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn],$ra\n\t" \
+ "lw %[fn], %[API](%[t0])\n\t" \
+ "movz %[fn], $ra, %[fn]\n\t" \
+ "1:\n\t" \
+ "j %[fn]\n\t" \
+ " move %[v0], $0\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(_fn), \
+ [tls] "=&r"(_tls), \
+ [t0] "=&r"(_t0), \
+ [v0] "=&r"(_v0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4), \
+ [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+ : \
+ );
+
+ #else
+
+ #error Unsupported architecture
+
+ #endif
+
#define CALL_GL_API_RETURN(_api, ...) \
CALL_GL_API(_api, __VA_ARGS__) \
return 0; // placate gcc's warnings. never reached.
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 48fd278..8ac8ff9 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -97,6 +97,8 @@
#if USE_FAST_TLS_KEY && !CHECK_FOR_GL_ERRORS
+ #if defined(__arm__)
+
#define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
@@ -115,6 +117,42 @@
: \
);
+ #elif defined(__mips__)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_API(_api, ...) \
+ register unsigned int _t0 asm("t0"); \
+ register unsigned int _fn asm("t1"); \
+ register unsigned int _tls asm("v1"); \
+ register unsigned int _v0 asm("v0"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ ".set mips32r2\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "lw %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn], $ra\n\t" \
+ "lw %[fn], %[API](%[t0])\n\t" \
+ "movz %[fn], $ra, %[fn]\n\t" \
+ "1:\n\t" \
+ "j %[fn]\n\t" \
+ " move %[v0], $0\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(_fn), \
+ [tls] "=&r"(_tls), \
+ [t0] "=&r"(_t0), \
+ [v0] "=&r"(_v0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4), \
+ [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+ : \
+ );
+
+ #else
+ #error Unsupported architecture
+ #endif
+
#define CALL_GL_API_RETURN(_api, ...) \
CALL_GL_API(_api, __VA_ARGS__) \
return 0; // placate gcc's warnings. never reached.
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 77077d6..b2a684c 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -32,7 +32,7 @@
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
-#if !defined(__arm__)
+#if !defined(__arm__) && !defined(__mips__)
#define USE_SLOW_BINDING 1
#else
#define USE_SLOW_BINDING 0
diff --git a/opengl/specs/EGL_ANDROID_presentation_time.txt b/opengl/specs/EGL_ANDROID_presentation_time.txt
new file mode 100644
index 0000000..03370ed
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_presentation_time.txt
@@ -0,0 +1,121 @@
+Name
+
+ ANDROID_presentation_time
+
+Name Strings
+
+ EGL_ANDROID_presentation_time
+
+Contributors
+
+ Jamie Gennis
+ Andy McFadden
+
+Contact
+
+ Jamie Gennis, Google Inc. (jgennis 'at' google.com)
+
+Status
+
+ Draft
+
+Version
+
+ Version 2, April 1, 2013
+
+Number
+
+ EGL Extension #XXX
+
+Dependencies
+
+ Requires EGL 1.1
+
+ This extension is written against the wording of the EGL 1.4 Specification
+
+Overview
+
+ Often when rendering a sequence of images, there is some time at which each
+ image is intended to be presented to the viewer. This extension allows
+ this desired presentation time to be specified for each frame rendered to
+ an EGLSurface, allowing the native window system to use it.
+
+New Types
+
+ /*
+ * EGLnsecsANDROID is a signed integer type for representing a time in
+ * nanoseconds.
+ */
+ #include <khrplatform.h>
+ typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
+
+
+New Procedures and Functions
+
+ EGLboolean eglPresentationTimeANDROID(
+ EGLDisplay dpy,
+ EGLSurface sur,
+ EGLnsecsANDROID time);
+
+New Tokens
+
+ None.
+
+Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
+
+ Add a new subsection before Section 3.9.4, page 53 (Posting Errors)
+
+ "3.9.4 Presentation Time
+
+ The function
+
+ EGLboolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface
+ surface, EGLnsecsANDROID time);
+
+ specifies the time at which the current color buffer of surface should be
+ presented to the viewer. The time parameter should be a time in
+ nanoseconds, but the exact meaning of the time depends on the native
+ window system's use of the presentation time. In situations where
+ an absolute time is needed such as displaying the color buffer on a
+ display device, the time should correspond to the system monotonic up-time
+ clock. For situations in which an absolute time is not needed such as
+ using the color buffer for video encoding, the presentation time of the
+ first frame may be arbitrarily chosen and those of subsequent frames
+ chosen relative to that of the first frame.
+
+ The presentation time may be set multiple times, with each call to
+ eglPresentationTimeANDROID overriding prior calls. Setting the
+ presentation time alone does not cause the color buffer to be made
+ visible, but if the color buffer is subsequently posted to a native window
+ or copied to a native pixmap then the presentation time of the surface at
+ that time may be passed along for the native window system to use.
+
+ If the surface presentation time is successfully set, EGL_TRUE is
+ returned. Otherwise EGL_FALSE is returned and an appropriate error is
+ set.
+
+Issues
+
+ 1. How is the presentation time used?
+
+ RESOLVED: The uses of the presentation time are intentionally not specified
+ in this extension. Some possible uses include Audio/Video synchronization,
+ video frame timestamps for video encoding, display latency metrics, and
+ display latency control.
+
+ 2. How can the current value of the clock that should be used for the
+ presentation time when an absolute time is needed be queried on Android?
+
+ RESOLVED: The current clock value can be queried from the Java
+ SystemClock#uptimeMillis() method or from the native clock_gettime
+ function by passing CLOCK_MONOTONIC as the clock identifier.
+
+Revision History
+
+#1 (Jamie Gennis, April 1, 2013)
+ - Clarified how uses that either do or do not need an absolute time should
+ be handled.
+ - Specified the eglPresentationTimeANDROID return value.
+
+#1 (Jamie Gennis, January 8, 2013)
+ - Initial draft.