diff options
21 files changed, 281 insertions, 534 deletions
diff --git a/build/tablet-7in-xhdpi-2048-dalvik-heap.mk b/build/tablet-7in-xhdpi-2048-dalvik-heap.mk new file mode 100644 index 0000000..e0f20c1 --- /dev/null +++ b/build/tablet-7in-xhdpi-2048-dalvik-heap.mk @@ -0,0 +1,25 @@ +# +# Copyright (C) 2013 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. +# + +# Provides overrides to configure the Dalvik heap for a 320dpi 7" tablet device. + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=16m \ + dalvik.vm.heapgrowthlimit=192m \ + dalvik.vm.heapsize=512m \ + dalvik.vm.heaptargetutilization=0.75 \ + dalvik.vm.heapminfree=512k \ + dalvik.vm.heapmaxfree=8m diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 06e9744..1911839 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -81,6 +81,7 @@ static const TracingCategory k_categories[] = { { "camera", "Camera", ATRACE_TAG_CAMERA, { } }, { "hal", "Hardware Modules", ATRACE_TAG_HAL, { } }, { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } }, + { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } }, { "sched", "CPU Scheduling", 0, { { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" }, { REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" }, diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index e544be7..8e14a2c 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -421,7 +421,7 @@ int rm_dex(const char *path) } int get_size(const char *pkgname, int persona, const char *apkpath, - const char *fwdlock_apkpath, const char *asecpath, + const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int64_t* _asecsize) { @@ -460,8 +460,8 @@ int get_size(const char *pkgname, int persona, const char *apkpath, } /* add in size of any libraries */ - if (!create_pkg_path_in_dir(path, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { - d = opendir(path); + if (libdirpath != NULL && libdirpath[0] != '!') { + d = opendir(libdirpath); if (d != NULL) { dfd = dirfd(d); codesize += calculate_dir_size(dfd); diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index 230899b..c918633 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -84,7 +84,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int res = 0; /* pkgdir, persona, apkpath */ - res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], + res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5], &codesize, &datasize, &cachesize, &asecsize); /* @@ -138,7 +138,7 @@ struct cmdinfo cmds[] = { { "fixuid", 3, do_fixuid }, { "freecache", 1, do_free_cache }, { "rmcache", 2, do_rm_cache }, - { "getsize", 5, do_get_size }, + { "getsize", 6, do_get_size }, { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 3, do_linklib }, diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index 033d5a3..fbfc876 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -203,9 +203,9 @@ int delete_cache(const char *pkgname, uid_t persona); int move_dex(const char *src, const char *dst); int rm_dex(const char *path); int protect(char *pkgname, gid_t gid); -int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath, - const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize, - int64_t *asecsize); +int get_size(const char *pkgname, int persona, const char *apkpath, const char *libdirpath, + const char *fwdlock_apkpath, const char *asecpath, int64_t *codesize, + int64_t *datasize, int64_t *cachesize, int64_t *asecsize); int free_cache(int64_t free_size); int dexopt(const char *apk_path, uid_t uid, int is_public); int movefiles(); diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h index c89f2d6..fbf93bc 100644 --- a/include/media/drm/DrmAPI.h +++ b/include/media/drm/DrmAPI.h @@ -80,10 +80,12 @@ namespace android { // 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. + // is disconnected from the network. The Release type is used to request + // that offline keys be no longer restricted to offline use. enum KeyType { kKeyType_Offline, - kKeyType_Streaming + kKeyType_Streaming, + kKeyType_Release }; DrmPlugin() {} @@ -101,35 +103,55 @@ namespace android { // is used to obtain an opaque key request blob that is delivered to the // license server. // + // The scope parameter may be a sessionId or a keySetId, depending on the + // specified keyType. When the keyType is kKeyType_Offline or + // kKeyType_Streaming, scope should be set to the sessionId the keys will be + // provided to. When the keyType is kKeyType_Release, scope should be set to + // the keySetId of the keys being released. Releasing keys from a device + // invalidates them for all sessions. + // // 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 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 key request. + // in generating the key request. Init may be null when keyType is + // kKeyType_Release. + // + // mimeType identifies the mime type of the content // - // keyType specifes if the keys are to be used for streaming or offline content + // keyType specifies if the keys are to be used for streaming or offline content // // 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 key request blob is returned to the caller. virtual status_t - getKeyRequest(Vector<uint8_t> const &sessionId, + getKeyRequest(Vector<uint8_t> const &scope, Vector<uint8_t> const &initData, String8 const &mimeType, KeyType keyType, KeyedVector<String8, String8> const &optionalParameters, Vector<uint8_t> &request, String8 &defaultUrl) = 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, + // Drm plugin using provideKeyResponse. + // + // scope may be a sessionId or a keySetId depending on the type of the + // response. Scope should be set to the sessionId when the response is + // for either streaming or offline key requests. Scope should be set to the + // keySetId when the response is for a release request. + // + // When the response is for an offline key request, a keySetId is returned + // in the keySetId vector parameter that can be used to later restore the + // keys to a new session with the method restoreKeys. When the response is + // for a streaming or release request, no keySetId is returned. + // + virtual status_t provideKeyResponse(Vector<uint8_t> const &scope, Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) = 0; - // Remove the persisted keys associated with an offline license for a session. - virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0; + // Remove the current keys from a session + virtual status_t removeKeys(Vector<uint8_t> const &sessionId) = 0; // Restore persisted offline keys into a new session. keySetId identifies // the keys to load, obtained from a prior call to provideKeyResponse(). diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c index 6703783..24e5af0 100644 --- a/libs/diskusage/dirsize.c +++ b/libs/diskusage/dirsize.c @@ -24,7 +24,8 @@ int64_t stat_size(struct stat *s) { int64_t blksize = s->st_blksize; - int64_t size = s->st_size; + // count actual blocks used instead of nominal file size + int64_t size = s->st_blocks * 512; if (blksize) { /* round up to filesystem block size */ diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen index 29212c0..d236c1e 100755 --- a/opengl/tools/glgen/gen +++ b/opengl/tools/glgen/gen @@ -96,6 +96,7 @@ rm src/*.class pushd out > /dev/null mkdir classes javac -d classes android/opengl/EGL14.java \ + android/opengl/EGLExt.java \ com/google/android/gles_jni/GLImpl.java \ javax/microedition/khronos/opengles/GL10.java \ javax/microedition/khronos/opengles/GL10Ext.java \ @@ -154,7 +155,7 @@ do compareGenerated ../../../../base/opengl/java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x done -for x in EGL14 GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30 +for x in EGL14 EGLExt GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30 do compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java compareGenerated ../../../../base/core/jni generated/C android_opengl_${x}.cpp diff --git a/opengl/tools/glgen/specs/egl/EGL14.spec b/opengl/tools/glgen/specs/egl/EGL14.spec index aef0bcb..828e114 100644 --- a/opengl/tools/glgen/specs/egl/EGL14.spec +++ b/opengl/tools/glgen/specs/egl/EGL14.spec @@ -31,4 +31,3 @@ EGLBoolean eglWaitGL ( void ) EGLBoolean eglWaitNative ( EGLint engine ) EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface ) EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target ) -EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time ) diff --git a/opengl/tools/glgen/specs/egl/EGLExt.spec b/opengl/tools/glgen/specs/egl/EGLExt.spec new file mode 100644 index 0000000..e4fc337 --- /dev/null +++ b/opengl/tools/glgen/specs/egl/EGLExt.spec @@ -0,0 +1 @@ +EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time ) diff --git a/opengl/tools/glgen/src/GenerateEGL.java b/opengl/tools/glgen/src/GenerateEGL.java index aaa748c..2ef3970 100644 --- a/opengl/tools/glgen/src/GenerateEGL.java +++ b/opengl/tools/glgen/src/GenerateEGL.java @@ -84,26 +84,26 @@ public class GenerateEGL { ParameterChecker checker = new ParameterChecker(checksReader); - BufferedReader specReader = - new BufferedReader(new FileReader("specs/egl/EGL14.spec")); - - String egljFilename = "android/opengl/EGL14.java"; - String eglcFilename = "android_opengl_EGL14.cpp"; - PrintStream egljStream = - new PrintStream(new FileOutputStream("out/" + egljFilename)); - PrintStream eglcStream = - new PrintStream(new FileOutputStream("out/" + eglcFilename)); - egljStream.println("/*"); - eglcStream.println("/*"); - copy("stubs/egl/EGL14Header.java-if", egljStream); - copy("stubs/egl/EGL14cHeader.cpp", eglcStream); - EGLCodeEmitter emitter = new EGLCodeEmitter( - "android/opengl/EGL14", - checker, egljStream, eglcStream); - emit(emitter, specReader, egljStream, eglcStream); - emitter.emitNativeRegistration("register_android_opengl_jni_EGL14"); - egljStream.println("}"); - egljStream.close(); - eglcStream.close(); + for(String suffix: new String[] {"EGL14", "EGLExt"}) { + BufferedReader specReader = new BufferedReader(new FileReader( + "specs/egl/" + suffix + ".spec")); + String egljFilename = "android/opengl/" + suffix + ".java"; + String eglcFilename = "android_opengl_" + suffix + ".cpp"; + PrintStream egljStream = + new PrintStream(new FileOutputStream("out/" + egljFilename)); + PrintStream eglcStream = + new PrintStream(new FileOutputStream("out/" + eglcFilename)); + copy("stubs/egl/" + suffix + "Header.java-if", egljStream); + copy("stubs/egl/" + suffix + "cHeader.cpp", eglcStream); + EGLCodeEmitter emitter = new EGLCodeEmitter( + "android/opengl/" + suffix, + checker, egljStream, eglcStream); + emit(emitter, specReader, egljStream, eglcStream); + emitter.emitNativeRegistration( + "register_android_opengl_jni_" + suffix); + egljStream.println("}"); + egljStream.close(); + eglcStream.close(); + } } } diff --git a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if index 0c29d5c..f3bf220 100644 --- a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if +++ b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if @@ -1,4 +1,4 @@ -** +/* ** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp index 5fda9f8..54de1e7 100644 --- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp +++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp @@ -1,3 +1,4 @@ +/* ** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if new file mode 100644 index 0000000..a5a8968 --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if @@ -0,0 +1,36 @@ +/* +** Copyright 2013, 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. +*/ + +// This source file is automatically generated + +package android.opengl; + +/** + * EGL Extensions + */ +public class EGLExt { + + // EGL_KHR_create_context + public static final int EGL_CONTEXT_MAJOR_VERSION_KHR = 0x3098; + public static final int EGL_CONTEXT_MINOR_VERSION_KHR = 0x30FB; + public static final int EGL_CONTEXT_FLAGS_KHR = 0x30FC; + public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040; + + native private static void _nativeClassInit(); + static { + _nativeClassInit(); + } + diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp new file mode 100644 index 0000000..5e1ffa1 --- /dev/null +++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp @@ -0,0 +1,133 @@ +/* +** Copyright 2013, 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. +*/ + +// This source file is automatically generated + +#include "jni.h" +#include "JNIHelp.h" +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_view_Surface.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> +#include <utils/misc.h> + +#include <assert.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <gui/Surface.h> +#include <gui/GLConsumer.h> +#include <gui/Surface.h> + +#include <ui/ANativeObjectBase.h> + +static int initialized = 0; + +static jclass egldisplayClass; +static jclass eglcontextClass; +static jclass eglsurfaceClass; +static jclass eglconfigClass; + +static jmethodID egldisplayGetHandleID; +static jmethodID eglcontextGetHandleID; +static jmethodID eglsurfaceGetHandleID; +static jmethodID eglconfigGetHandleID; + +static jmethodID egldisplayConstructor; +static jmethodID eglcontextConstructor; +static jmethodID eglsurfaceConstructor; +static jmethodID eglconfigConstructor; + +static jobject eglNoContextObject; +static jobject eglNoDisplayObject; +static jobject eglNoSurfaceObject; + + + +/* Cache method IDs each time the class is loaded. */ + +static void +nativeClassInit(JNIEnv *_env, jclass glImplClass) +{ + jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay"); + egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal); + jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext"); + eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal); + jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface"); + eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal); + jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig"); + eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal); + + egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I"); + eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I"); + eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I"); + eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I"); + + + egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V"); + eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V"); + eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V"); + eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V"); + + jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT); + eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject); + jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY); + eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject); + jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE); + eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject); + + + jclass eglClass = _env->FindClass("android/opengl/EGL14"); + jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;"); + _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject); + + jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;"); + _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject); + + jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;"); + _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject); +} + +static void * +fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) { + if (obj == NULL){ + jniThrowException(_env, "java/lang/IllegalArgumentException", + "Object is set to null."); + } + + return (void*) (_env->CallIntMethod(obj, mid)); +} + +static jobject +toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) { + if (cls == eglcontextClass && + (EGLContext)handle == EGL_NO_CONTEXT) { + return eglNoContextObject; + } + + if (cls == egldisplayClass && + (EGLDisplay)handle == EGL_NO_DISPLAY) { + return eglNoDisplayObject; + } + + if (cls == eglsurfaceClass && + (EGLSurface)handle == EGL_NO_SURFACE) { + return eglNoSurfaceObject; + } + + return _env->NewObject(cls, con, (jint)handle); +} + +// -------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index f36e1bf..ec296d3 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -14,7 +14,6 @@ LOCAL_SRC_FILES:= \ SurfaceFlingerConsumer.cpp \ SurfaceTextureLayer.cpp \ Transform.cpp \ - DisplayHardware/BufferQueueInterposer.cpp \ DisplayHardware/FramebufferSurface.cpp \ DisplayHardware/HWComposer.cpp \ DisplayHardware/PowerHAL.cpp \ diff --git a/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.cpp b/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.cpp deleted file mode 100644 index 91f9aea..0000000 --- a/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#undef LOG_TAG -#define LOG_TAG "BQInterposer" -//#define LOG_NDEBUG 0 - -#include "BufferQueueInterposer.h" - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -#define BQI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BQI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BQI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BQI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BQI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) - -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { - static volatile int32_t globalCounter = 0; - return android_atomic_inc(&globalCounter); -} - -BufferQueueInterposer::BufferQueueInterposer( - const sp<IGraphicBufferProducer>& sink, const String8& name) -: mSink(sink), - mName(name), - mAcquired(false) -{ - BQI_LOGV("BufferQueueInterposer sink=%p", sink.get()); -} - -BufferQueueInterposer::~BufferQueueInterposer() { - Mutex::Autolock lock(mMutex); - flushQueuedBuffersLocked(); - BQI_LOGV("~BufferQueueInterposer"); -} - -status_t BufferQueueInterposer::requestBuffer(int slot, - sp<GraphicBuffer>* outBuf) { - BQI_LOGV("requestBuffer slot=%d", slot); - Mutex::Autolock lock(mMutex); - - if (size_t(slot) >= mBuffers.size()) { - size_t size = mBuffers.size(); - mBuffers.insertAt(size, size - slot + 1); - } - sp<GraphicBuffer>& buf = mBuffers.editItemAt(slot); - - status_t result = mSink->requestBuffer(slot, &buf); - *outBuf = buf; - return result; -} - -status_t BufferQueueInterposer::setBufferCount(int bufferCount) { - BQI_LOGV("setBufferCount count=%d", bufferCount); - Mutex::Autolock lock(mMutex); - - bufferCount += 1; - - status_t result = flushQueuedBuffersLocked(); - if (result != NO_ERROR) - return result; - - result = mSink->setBufferCount(bufferCount); - if (result != NO_ERROR) - return result; - - for (size_t i = 0; i < mBuffers.size(); i++) - mBuffers.editItemAt(i).clear(); - ssize_t n = mBuffers.resize(bufferCount); - result = (n < 0) ? n : result; - - return result; -} - -status_t BufferQueueInterposer::dequeueBuffer(int* slot, sp<Fence>* fence, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { - BQI_LOGV("dequeueBuffer %ux%u fmt=%u usage=%#x", w, h, format, usage); - return mSink->dequeueBuffer(slot, fence, w, h, format, usage); -} - -status_t BufferQueueInterposer::queueBuffer(int slot, - const QueueBufferInput& input, QueueBufferOutput* output) { - BQI_LOGV("queueBuffer slot=%d", slot); - Mutex::Autolock lock(mMutex); - mQueue.push(QueuedBuffer(slot, input)); - *output = mQueueBufferOutput; - return NO_ERROR; -} - -void BufferQueueInterposer::cancelBuffer(int slot, const sp<Fence>& fence) { - BQI_LOGV("cancelBuffer slot=%d", slot); - mSink->cancelBuffer(slot, fence); -} - -int BufferQueueInterposer::query(int what, int* value) { - BQI_LOGV("query what=%d", what); - return mSink->query(what, value); -} - -status_t BufferQueueInterposer::setSynchronousMode(bool enabled) { - BQI_LOGV("setSynchronousMode %s", enabled ? "true" : "false"); - return mSink->setSynchronousMode(enabled); -} - -status_t BufferQueueInterposer::connect(int api, QueueBufferOutput* output) { - BQI_LOGV("connect api=%d", api); - Mutex::Autolock lock(mMutex); - status_t result = mSink->connect(api, &mQueueBufferOutput); - if (result == NO_ERROR) { - *output = mQueueBufferOutput; - } - return result; -} - -status_t BufferQueueInterposer::disconnect(int api) { - BQI_LOGV("disconnect: api=%d", api); - Mutex::Autolock lock(mMutex); - flushQueuedBuffersLocked(); - return mSink->disconnect(api); -} - -status_t BufferQueueInterposer::pullEmptyBuffer() { - status_t result; - - int slot; - sp<Fence> fence; - result = dequeueBuffer(&slot, &fence, 0, 0, 0, 0); - if (result == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { - sp<GraphicBuffer> buffer; - result = requestBuffer(slot, &buffer); - } else if (result != NO_ERROR) { - return result; - } - - uint32_t w, h, transformHint, numPendingBuffers; - mQueueBufferOutput.deflate(&w, &h, &transformHint, &numPendingBuffers); - - IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(w, h), - NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, fence); - IGraphicBufferProducer::QueueBufferOutput qbo; - result = queueBuffer(slot, qbi, &qbo); - if (result != NO_ERROR) - return result; - - return NO_ERROR; -} - -status_t BufferQueueInterposer::acquireBuffer(sp<GraphicBuffer>* buf, - sp<Fence>* fence) { - Mutex::Autolock lock(mMutex); - if (mQueue.empty()) { - BQI_LOGV("acquireBuffer: no buffers available"); - return NO_BUFFER_AVAILABLE; - } - if (mAcquired) { - BQI_LOGE("acquireBuffer: buffer already acquired"); - return BUFFER_ALREADY_ACQUIRED; - } - BQI_LOGV("acquireBuffer: acquiring slot %d", mQueue[0].slot); - - *buf = mBuffers[mQueue[0].slot]; - *fence = mQueue[0].fence; - mAcquired = true; - return NO_ERROR; -} - -status_t BufferQueueInterposer::releaseBuffer(const sp<Fence>& fence) { - Mutex::Autolock lock(mMutex); - if (!mAcquired) { - BQI_LOGE("releaseBuffer: releasing a non-acquired buffer"); - return BUFFER_NOT_ACQUIRED; - } - BQI_LOGV("releaseBuffer: releasing slot %d to sink", mQueue[0].slot); - - const QueuedBuffer& b = mQueue[0]; - status_t result = mSink->queueBuffer(b.slot, - QueueBufferInput(b.timestamp, b.crop, b.scalingMode, - b.transform, b.fence), - &mQueueBufferOutput); - mQueue.removeAt(0); - mAcquired = false; - - return result; -} - -status_t BufferQueueInterposer::flushQueuedBuffersLocked() { - if (mAcquired) { - BQI_LOGE("flushQueuedBuffersLocked: buffer acquired, can't flush"); - return INVALID_OPERATION; - } - - status_t result = NO_ERROR; - for (size_t i = 0; i < mQueue.size(); i++) { - const QueuedBuffer& b = mQueue[i]; - BQI_LOGV("flushing queued slot %d to sink", b.slot); - status_t err = mSink->queueBuffer(b.slot, - QueueBufferInput(b.timestamp, b.crop, b.scalingMode, - b.transform, b.fence), - &mQueueBufferOutput); - if (err != NO_ERROR && result == NO_ERROR) // latch first error - result = err; - } - mQueue.clear(); - return result; -} - -// --------------------------------------------------------------------------- -} // namespace android -// --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.h b/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.h deleted file mode 100644 index 7e84e97..0000000 --- a/services/surfaceflinger/DisplayHardware/BufferQueueInterposer.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef ANDROID_SF_BUFFERQUEUEINTERPOSER_H -#define ANDROID_SF_BUFFERQUEUEINTERPOSER_H - -#include <gui/IGraphicBufferProducer.h> -#include <utils/Mutex.h> -#include <utils/Vector.h> - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -// BufferQueueInterposers introduce an extra stage between a buffer producer -// (the source) and a buffer consumer (the sink), which communicate via the -// IGraphicBufferProducer interface. It is designed to be as transparent as -// possible to both endpoints, so that they can work the same whether an -// interposer is present or not. -// -// When the interpose is present, the source queues buffers to the -// IGraphicBufferProducer implemented by BufferQueueInterposer. A client of -// the BufferQueueInterposer can acquire each buffer in turn and read or -// modify it, releasing the buffer when finished. When the buffer is released, -// the BufferQueueInterposer queues it to the original IGraphicBufferProducer -// interface representing the sink. -// -// A BufferQueueInterposer can be used to do additional rendering to a buffer -// before it is consumed -- essentially pipelining two producers. As an -// example, SurfaceFlinger uses this to implement mixed GLES and HWC -// compositing to the same buffer for virtual displays. If it used two separate -// buffer queues, then in GLES-only or mixed GLES+HWC compositing, the HWC -// would have to copy the GLES output buffer to the HWC output buffer, using -// more bandwidth than having HWC do additional composition "in place" on the -// GLES output buffer. -// -// The goal for this class is to be usable in a variety of situations and be -// part of libgui. But both the interface and implementation need some -// iteration before then, so for now it should only be used by -// VirtualDisplaySurface, which is why it's currently in SurfaceFlinger. -// -// Some of the problems that still need to be solved are: -// -// - Refactor the interposer interface along with BufferQueue and ConsumerBase, -// so that there is a common interface for the consumer end of a queue. The -// existing interfaces have some problems when the implementation isn't the -// final consumer. -// -// - The client of the interposer may need one or more buffers in addition to -// those used by the source and sink. IGraphicBufferProducer will probably -// need to change to allow the producer to specify how many buffers it needs -// to dequeue at a time, and then the interposer can add its requirements to -// those of the source. -// -// - Abandoning, disconnecting, and connecting need to pass through somehow. -// There needs to be a way to tell the interposer client to release its -// buffer immediately so it can be queued/released, e.g. when the source -// calls disconnect(). -// -// - Right now the source->BQI queue is synchronous even if the BQI->sink queue -// is asynchronous. Need to figure out how asynchronous should behave and -// implement that. - -class BufferQueueInterposer : public BnGraphicBufferProducer { -public: - BufferQueueInterposer(const sp<IGraphicBufferProducer>& sink, - const String8& name); - - // - // IGraphicBufferProducer interface - // - virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* outBuf); - virtual status_t setBufferCount(int bufferCount); - virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, - uint32_t w, uint32_t h, uint32_t format, uint32_t usage); - virtual status_t queueBuffer(int slot, - const QueueBufferInput& input, QueueBufferOutput* output); - virtual void cancelBuffer(int slot, const sp<Fence>& fence); - virtual int query(int what, int* value); - virtual status_t setSynchronousMode(bool enabled); - virtual status_t connect(int api, QueueBufferOutput* output); - virtual status_t disconnect(int api); - - // - // Interposer interface - // - - enum { - NO_BUFFER_AVAILABLE = 2, // matches BufferQueue - BUFFER_NOT_ACQUIRED, - BUFFER_ALREADY_ACQUIRED, - }; - - // Acquire the oldest queued buffer. If no buffers are pending, returns - // NO_BUFFER_AVAILABLE. If a buffer is currently acquired, returns - // BUFFER_ALREADY_ACQUIRED. - status_t acquireBuffer(sp<GraphicBuffer>* buf, sp<Fence>* fence); - - // Release the currently acquired buffer, queueing it to the sink. If the - // current buffer hasn't been acquired, returns BUFFER_NOT_ACQUIRED. - status_t releaseBuffer(const sp<Fence>& fence); - - // pullEmptyBuffer dequeues a buffer from the sink, then immediately - // queues it to the interposer. This makes a buffer available for the - // client to acquire even if the source hasn't queued one. - status_t pullEmptyBuffer(); - -private: - struct QueuedBuffer { - QueuedBuffer(): slot(-1) {} - QueuedBuffer(int slot, const QueueBufferInput& qbi): slot(slot) { - qbi.deflate(×tamp, &crop, &scalingMode, &transform, &fence); - } - int slot; - int64_t timestamp; - Rect crop; - int scalingMode; - uint32_t transform; - sp<Fence> fence; - }; - - virtual ~BufferQueueInterposer(); - status_t flushQueuedBuffersLocked(); - - const sp<IGraphicBufferProducer> mSink; - String8 mName; - - Mutex mMutex; - Vector<sp<GraphicBuffer> > mBuffers; - Vector<QueuedBuffer> mQueue; - bool mAcquired; - QueueBufferOutput mQueueBufferOutput; -}; - -// --------------------------------------------------------------------------- -} // namespace android -// --------------------------------------------------------------------------- - -#endif // ANDROID_SF_BUFFERQUEUEINTERPOSER_H diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 3f00f07..f0f7463 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -50,6 +50,10 @@ namespace android { +// This is not a real HWC version. It's used for in-development features that +// haven't been committed to a specific real HWC version. +#define HWC_DEVICE_API_VERSION_1_EXP HARDWARE_DEVICE_API_VERSION_2(1, 0xFF, HWC_HEADER_VERSION) + #define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION #define NUM_PHYSICAL_DISPLAYS HWC_NUM_DISPLAY_TYPES @@ -152,8 +156,8 @@ HWComposer::HWComposer( // the number of displays we actually have depends on the // hw composer version - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { - // 1.2 adds support for virtual displays + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) { + // 1.?? adds support for virtual displays mNumDisplays = MAX_DISPLAYS; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // 1.1 adds support for multiple displays @@ -581,7 +585,7 @@ status_t HWComposer::prepare() { } mLists[i] = disp.list; if (mLists[i]) { - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) { mLists[i]->outbuf = NULL; mLists[i]->outbufAcquireFenceFd = -1; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 7e14d95..2838b23 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -15,7 +15,9 @@ */ #include "VirtualDisplaySurface.h" -#include "HWComposer.h" + +#include <cutils/log.h> +#include <gui/IGraphicBufferProducer.h> // --------------------------------------------------------------------------- namespace android { @@ -23,28 +25,16 @@ namespace android { VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, const sp<IGraphicBufferProducer>& sink, const String8& name) -: mHwc(hwc), - mDisplayId(dispId), - mName(name) +: mSink(sink) { - if (mDisplayId >= 0) { - mInterposer = new BufferQueueInterposer(sink, name); - mSourceProducer = mInterposer; - } else { - mSourceProducer = sink; - } + LOG_ALWAYS_FATAL_IF(dispId >= 0); } VirtualDisplaySurface::~VirtualDisplaySurface() { - if (mAcquiredBuffer != NULL) { - status_t result = mInterposer->releaseBuffer(Fence::NO_FENCE); - ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " - "failed to release buffer: %d", mName.string(), result); - } } sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const { - return mSourceProducer; + return mSink; } status_t VirtualDisplaySurface::compositionComplete() { @@ -52,60 +42,10 @@ status_t VirtualDisplaySurface::compositionComplete() { } status_t VirtualDisplaySurface::advanceFrame() { - if (mInterposer == NULL) - return NO_ERROR; - - Mutex::Autolock lock(mMutex); - status_t result = NO_ERROR; - - if (mAcquiredBuffer != NULL) { - ALOGE("VirtualDisplaySurface \"%s\": " - "advanceFrame called twice without onFrameCommitted", - mName.string()); - return INVALID_OPERATION; - } - - sp<Fence> fence; - result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence); - if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) { - result = mInterposer->pullEmptyBuffer(); - if (result != NO_ERROR) - return result; - result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence); - } - if (result != NO_ERROR) - return result; - - result = mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer); - if (result == NO_ERROR) { - result = mHwc.setOutputBuffer(mDisplayId, fence, mAcquiredBuffer); - } - return result; + return NO_ERROR; } void VirtualDisplaySurface::onFrameCommitted() { - if (mInterposer == NULL) - return; - - Mutex::Autolock lock(mMutex); - if (mAcquiredBuffer != NULL) { - // fbFence signals when reads from the framebuffer are finished - // outFence signals when writes to the output buffer are finished - // It's unlikely that there will be an implementation where fbFence - // signals after outFence (in fact they'll typically be the same - // sync_pt), but just to be pedantic we merge them so the sink will - // be sure to wait until both are complete. - sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId); - sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId); - sp<Fence> fence = Fence::merge( - String8::format("HWC done: %.21s", mName.string()), - fbFence, outFence); - - status_t result = mInterposer->releaseBuffer(fence); - ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " - "failed to release buffer: %d", mName.string(), result); - mAcquiredBuffer.clear(); - } } void VirtualDisplaySurface::dump(String8& result) const { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 0706e75..f321795 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -17,7 +17,6 @@ #ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H #define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H -#include "BufferQueueInterposer.h" #include "DisplaySurface.h" // --------------------------------------------------------------------------- @@ -26,33 +25,8 @@ namespace android { class HWComposer; -/* This DisplaySurface implementation uses a BufferQueueInterposer to pass - * partially- or fully-composited buffers from the OpenGL ES driver to - * HWComposer to use as the output buffer for virtual displays. Allowing HWC - * to compose into the same buffer that contains GLES results saves bandwidth - * compared to having two separate BufferQueues for frames with at least some - * GLES composition. - * - * The alternative would be to have two complete BufferQueues, one from GLES - * to HWC and one from HWC to the virtual display sink (e.g. video encoder). - * For GLES-only frames, the same bandwidth saving could be achieved if buffers - * could be acquired from the GLES->HWC queue and inserted into the HWC->sink - * queue. That would be complicated and doesn't help the mixed GLES+HWC case. - * - * On frames with no GLES composition, the VirtualDisplaySurface dequeues a - * buffer directly from the sink IGraphicBufferProducer and passes it to HWC, - * bypassing the GLES driver. This is only guaranteed to work if - * eglSwapBuffers doesn't immediately dequeue a buffer for the next frame, - * since we can't rely on being able to dequeue more than one buffer at a time. - * - * This class also has a passthrough mode, where it doesn't use a - * BufferQueueInterposer and never sends buffers to HWC. Instead, OpenGL ES - * output buffers are queued directly to the virtual display sink; this class - * is inactive after construction. This mode is used when the HWC doesn't - * support compositing for virtual displays. - * - * TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy - * dequeBuffers; we've wanted to require that for other reasons anyway. +/* This DisplaySurface implementation is a stub used for developing HWC + * virtual display support. It is currently just a passthrough. */ class VirtualDisplaySurface : public DisplaySurface { public: @@ -70,19 +44,7 @@ public: private: virtual ~VirtualDisplaySurface(); - // immutable after construction - HWComposer& mHwc; - int32_t mDisplayId; - String8 mName; - - // with HWC support, both of these point to the same object. - // otherwise, mInterposer is NULL and mSourceProducer is the sink. - sp<BufferQueueInterposer> mInterposer; - sp<IGraphicBufferProducer> mSourceProducer; - - // mutable, must be synchronized with mMutex - Mutex mMutex; - sp<GraphicBuffer> mAcquiredBuffer; + sp<IGraphicBufferProducer> mSink; }; // --------------------------------------------------------------------------- |